Files
Dwinzo_Demo/app/src/components/layout/sidebarRight/properties/SelectedFloorProperties.tsx

256 lines
9.5 KiB
TypeScript

import { useEffect, useState } from "react";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import InputToggle from "../../../ui/inputs/InputToggle";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { useVersionContext } from "../../../../modules/builder/version/versionContext";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../functions/getUserData";
import { useSocketStore } from "../../../../store/builder/store";
import { materials } from "./FloorProperties";
import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
const SelectedFloorProperties = () => {
const [depth, setDepth] = useState("");
const [isBeveled, setIsBeveled] = useState(false);
const [bevelStrength, setBevelStrength] = useState("");
const { selectedFloor } = useBuilderStore();
const { floorStore } = useSceneContext();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { socket } = useSocketStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { getFloorById, updateFloor } = floorStore();
const [activeSurface, setActiveSurface] = useState<"top" | "side">("top");
const floor = selectedFloor ? getFloorById(selectedFloor.userData.floorUuid) : null;
useEffect(() => {
if (floor) {
setDepth(floor.floorDepth.toString());
setIsBeveled(floor.isBeveled);
setBevelStrength(floor.bevelStrength.toString());
}
}, [floor]);
const handleDepthChange = (val: string) => {
setDepth(val);
const parsed = parseFloat(val);
if (!isNaN(parsed) && floor) {
const updatedFloor = updateFloor(floor.floorUuid, { floorDepth: parsed });
if (projectId) {
if (!socket?.connected) {
// API
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
}
}
};
const handleBevelChange = (val: string) => {
setBevelStrength(val);
const parsed = parseFloat(val);
if (!isNaN(parsed) && floor) {
const updatedFloor = updateFloor(floor.floorUuid, { bevelStrength: parsed });
if (projectId) {
if (!socket?.connected) {
// API
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
}
}
};
const handleIsBeveledToggle = () => {
setIsBeveled(!isBeveled);
if (!floor) return;
const updatedFloor = updateFloor(floor.floorUuid, { isBeveled: !floor.isBeveled });
if (projectId) {
if (!socket?.connected) {
// API
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
}
};
const handleSelectMaterial = (material: { textureId: string; textureName: string }) => {
if (!floor) return;
const key = activeSurface === "top" ? "topMaterial" : "sideMaterial";
const updatedFloor = updateFloor(floor.floorUuid, { [key]: material.textureId });
if (projectId) {
if (!socket?.connected) {
// API
upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
} else {
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
}
};
if (!floor) return null;
const selectedMaterials = {
top: materials.find((m) => m.textureId === floor.topMaterial) ?? materials[0],
side: materials.find((m) => m.textureId === floor.sideMaterial) ?? materials[0],
};
return (
<div className="wall-properties-container">
<section className="wall-properties-section">
<div className="header">Floor</div>
<div className="wall-properties">
<InputWithDropDown
label="Depth"
value={depth}
min={0.1}
max={10}
step={0.1}
onChange={handleDepthChange}
/>
<InputToggle
label="Beveled"
inputKey="isBeveled"
value={isBeveled}
onClick={handleIsBeveledToggle}
/>
<InputWithDropDown
label="Bevel Strength"
value={bevelStrength}
min={1}
max={10}
step={1}
onChange={handleBevelChange}
/>
</div>
</section>
<section>
<div className="header-wrapper">
<div className="header">Materials</div>
</div>
<div className="material-preview">
<div className="sides-wrapper">
{(["top", "side"] as const).map((surface) => (
<button
key={surface}
className={`side-wrapper ${activeSurface === surface ? "active" : ""}`}
onClick={() => setActiveSurface(surface)}
>
<div className="label">{surface === "top" ? "Top" : "Side"}</div>
<div className="texture-image">
<img
draggable={false}
src={selectedMaterials[surface].texture}
alt={selectedMaterials[surface].textureName}
/>
</div>
</button>
))}
</div>
<div className="preview">
<img
draggable={false}
src={selectedMaterials[activeSurface].texture}
alt={selectedMaterials[activeSurface].textureName}
/>
</div>
</div>
<div className="materials">
<div className="material-container">
{materials.map((material, index) => {
const isSelected = selectedMaterials[activeSurface].textureId === material.textureId;
return (
<button
className={`material-wrapper ${isSelected ? "selectedMaterial" : ""}`}
key={`${material.textureName}_${index}`}
onClick={() => handleSelectMaterial(material)}
>
<div className="material-property">
<div className="material-image">
<img
draggable={false}
src={material.texture}
alt={material.textureName}
/>
</div>
<div className="material-name">{material.textureName}</div>
</div>
</button>
);
})}
</div>
</div>
</section>
</div>
);
};
export default SelectedFloorProperties;