Refactor code structure for improved readability and maintainability

This commit is contained in:
2025-05-13 15:37:06 +05:30
parent 4939c19c12
commit d66384c7a5
24 changed files with 328 additions and 417 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -1,5 +1,5 @@
import React, { useState } from "react";
import orgImg from "../../../assets/orgTemp.png";
import orgImg from "../../../assets/image/orgTemp.png";
import { useActiveUsers, useCamMode } from "../../../store/store";
import { ActiveUser } from "../../../types/users";
import CollaborationPopup from "../../templates/CollaborationPopup";

View File

@@ -38,450 +38,360 @@ import {
useFloatingWidget,
} from "../../store/visualization/useDroppedObjectsStore";
const Tools: React.FC = () => {
const { templates } = useTemplateStore();
const { activeSubTool, setActiveSubTool } = useActiveSubTool();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const { setToggleUI } = useToggleStore();
// Utility component
const ToolButton = ({ icon: Icon, active, onClick, tooltip }: any) => (
<button className={`tool-button ${active ? "active" : ""}`} onClick={onClick}>
<div className="tooltip">{tooltip}</div>
<Icon isActive={active} />
</button>
);
const dropdownRef = useRef<HTMLDivElement>(null);
const [openDrop, setOpenDrop] = useState(false);
const { visualizationSocket } = useSocketStore();
const Tools: React.FC = () => {
const { activeModule } = useModuleStore();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { addTemplate } = useTemplateStore();
const {
activeTool,
setActiveTool,
setToolMode,
setAddAction,
setDeleteTool,
setDeletePointOrLine,
setTransformMode,
} = useStoreHooks();
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
const { setSelectedWallItem } = useSelectedWallItem();
const { setRefTextUpdate } = useRefTextUpdate();
const { setToggleUI } = useToggleStore();
const { setToggleView, toggleView } = useToggleView();
const { addTemplate, templates } = useTemplateStore();
const { selectedZone } = useSelectedZoneStore();
const { floatingWidget } = useFloatingWidget();
const { widgets3D } = use3DWidget();
const { visualizationSocket } = useSocketStore();
// wall options
const { toggleView, setToggleView } = useToggleView();
const { setDeleteTool } = useDeleteTool();
const { setAddAction } = useAddAction();
const { setSelectedWallItem } = useSelectedWallItem();
const dropdownRef = useRef<HTMLButtonElement>(null);
const [openDrop, setOpenDrop] = useState(false);
const { setTransformMode } = useTransformMode();
const { setDeletePointOrLine } = useDeletePointOrLine();
const { setToolMode } = useToolMode();
const { activeTool, setActiveTool } = useActiveTool();
const { setRefTextUpdate } = useRefTextUpdate();
// Reset activeTool whenever activeModule changes
// 1. Set UI toggles on initial render
useEffect(() => {
setToggleUI(
localStorage.getItem("navBarUiLeft")
? localStorage.getItem("navBarUiLeft") === "true"
: true,
localStorage.getItem("navBarUiRight")
? localStorage.getItem("navBarUiRight") === "true"
: true
localStorage.getItem("navBarUiLeft") !== "false",
localStorage.getItem("navBarUiRight") !== "false"
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 2. Update tool based on subtool and module
useEffect(() => {
setActiveTool(activeSubTool);
setActiveSubTool(activeSubTool);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeModule]);
const toggleSwitch = () => {
if (toggleThreeD) {
setSelectedWallItem(null);
setDeleteTool(false);
setAddAction(null);
setToggleView(true);
// localStorage.setItem("navBarUi", JSON.stringify(!toggleThreeD));
} else {
setToggleView(false);
}
setToggleUI(
localStorage.getItem("navBarUiLeft")
? localStorage.getItem("navBarUiLeft") === "true"
: true,
localStorage.getItem("navBarUiRight")
? localStorage.getItem("navBarUiRight") === "true"
: true
);
setToggleThreeD(!toggleThreeD);
setActiveSubTool("cursor");
setActiveTool("cursor");
};
// 3. Update tools behavior based on selected tool and view mode
useEffect(() => {
const handleOutsideClick = (event: MouseEvent) => {
resetTools();
updateToolBehavior(activeTool, toggleView);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeTool, toggleView]);
// 4. Dropdown auto-close
useEffect(() => {
const handleClickOutside = (e: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
!dropdownRef.current.contains(e.target as Node)
) {
setOpenDrop(false); // Close the dropdown
setOpenDrop(false);
}
};
document.addEventListener("mousedown", handleOutsideClick);
return () => {
document.removeEventListener("mousedown", handleOutsideClick);
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
useEffect(() => {
if (!toggleThreeD) {
setToggleUI(false, false);
}
}, [toggleThreeD]);
useEffect(() => {
const resetTools = () => {
setToolMode(null);
setDeleteTool(false);
setAddAction(null);
setTransformMode(null);
setDeletePointOrLine(false);
setRefTextUpdate((prevUpdate) => prevUpdate - 1);
setRefTextUpdate((prev) => prev - 1);
};
switch (activeTool) {
const updateToolBehavior = (tool: string, is2D: boolean) => {
switch (tool) {
case "cursor":
if (toggleView) {
setToolMode("move");
} else {
setTransformMode("translate");
}
is2D ? setToolMode("move") : setTransformMode("translate");
break;
case "Rotate":
if (!toggleView) {
setTransformMode("rotate");
}
if (!is2D) setTransformMode("rotate");
break;
case "Scale":
if (!toggleView) {
setTransformMode("scale");
}
if (!is2D) setTransformMode("scale");
break;
case "draw-wall":
if (toggleView) {
setToolMode("Wall");
}
is2D && setToolMode("Wall");
break;
case "draw-aisle":
if (toggleView) {
setToolMode("Aisle");
}
is2D && setToolMode("Aisle");
break;
case "draw-zone":
if (toggleView) {
setToolMode("Zone");
}
is2D && setToolMode("Zone");
break;
case "draw-floor":
if (toggleView) {
setToolMode("Floor");
}
is2D && setToolMode("Floor");
break;
case "measure":
setToolMode("MeasurementScale");
break;
case "Add pillar":
if (!toggleView) {
setAddAction("pillar");
}
if (!is2D) setAddAction("pillar");
break;
case "delete":
if (toggleView) {
setDeletePointOrLine(true);
} else {
setDeleteTool(true);
}
break;
default:
is2D ? setDeletePointOrLine(true) : setDeleteTool(true);
break;
}
};
setActiveTool(activeTool);
}, [activeTool, toggleView]);
const toggle2D3D = () => {
setToggleThreeD(!toggleThreeD);
setToggleUI(
localStorage.getItem("navBarUiLeft") !== "false",
localStorage.getItem("navBarUiRight") !== "false"
);
setSelectedWallItem(null);
setActiveSubTool("cursor");
setActiveTool("cursor");
setToggleView(!toggleThreeD);
};
if (isPlaying && activeModule !== "simulation") {
return (
<button className="exitPlay" onClick={() => setIsPlaying(false)}>
X
</button>
);
}
const renderBuilderTools = () => (
<>
{!toggleThreeD && (
<div className="draw-tools">
<ToolButton
icon={WallIcon}
tooltip="draw wall (q)"
active={activeTool === "draw-wall"}
onClick={() => setActiveTool("draw-wall")}
/>
<ToolButton
icon={ZoneIcon}
tooltip="draw zone (e)"
active={activeTool === "draw-zone"}
onClick={() => setActiveTool("draw-zone")}
/>
<ToolButton
icon={AsileIcon}
tooltip="draw aisle (r)"
active={activeTool === "draw-aisle"}
onClick={() => setActiveTool("draw-aisle")}
/>
<ToolButton
icon={FloorIcon}
tooltip="draw floor (t)"
active={activeTool === "draw-floor"}
onClick={() => setActiveTool("draw-floor")}
/>
</div>
)}
<div className="draw-tools">
<ToolButton
icon={MeasureToolIcon}
tooltip="measure scale (m)"
active={activeTool === "measure"}
onClick={() => setActiveTool("measure")}
/>
</div>
</>
);
const renderSimulationTools = () => (
<div className="draw-tools">
<ToolButton
icon={PenIcon}
tooltip="pen"
active={activeTool === "pen"}
onClick={() => setActiveTool("pen")}
/>
</div>
);
const renderVisualizationTools = () => (
<div className="draw-tools">
<ToolButton
icon={SaveTemplateIcon}
tooltip="save template"
active={false}
onClick={() =>
handleSaveTemplate({
addTemplate,
floatingWidget,
widgets3D,
selectedZone,
templates,
visualizationSocket,
})
}
/>
</div>
);
const renderModeSwitcher = () => (
<button
className={`toggle-threed-button${toggleThreeD ? " toggled" : ""}`}
onClick={toggle2D3D}
>
<div className="tooltip">toggle view (tab)</div>
<div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>2d</div>
<div className={`toggle-option${toggleThreeD ? " active" : ""}`}>3d</div>
</button>
);
const getIconByTool = (tool: string) => {
switch (tool) {
case "cursor":
return CursorIcon;
case "free-hand":
return FreeMoveIcon;
case "delete":
return DeleteIcon;
default:
return CursorIcon;
}
};
const getTooltipShortcut = (tool: string) => {
switch (tool) {
case "cursor":
return "v";
case "free-hand":
return "h";
case "delete":
return "x";
default:
return "";
}
};
const getIconComponent = (option: string) => {
switch (option) {
case "cursor":
return <CursorIcon isActive={false} />;
case "free-hand":
return <FreeMoveIcon isActive={false} />;
case "delete":
return <DeleteIcon isActive={false} />;
default:
return null;
}
};
return (
<>
{!isPlaying ? (
<div className="tools-container">
<div className="drop-down-icons">
<div className="activeDropicon">
{activeSubTool == "cursor" && (
<div
className={`tool-button ${
activeTool === "cursor" ? "active" : ""
}`}
onClick={() => {
setActiveTool("cursor");
}}
>
<div className="tooltip">cursor (v)</div>
<CursorIcon isActive={activeTool === "cursor"} />
</div>
)}
{activeSubTool == "free-hand" && (
<div
className={`tool-button ${
activeTool === "free-hand" ? "active" : ""
}`}
onClick={() => {
setActiveTool("free-hand");
}}
>
<div className="tooltip">free hand (h)</div>
<FreeMoveIcon isActive={activeTool === "free-hand"} />
</div>
)}
{activeSubTool == "delete" && (
<div
className={`tool-button ${
activeTool === "delete" ? "active" : ""
}`}
onClick={() => {
setActiveTool("delete");
}}
>
<div className="tooltip">delete (x)</div>
<DeleteIcon isActive={activeTool === "delete"} />
</div>
)}
{activeModule !== "visualization" && (
<div
className="drop-down-option-button"
ref={dropdownRef}
onClick={() => {
setOpenDrop(!openDrop);
}}
>
<ArrowIcon />
{openDrop && (
<div className="drop-down-container">
<div
className="option-list"
onClick={() => {
setOpenDrop(false);
setActiveTool("cursor");
setActiveSubTool("cursor");
}}
>
<div className="active-option">
{activeSubTool === "cursor" && <TickIcon />}
</div>
<CursorIcon isActive={false} />
<div className="option">Cursor</div>
</div>
<div
className="option-list"
onClick={() => {
setOpenDrop(false);
setActiveTool("free-hand");
setActiveSubTool("free-hand");
}}
>
<div className="active-option">
{activeSubTool === "free-hand" && <TickIcon />}
</div>
<FreeMoveIcon isActive={false} />
<div className="option">Free Hand</div>
</div>
<div
className="option-list"
onClick={() => {
setOpenDrop(false);
setActiveTool("delete");
setActiveSubTool("delete");
}}
>
<div className="active-option">
{activeSubTool === "delete" && <TickIcon />}
</div>
<DeleteIcon isActive={false} />
<div className="option">Delete</div>
</div>
<div className="tools-container">
<div className="activeDropicon">
{/* Tool Picker (cursor, delete, etc.) */}
{["cursor", "free-hand", "delete"].map(
(tool) =>
activeSubTool === tool && (
<ToolButton
key={tool}
icon={getIconByTool(tool)}
tooltip={`${tool} (${getTooltipShortcut(tool)})`}
active={activeTool === tool}
onClick={() => setActiveTool(tool)}
/>
)
)}
{/* Dropdown Menu */}
{activeModule !== "visualization" && (
<button
className="drop-down-option-button"
ref={dropdownRef}
onClick={() => setOpenDrop(!openDrop)}
>
<ArrowIcon />
{openDrop && (
<div className="drop-down-container">
{["cursor", "free-hand", "delete"].map((option) => (
<button
key={option}
className="option-list"
onClick={() => {
setActiveTool(option);
setActiveSubTool(option);
setOpenDrop(false);
}}
>
<div className="active-option">
{activeSubTool === option && <TickIcon />}
</div>
)}
</div>
)}
</div>
</div>
{!toggleThreeD && activeModule === "builder" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button ${
activeTool === "draw-wall" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-wall");
}}
>
<div className="tooltip">draw wall (q)</div>
<WallIcon isActive={activeTool === "draw-wall"} />
</div>
<div
className={`tool-button ${
activeTool === "draw-zone" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-zone");
}}
>
<div className="tooltip">draw zone (e)</div>
<ZoneIcon isActive={activeTool === "draw-zone"} />
</div>
<div
className={`tool-button ${
activeTool === "draw-aisle" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-aisle");
}}
>
<div className="tooltip">draw asile (r)</div>
<AsileIcon isActive={activeTool === "draw-aisle"} />
</div>
<div
className={`tool-button ${
activeTool === "draw-floor" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-floor");
}}
>
<div className="tooltip">draw floor (t)</div>
<FloorIcon isActive={activeTool === "draw-floor"} />
</div>
</div>
</>
)}
{activeModule === "builder" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button ${
activeTool === "measure" ? "active" : ""
}`}
onClick={() => {
setActiveTool("measure");
}}
>
<div className="tooltip">measure scale (m)</div>
<MeasureToolIcon isActive={activeTool === "measure"} />
</div>
</div>
</>
)}
{activeModule === "simulation" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button ${
activeTool === "pen" ? "active" : ""
}`}
onClick={() => {
setActiveTool("pen");
}}
>
<div className="tooltip">pen</div>
<PenIcon isActive={activeTool === "pen"} />
</div>
</div>
</>
)}
{activeModule === "visualization" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button`}
onClick={() => {
handleSaveTemplate({
addTemplate,
floatingWidget,
widgets3D,
selectedZone,
templates,
visualizationSocket,
});
}}
>
<div className="tooltip">save template</div>
<SaveTemplateIcon isActive={false} />
</div>
</div>
</>
)}
<div className="split"></div>
<div className="general-options">
<div
className={`tool-button ${
activeTool === "comment" ? "active" : ""
}`}
onClick={() => {
setActiveTool("comment");
}}
>
<div className="tooltip">comment</div>
<CommentIcon isActive={activeTool === "comment"} />
</div>
{toggleThreeD && (
<div
className={`tool-button ${
activeTool === "play" ? "active" : ""
}`}
onClick={() => {
setIsPlaying(!isPlaying);
}}
>
<div className="tooltip">play (ctrl + p)</div>
<PlayIcon isActive={activeTool === "play"} />
{getIconComponent(option)}
<div className="option">{option}</div>
</button>
))}
</div>
)}
</div>
{activeModule === "builder" && (
<>
<div className="split"></div>
<div
className={`toggle-threed-button${
toggleThreeD ? " toggled" : ""
}`}
onClick={toggleSwitch}
>
<div className="tooltip">toggle view (tab)</div>
<div
className={`toggle-option${!toggleThreeD ? " active" : ""}`}
>
2d
</div>
<div
className={`toggle-option${toggleThreeD ? " active" : ""}`}
>
3d
</div>
</div>
</>
)}
</div>
) : (
</button>
)}
</div>
<div className="split"></div>
{activeModule === "builder" && renderBuilderTools()}
{activeModule === "simulation" && renderSimulationTools()}
{activeModule === "visualization" && renderVisualizationTools()}
<div className="split"></div>
<div className="general-options">
<ToolButton
icon={CommentIcon}
tooltip="comment"
active={activeTool === "comment"}
onClick={() => setActiveTool("comment")}
/>
{toggleThreeD && (
<ToolButton
icon={PlayIcon}
tooltip="play (ctrl + p)"
active={activeTool === "play"}
onClick={() => setIsPlaying(!isPlaying)}
/>
)}
</div>
{activeModule === "builder" && (
<>
{activeModule !== "simulation" && (
<button className="exitPlay" onClick={() => setIsPlaying(false)}>
X
</button>
)}
<div className="split"></div>
{renderModeSwitcher()}
</>
)}
</>
</div>
);
};
// Extracted common store logic
const useStoreHooks = () => {
return {
...useActiveTool(),
...useToolMode(),
...useDeleteTool(),
...useAddAction(),
...useTransformMode(),
...useDeletePointOrLine(),
...useRefTextUpdate(),
};
};
export default Tools;

View File

@@ -11,9 +11,9 @@ import ReferenceDistanceText from "./geomentries/lines/distanceText/referenceDis
////////// Assests Imports //////////
import arch from "../../assets/gltf-glb/arch.glb";
import door from "../../assets/gltf-glb/door.glb";
import Window from "../../assets/gltf-glb/window.glb";
// import arch from "../../assets/gltf-glb/arch.glb";
// import door from "../../assets/gltf-glb/door.glb";
// import Window from "../../assets/gltf-glb/window.glb";
////////// Zustand State Imports //////////
@@ -129,30 +129,30 @@ export default function Builder() {
////////// Assest Configuration Values //////////
const AssetConfigurations: Types.AssetConfigurations = {
arch: {
modelUrl: arch,
scale: [0.75, 0.75, 0.75],
csgscale: [2, 4, 0.5],
csgposition: [0, 2, 0],
positionY: () => 0,
type: "Fixed-Move",
},
door: {
modelUrl: door,
scale: [0.75, 0.75, 0.75],
csgscale: [2, 4, 0.5],
csgposition: [0, 2, 0],
positionY: () => 0,
type: "Fixed-Move",
},
window: {
modelUrl: Window,
scale: [0.75, 0.75, 0.75],
csgscale: [5, 3, 0.5],
csgposition: [0, 1.5, 0],
positionY: (intersectionPoint) => intersectionPoint.point.y,
type: "Free-Move",
},
// arch: {
// modelUrl: arch,
// scale: [0.75, 0.75, 0.75],
// csgscale: [2, 4, 0.5],
// csgposition: [0, 2, 0],
// positionY: () => 0,
// type: "Fixed-Move",
// },
// door: {
// modelUrl: door,
// scale: [0.75, 0.75, 0.75],
// csgscale: [2, 4, 0.5],
// csgposition: [0, 2, 0],
// positionY: () => 0,
// type: "Fixed-Move",
// },
// window: {
// modelUrl: Window,
// scale: [0.75, 0.75, 0.75],
// csgscale: [5, 3, 0.5],
// csgposition: [0, 1.5, 0],
// positionY: (intersectionPoint) => intersectionPoint.point.y,
// type: "Free-Move",
// },
};
////////// All Toggle's //////////

View File

@@ -4,7 +4,7 @@ import PostProcessing from '../postProcessing/postProcessing'
import Controls from '../controls/controls';
import { Environment } from '@react-three/drei'
import background from "../../../assets/hdr/mudroadpuresky2k.hdr";
import background from "../../../assets/textures/hdr/mudroadpuresky2k.hdr";
function Setup() {
return (

View File

@@ -2,10 +2,10 @@ import { useGLTF } from '@react-three/drei'
import { useMemo } from 'react';
import * as THREE from 'three';
import defaultMaterial from '../../../../../assets/gltf-glb/default.glb';
import material1 from '../../../../../assets/gltf-glb/material1.glb';
import material2 from '../../../../../assets/gltf-glb/material2.glb';
import material3 from '../../../../../assets/gltf-glb/material3.glb';
import defaultMaterial from '../../../../../assets/gltf-glb/materials/default.glb';
import material1 from '../../../../../assets/gltf-glb/materials/material1.glb';
import material2 from '../../../../../assets/gltf-glb/materials/material2.glb';
import material3 from '../../../../../assets/gltf-glb/materials/material3.glb';
const modelPaths: Record<string, string> = {
'Default material': defaultMaterial,

View File

@@ -8,8 +8,8 @@ import PickDropPoints from './PickDropPoints';
import useDraggableGLTF from './useDraggableGLTF';
import * as THREE from 'three';
import armPick from "../../../../assets/gltf-glb/arm_ui_pick.glb";
import armDrop from "../../../../assets/gltf-glb/arm_ui_drop.glb";
import armPick from "../../../../assets/gltf-glb/ui/arm_ui_pick.glb";
import armDrop from "../../../../assets/gltf-glb/ui/arm_ui_drop.glb";
import { upsertProductOrEventApi } from '../../../../services/simulation/UpsertProductOrEventApi';
type Positions = {

View File

@@ -1,7 +1,5 @@
import { useEffect, useRef, useState } from "react";
import * as Types from "../../../../types/world/worldTypes";
import startPoint from "../../../../assets/gltf-glb/arrow_green.glb";
import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
import { useGLTF } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import {
@@ -15,6 +13,9 @@ import { useProductStore } from "../../../../store/simulation/useProductStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
import { DoubleSide, Group, Plane, Vector3 } from "three";
import startPoint from "../../../../assets/gltf-glb/ui/arrow_green.glb";
import startEnd from "../../../../assets/gltf-glb/ui/arrow_red.glb";
const VehicleUI = () => {
const { scene: startScene } = useGLTF(startPoint) as any;
const { scene: endScene } = useGLTF(startEnd) as any;