Merge remote-tracking branch 'origin/main-dev' into dev-collaboration

This commit is contained in:
2025-06-26 10:59:22 +05:30
41 changed files with 1495 additions and 857 deletions

View File

@@ -42,7 +42,6 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
const projectId = generateProjectId(); const projectId = generateProjectId();
useSocketStore.getState().initializeSocket(email, organization, token); useSocketStore.getState().initializeSocket(email, organization, token);
//API for creating new Project //API for creating new Project
// const project = await createProject( // const project = await createProject(
// projectId, // projectId,
@@ -50,18 +49,16 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
// savedTheme === "dark" ? darkThemeImage : lightThemeImage, // savedTheme === "dark" ? darkThemeImage : lightThemeImage,
// organization // organization
// ); // );
// console.log('Created project: ', project);
const addProject = { const addProject = {
userId, userId,
thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage, thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage,
organization: organization, organization: organization,
projectUuid: projectId, projectUuid: projectId,
}; };
// console.log("projectSocket: ", projectSocket);
if (projectSocket) { if (projectSocket) {
// console.log('addProject: ', addProject);
const handleResponse = (data: any) => { const handleResponse = (data: any) => {
// console.log('Project add response:', data);
if (data.message === "Project created successfully") { if (data.message === "Project created successfully") {
setLoadingProgress(1) setLoadingProgress(1)
navigate(`/${data.data.projectId}`); navigate(`/${data.data.projectId}`);
@@ -70,7 +67,6 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
}; };
projectSocket.on("v1-project:response:add", handleResponse); projectSocket.on("v1-project:response:add", handleResponse);
// console.log('addProject: ', addProject);
projectSocket.emit("v1:project:add", addProject); projectSocket.emit("v1:project:add", addProject);
} else { } else {
console.error("Socket is not connected."); console.error("Socket is not connected.");

View File

@@ -23,12 +23,14 @@ import {
useSelectedEventSphere, useSelectedEventSphere,
} from "../../../store/simulation/useSimulationStore"; } from "../../../store/simulation/useSimulationStore";
import GlobalProperties from "./properties/GlobalProperties"; import GlobalProperties from "./properties/GlobalProperties";
import AsstePropertiies from "./properties/AssetProperties"; import AssetProperties from "./properties/AssetProperties";
import ZoneProperties from "./properties/ZoneProperties"; import ZoneProperties from "./properties/ZoneProperties";
import EventProperties from "./properties/eventProperties/EventProperties"; import EventProperties from "./properties/eventProperties/EventProperties";
import VersionHistory from "./versionHisory/VersionHistory"; import VersionHistory from "./versionHisory/VersionHistory";
import AisleProperties from "./properties/AisleProperties"; import AisleProperties from "./properties/AisleProperties";
import WallProperties from "./properties/eventProperties/WallProperties"; import WallProperties from "./properties/WallProperties";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import SelectedWallProperties from "./properties/SelectedWallProperties";
const SideBarRight: React.FC = () => { const SideBarRight: React.FC = () => {
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
@@ -36,6 +38,7 @@ const SideBarRight: React.FC = () => {
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { subModule, setSubModule } = useSubModuleStore(); const { subModule, setSubModule } = useSubModuleStore();
const { selectedFloorItem } = useSelectedFloorItem(); const { selectedFloorItem } = useSelectedFloorItem();
const { selectedWall } = useBuilderStore();
const { selectedEventData } = useSelectedEventData(); const { selectedEventData } = useSelectedEventData();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore(); const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore();
@@ -143,7 +146,8 @@ const SideBarRight: React.FC = () => {
{!viewVersionHistory && {!viewVersionHistory &&
subModule === "properties" && subModule === "properties" &&
activeModule !== "visualization" && activeModule !== "visualization" &&
!selectedFloorItem && ( !selectedFloorItem &&
!selectedWall && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
{(() => { {(() => {
@@ -158,13 +162,26 @@ const SideBarRight: React.FC = () => {
</div> </div>
</div> </div>
)} )}
{!viewVersionHistory && {!viewVersionHistory &&
subModule === "properties" && subModule === "properties" &&
activeModule !== "visualization" && activeModule !== "visualization" &&
selectedFloorItem && ( selectedFloorItem && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<AsstePropertiies /> <AssetProperties />
</div>
</div>
)}
{!viewVersionHistory &&
subModule === "properties" &&
activeModule !== "visualization" &&
!selectedFloorItem &&
selectedWall && (
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
<SelectedWallProperties />
</div> </div>
</div> </div>
)} )}
@@ -178,6 +195,7 @@ const SideBarRight: React.FC = () => {
</div> </div>
</div> </div>
)} )}
{/* simulation */} {/* simulation */}
{!isVersionSaved && {!isVersionSaved &&
!viewVersionHistory && !viewVersionHistory &&

View File

@@ -0,0 +1,143 @@
import { useState } from "react";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import defaultTexture from '../../../../assets/textures/floor/wall-tex.png';
import wallTexture1 from '../../../../assets/textures/floor/factory wall texture.jpg';
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
const SelectedWallProperties = () => {
const { selectedWall } = useBuilderStore();
const { wallStore } = useSceneContext();
const { getWallById, updateWall } = wallStore();
const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1");
const materials = [
{ texture: defaultTexture, textureId: "Default Material", textureName: "Default Material" },
{ texture: wallTexture1, textureId: "Material 1", textureName: "Grunge Concrete Wall" }
];
const wall = selectedWall ? getWallById(selectedWall.userData.wallUuid) : null;
const handleHeightChange = (val: string) => {
const height = parseFloat(val);
if (!isNaN(height) && wall) {
updateWall(wall.wallUuid, { wallHeight: height });
}
};
const handleThicknessChange = (val: string) => {
const thickness = parseFloat(val);
if (!isNaN(thickness) && wall) {
updateWall(wall.wallUuid, { wallThickness: thickness });
}
};
const handleSelectMaterial = (material: { textureId: string; textureName: string }) => {
if (!wall) return;
const updated = (activeSide === "side1" ? { insideMaterial: material.textureId } : { outsideMaterial: material.textureId })
updateWall(wall.wallUuid, updated);
};
if (!wall) return null;
const selectedMaterials = {
side1: {
texture: materials.find((material) => material.textureId === wall.insideMaterial)?.texture || 'Unknown',
textureId: materials.find((material) => material.textureId === wall.insideMaterial)?.textureId || 'Unknown',
textureName: materials.find((material) => material.textureId === wall.insideMaterial)?.textureName || 'Unknown'
},
side2: {
texture: materials.find((material) => material.textureId === wall.outsideMaterial)?.texture || 'Unknown',
textureId: materials.find((material) => material.textureId === wall.outsideMaterial)?.textureId || 'Unknown',
textureName: materials.find((material) => material.textureId === wall.outsideMaterial)?.textureName || 'Unknown'
}
};
return (
<div className="wall-properties-container">
<section className="wall-properties-section">
<div className="header">Wall</div>
<div className="wall-properties">
<InputWithDropDown
label="Height"
value={`${wall.wallHeight}`}
onChange={handleHeightChange}
/>
<InputWithDropDown
label="Thickness"
value={`${wall.wallThickness}`}
onChange={handleThicknessChange}
/>
</div>
</section>
<section>
<div className="header-wrapper">
<div className="header">Materials</div>
</div>
<div className="material-preview">
<div className="sides-wrapper">
{(["side1", "side2"] as const).map((side) => (
<button
key={side}
className={`side-wrapper ${activeSide === side ? "active" : ""}`}
onClick={() => setActiveSide(side)}
>
<div className="label">Side {side === "side1" ? 1 : 2}</div>
<div className="texture-image">
<img
draggable={false}
src={selectedMaterials[side].texture}
alt={selectedMaterials[side].textureName}
/>
</div>
</button>
))}
</div>
<div className="preview">
<img
draggable={false}
src={selectedMaterials[activeSide].texture}
alt={selectedMaterials[activeSide].textureName}
/>
</div>
</div>
<div className="materials">
<div className="material-container">
{materials.map((material, index) => {
const isSelected = selectedMaterials[activeSide].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 SelectedWallProperties;

View File

@@ -1,11 +1,12 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import InputWithDropDown from "../../../../ui/inputs/InputWithDropDown"; import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons";
// Texture Imports // Texture Imports
import wallTexture1 from "../../../../../assets/image/wallTextures/wallTexture.png";
import defaultTexture from "../../../../../assets/image/wallTextures/defaultTexture.jpg"; import defaultTexture from '../../../../assets/textures/floor/wall-tex.png';
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore"; import wallTexture1 from '../../../../assets/textures/floor/factory wall texture.jpg';
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
// Define Material type // Define Material type
type Material = { type Material = {
@@ -58,14 +59,6 @@ const WallProperties = () => {
setWallThickness(parseFloat(newValue)); setWallThickness(parseFloat(newValue));
}; };
const handleAddMaterial = () => {
const newMaterial: Material = {
texture: defaultMaterial.texture,
textureName: `Material ${materials.length + 1}`,
};
setMaterials([...materials, newMaterial]);
};
const handleSelectMaterial = (material: Material) => { const handleSelectMaterial = (material: Material) => {
setSelectedMaterials((prev) => ({ setSelectedMaterials((prev) => ({
...prev, ...prev,
@@ -73,46 +66,26 @@ const WallProperties = () => {
})); }));
}; };
const handleRemoveMaterial = (index: number) => {
const removedTexture = materials[index].texture;
const updatedMaterials = materials.filter((_, i) => i !== index);
const newMaterials = updatedMaterials.length === 0 ? [defaultMaterial] : updatedMaterials;
setMaterials(newMaterials);
setSelectedMaterials((prev) => {
const updated = { ...prev };
["side1", "side2"].forEach((side) => {
if (updated[side as "side1" | "side2"]?.texture === removedTexture) {
updated[side as "side1" | "side2"] = defaultMaterial;
}
});
return updated;
});
};
return ( return (
<div className="wall-properties-container"> <div className="wall-properties-container">
<div className="header">Wall</div> <section className="wall-properties-section">
<div className="wall-properties"> <div className="header">Wall</div>
<InputWithDropDown <div className="wall-properties">
label="Height" <InputWithDropDown
value={`${wallHeight}`} label="Height"
onChange={(val) => handleHeightChange(val)} value={`${wallHeight}`}
/> onChange={(val) => handleHeightChange(val)}
<InputWithDropDown />
label="Thickness" <InputWithDropDown
value={`${wallThickness}`} label="Thickness"
onChange={(val) => handleThicknessChange(val)} value={`${wallThickness}`}
/> onChange={(val) => handleThicknessChange(val)}
</div> />
</div>
</section>
<section> <section>
<div className="header-wrapper"> <div className="header-wrapper">
<div className="header">Materials</div> <div className="header">Materials</div>
<button className="addMaterial" onClick={handleAddMaterial}>
<AddIcon />
</button>
</div> </div>
<div className="material-preview"> <div className="material-preview">
@@ -185,15 +158,6 @@ const WallProperties = () => {
</div> </div>
<div className="material-name">{material.textureName}</div> <div className="material-name">{material.textureName}</div>
</div> </div>
<button
className="delete-material"
onClick={(e) => {
e.stopPropagation();
handleRemoveMaterial(index);
}}
>
<RemoveIcon />
</button>
</button> </button>
); );
})} })}

View File

@@ -91,16 +91,7 @@ const BarChartInput = (props: Props) => {
duration: inputDuration, duration: inputDuration,
} }
} }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || ""); let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "");

View File

@@ -210,15 +210,7 @@ const LineGrapInput = (props: Props) => {
} }
} }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || ""); let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "");
if (response.message === "Widget updated successfully") { if (response.message === "Widget updated successfully") {

View File

@@ -94,15 +94,7 @@ const PieChartInput = (props: Props) => {
duration: inputDuration, duration: inputDuration,
}, },
} }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || ""); let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "");

View File

@@ -93,15 +93,7 @@ const Progress1Input = (props: Props) => {
duration: inputDuration, duration: inputDuration,
}, },
} }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || ""); let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "");
if (response.message === "Widget updated successfully") { if (response.message === "Widget updated successfully") {

View File

@@ -94,16 +94,6 @@ const Progress2Input = (props: Props) => {
} }
} }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || ""); let response = await addingWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "");
if (response.message === "Widget updated successfully") { if (response.message === "Widget updated successfully") {

View File

@@ -38,15 +38,15 @@ const Widget2InputCard3D = (props: Props) => {
setLoading(true); setLoading(true);
const response = await axios.get(`http://${iotApiUrl}/floatinput`); const response = await axios.get(`http://${iotApiUrl}/floatinput`);
if (response.status === 200) { if (response.status === 200) {
// console.log("dropdown data:", response.data); //
setDropDownData(response.data); setDropDownData(response.data);
setLoading(false); setLoading(false);
} else { } else {
// console.log("Unexpected response:", response); //
} }
} catch (error) { } catch (error) {
echo.error("Failed to fetch zone data"); echo.error("Failed to fetch zone data");
console.error("There was an error!", error);
} }
}; };
fetchZoneData(); fetchZoneData();
@@ -55,14 +55,14 @@ const Widget2InputCard3D = (props: Props) => {
useEffect(() => { useEffect(() => {
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (selectedChartId.id !== "") { if (selectedChartId.id !== "") {
let response = await get3dWidgetInput(selectedChartId.id, organization) let response = await get3dWidgetInput(selectedChartId.id, organization, projectId, selectedVersion?.versionId || "")
console.log('response: ', response);
if (response) { if (response) {
setSelections(response.data.Data.measurements); setSelections(response.Datastructure.measurements);
setDuration(response.data.Data.duration); setDuration(response.Datastructure.duration);
setWidgetName(response.data.widgetName); setWidgetName(response.widgetName);
} }
} }
}; };
@@ -81,44 +81,61 @@ const Widget2InputCard3D = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// let newWidget = { let newWidget = {
// id: selectedChartId.id, id: selectedChartId.id,
// widgetName: inputName, widgetName: inputName,
// Data: { Data: {
// measurements: inputMeasurement, measurements: inputMeasurement,
// duration: inputDuration, duration: inputDuration,
// }, },
// }
// let response = await adding3dWidgets(selectedZone.zoneUuid, organization, newWidget,projectId, selectedVersion?.versionId || "")
// console.log('response: ', response);
try {
const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget3d/save`,
{
organization,
zoneUuid: selectedZone.zoneUuid,
widget: {
id: selectedChartId.id,
widgetName: inputName,
Data: {
measurements: inputMeasurement,
duration: inputDuration,
},
},
} as any
);
if (response.status === 200) {
return true;
} else {
// console.log("Unexpected response:", response);
return false;
}
} catch (error) {
echo.error("Failed to send input");
console.error("There was an error!", error);
return false;
} }
let response = await adding3dWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "")
if (response.message === "widget update successfully") {
return true;
} else {
return false
}
// try {
// const response = await axios.post(
// `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget3d/save`,
// {
// headers: {
// Authorization: "Bearer <access_token>",
// "Content-Type": "application/json",
// token: localStorage.getItem("token") || "",
// refresh_token: localStorage.getItem("refreshToken") || "",
// },
// },
// {
// organization,
// zoneUuid: selectedZone.zoneUuid,
// widget: {
// id: selectedChartId.id,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// },
// },
// projectId: projectId,
// versionId: selectedVersion?.versionId || ""
// } as any,
// );
//
// if (response.status === 200) {
// return true;
// } else {
// //
// return false;
// }
// } catch (error) {
// echo.error("Failed to send input");
//
// return false;
// }
}; };
const handleSelect = async ( const handleSelect = async (
@@ -133,7 +150,7 @@ const Widget2InputCard3D = (props: Props) => {
newSelections[inputKey] = selectedData; newSelections[inputKey] = selectedData;
} }
// setMeasurements(newSelections); // Update Zustand store // setMeasurements(newSelections); // Update Zustand store
// console.log(newSelections); //
if (await sendInputes(newSelections, duration, widgetName)) { if (await sendInputes(newSelections, duration, widgetName)) {
setSelections(newSelections); setSelections(newSelections);
} }
@@ -150,7 +167,7 @@ const Widget2InputCard3D = (props: Props) => {
}; };
const handleNameChange = async (name: any) => { const handleNameChange = async (name: any) => {
// console.log("name change requested", name); //
if (await sendInputes(selections, duration, name)) { if (await sendInputes(selections, duration, name)) {
setWidgetName(name); setWidgetName(name);

View File

@@ -36,15 +36,15 @@ const Widget3InputCard3D = () => {
setLoading(true); setLoading(true);
const response = await axios.get(`http://${iotApiUrl}/getinput`); const response = await axios.get(`http://${iotApiUrl}/getinput`);
if (response.status === 200) { if (response.status === 200) {
// console.log("dropdown data:", response.data); //
setDropDownData(response.data); setDropDownData(response.data);
setLoading(false); setLoading(false);
} else { } else {
// console.log("Unexpected response:", response); //
} }
} catch (error) { } catch (error) {
echo.error("Failed to fetch zone data"); echo.error("Failed to fetch zone data");
console.error("There was an error!", error);
} }
}; };
fetchZoneData(); fetchZoneData();
@@ -53,12 +53,12 @@ const Widget3InputCard3D = () => {
useEffect(() => { useEffect(() => {
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (selectedChartId.id !== "") { if (selectedChartId.id !== "") {
let response = await get3dWidgetInput(selectedChartId.id, organization) let response = await get3dWidgetInput(selectedChartId.id, organization, projectId, selectedVersion?.versionId || "")
console.log('response: ', response);
if (response) { if (response) {
setSelections(response.data.Data.measurements); setSelections(response.Datastructure.measurements);
setDuration(response.data.Data.duration); setDuration(response.Datastructure.duration);
setWidgetName(response.data.widgetName); setWidgetName(response.widgetName);
} }
} }
@@ -79,45 +79,61 @@ const Widget3InputCard3D = () => {
inputName: any inputName: any
) => { ) => {
// let newWidget = { let newWidget = {
// id: selectedChartId.id, id: selectedChartId.id,
// widgetName: inputName, widgetName: inputName,
// Data: { Data: {
// measurements: inputMeasurement, measurements: inputMeasurement,
// duration: inputDuration, duration: inputDuration,
// }, },
// }
// let response = await adding3dWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "")
// console.log('response: ', response);
try {
const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget3d/save`,
{
organization,
zoneUuid: selectedZone.zoneUuid,
widget: {
id: selectedChartId.id,
widgetName: inputName,
Data: {
measurements: inputMeasurement,
duration: inputDuration,
},
},
} as any
);
if (response.status === 200) {
return true;
} else {
// console.log("Unexpected response:", response);
return false;
}
} catch (error) {
echo.error("Failed to send input");
console.error("There was an error!", error);
return false;
} }
let response = await adding3dWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "")
if (response.message === "widget update successfully") {
return true;
} else {
return false
}
// try {
// const response = await axios.post(
// `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget3d/save`,
// {
// headers: {
// Authorization: "Bearer <access_token>",
// "Content-Type": "application/json",
// token: localStorage.getItem("token") || "",
// refresh_token: localStorage.getItem("refreshToken") || "",
// },
// },
// {
// organization,
// zoneUuid: selectedZone.zoneUuid,
// widget: {
// id: selectedChartId.id,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// },
// },
// projectId: projectId,
// versionId: selectedVersion?.versionId || ""
// } as any
// );
//
// if (response.status === 200) {
// return true;
// } else {
// //
// return false;
// }
// } catch (error) {
// echo.error("Failed to send input");
//
// return false;
// }
}; };
const handleSelect = async ( const handleSelect = async (
@@ -132,7 +148,7 @@ const Widget3InputCard3D = () => {
newSelections[inputKey] = selectedData; newSelections[inputKey] = selectedData;
} }
// setMeasurements(newSelections); // Update Zustand store // setMeasurements(newSelections); // Update Zustand store
// console.log(newSelections); //
if (await sendInputes(newSelections, duration, widgetName)) { if (await sendInputes(newSelections, duration, widgetName)) {
setSelections(newSelections); setSelections(newSelections);
} }
@@ -145,7 +161,7 @@ const Widget3InputCard3D = () => {
}; };
const handleNameChange = async (name: any) => { const handleNameChange = async (name: any) => {
// console.log("name change requested", name); //
if (await sendInputes(selections, duration, name)) { if (await sendInputes(selections, duration, name)) {
setWidgetName(name); setWidgetName(name);

View File

@@ -38,15 +38,15 @@ const Widget4InputCard3D = (props: Props) => {
setLoading(true); setLoading(true);
const response = await axios.get(`http://${iotApiUrl}/floatinput`); const response = await axios.get(`http://${iotApiUrl}/floatinput`);
if (response.status === 200) { if (response.status === 200) {
// console.log("dropdown data:", response.data); //
setDropDownData(response.data); setDropDownData(response.data);
setLoading(false); setLoading(false);
} else { } else {
// console.log("Unexpected response:", response); //
} }
} catch (error) { } catch (error) {
echo.error("Failed to fetch zone data"); echo.error("Failed to fetch zone data");
console.error("There was an error!", error);
} }
}; };
fetchZoneData(); fetchZoneData();
@@ -55,14 +55,17 @@ const Widget4InputCard3D = (props: Props) => {
useEffect(() => { useEffect(() => {
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (selectedChartId.id !== "") { if (selectedChartId.id !== "") {
let response = await get3dWidgetInput(selectedChartId.id, organization)
console.log('response: ', response);
let response = await get3dWidgetInput(selectedChartId.id, organization, projectId, selectedVersion?.versionId || "")
if (response) { if (response) {
setSelections(response.data.Data.measurements); setSelections(response.Datastructure.measurements);
setDuration(response.data.Data.duration); setDuration(response.Datastructure.duration);
setWidgetName(response.data.widgetName); setWidgetName(response.widgetName);
} }
} }
}; };
@@ -81,44 +84,61 @@ const Widget4InputCard3D = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// let newWidget = { let newWidget = {
// id: selectedChartId.id, id: selectedChartId.id,
// widgetName: inputName, widgetName: inputName,
// Data: { Data: {
// measurements: inputMeasurement, measurements: inputMeasurement,
// duration: inputDuration, duration: inputDuration,
// }, },
// }
// let response = await adding3dWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "")
// console.log('response: ', response);
try {
const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget3d/save`,
{
organization,
zoneUuid: selectedZone.zoneUuid,
widget: {
id: selectedChartId.id,
widgetName: inputName,
Data: {
measurements: inputMeasurement,
duration: inputDuration,
},
},
} as any
);
if (response.status === 200) {
return true;
} else {
// console.log("Unexpected response:", response);
return false;
}
} catch (error) {
echo.error("Failed to send input");
console.error("There was an error!", error);
return false;
} }
let response = await adding3dWidgets(selectedZone.zoneUuid, organization, newWidget, projectId, selectedVersion?.versionId || "")
if (response.message === "widget update successfully") {
return true;
} else {
return false
}
//
// try {
// const response = await axios.post(
// `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget3d/save`,
// {
// headers: {
// Authorization: "Bearer <access_token>",
// "Content-Type": "application/json",
// token: localStorage.getItem("token") || "",
// refresh_token: localStorage.getItem("refreshToken") || "",
// },
// },
// {
// organization,
// zoneUuid: selectedZone.zoneUuid,
// widget: {
// id: selectedChartId.id,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// },
// },
// projectId: projectId,
// versionId: selectedVersion?.versionId || ""
// } as any
// );
//
// if (response.status === 200) {
// return true;
// } else {
// //
// return false;
// }
// } catch (error) {
// echo.error("Failed to send input");
//
// return false;
// }
}; };
const handleSelect = async ( const handleSelect = async (
@@ -133,7 +153,7 @@ const Widget4InputCard3D = (props: Props) => {
newSelections[inputKey] = selectedData; newSelections[inputKey] = selectedData;
} }
// setMeasurements(newSelections); // Update Zustand store // setMeasurements(newSelections); // Update Zustand store
// console.log(newSelections); //
if (await sendInputes(newSelections, duration, widgetName)) { if (await sendInputes(newSelections, duration, widgetName)) {
setSelections(newSelections); setSelections(newSelections);
} }
@@ -150,7 +170,7 @@ const Widget4InputCard3D = (props: Props) => {
}; };
const handleNameChange = async (name: any) => { const handleNameChange = async (name: any) => {
console.log("name change requested", name);
if (await sendInputes(selections, duration, name)) { if (await sendInputes(selections, duration, name)) {
setWidgetName(name); setWidgetName(name);

View File

@@ -0,0 +1,48 @@
import * as THREE from 'three';
import { Decal } from '@react-three/drei'
import { useLoader } from '@react-three/fiber';
import { useToggleView } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import defaultMaterial from '../../../assets/textures/floor/wall-tex.png';
import useModuleStore from '../../../store/useModuleStore';
function DecalInstance({ visible = true, decal }: { visible?: boolean, decal: Decal }) {
const { setSelectedWall, selectedDecal, setSelectedDecal } = useBuilderStore();
const { togglView } = useToggleView();
const { activeModule } = useModuleStore();
const material = useLoader(THREE.TextureLoader, defaultMaterial);
return (
<Decal
// debug
visible={visible}
position={decal.decalPosition}
rotation={[0, 0, decal.decalRotation]}
scale={[decal.decalScale, decal.decalScale, 0.01]}
userData={decal}
onClick={(e) => {
if (visible && !togglView && activeModule === 'builder') {
if (e.object.userData.decalUuid) {
setSelectedDecal(e.object);
setSelectedWall(null);
}
}
}}
onPointerMissed={() => {
if (selectedDecal && selectedDecal.userData.decalUuid === decal.decalUuid) {
setSelectedDecal(null);
}
}}
>
<meshBasicMaterial
map={material}
side={THREE.DoubleSide}
polygonOffset
polygonOffsetFactor={-1}
/>
</Decal>
)
}
export default DecalInstance

View File

@@ -79,6 +79,7 @@ const DxfFile = ({
userId userId
} }
console.log('input: ', input);
socket.emit('v1:Line:create', input); socket.emit('v1:Line:create', input);
}) })

View File

@@ -158,6 +158,7 @@ async function drawOnlyFloor(
userId, userId,
}; };
console.log('input: ', input);
socket.emit("v1:Line:create", input); socket.emit("v1:Line:create", input);
setNewLines([newLines[0], newLines[1], line.current]); setNewLines([newLines[0], newLines[1], line.current]);
@@ -248,6 +249,7 @@ async function drawOnlyFloor(
userId, userId,
}; };
console.log('input: ', input);
socket.emit("v1:Line:create", input); socket.emit("v1:Line:create", input);
setNewLines([line.current]); setNewLines([line.current]);

View File

@@ -14,232 +14,205 @@ import { Socket } from "socket.io-client";
import { getUserData } from "../../../../functions/getUserData"; import { getUserData } from "../../../../functions/getUserData";
async function drawWall( async function drawWall(
raycaster: THREE.Raycaster, raycaster: THREE.Raycaster,
plane: Types.RefMesh, plane: Types.RefMesh,
floorPlanGroupPoint: Types.RefGroup, floorPlanGroupPoint: Types.RefGroup,
snappedPoint: Types.RefVector3, snappedPoint: Types.RefVector3,
isSnapped: Types.RefBoolean, isSnapped: Types.RefBoolean,
isSnappedUUID: Types.RefString, isSnappedUUID: Types.RefString,
line: Types.RefLine, line: Types.RefLine,
ispreSnapped: Types.RefBoolean, ispreSnapped: Types.RefBoolean,
anglesnappedPoint: Types.RefVector3, anglesnappedPoint: Types.RefVector3,
isAngleSnapped: Types.RefBoolean, isAngleSnapped: Types.RefBoolean,
lines: Types.RefLines, lines: Types.RefLines,
floorPlanGroupLine: Types.RefGroup, floorPlanGroupLine: Types.RefGroup,
floorPlanGroup: Types.RefGroup, floorPlanGroup: Types.RefGroup,
ReferenceLineMesh: Types.RefMesh, ReferenceLineMesh: Types.RefMesh,
LineCreated: Types.RefBoolean, LineCreated: Types.RefBoolean,
currentLayerPoint: Types.RefMeshArray, currentLayerPoint: Types.RefMeshArray,
dragPointControls: Types.RefDragControl, dragPointControls: Types.RefDragControl,
setNewLines: any, setNewLines: any,
setDeletedLines: any, setDeletedLines: any,
activeLayer: Types.Number, activeLayer: Types.Number,
socket: Socket<any>, socket: Socket<any>,
projectId?: string, projectId?: string,
versionId?: string, versionId?: string,
): Promise<void> { ): Promise<void> {
const { userId, organization, email } = getUserData(); const { userId, organization } = getUserData();
////////// Creating lines Based on the positions clicked ////////// ////////// Creating lines Based on the positions clicked //////////
////////// Allows the user lines that represents walls and roof, floor if forms a polygon ////////// ////////// Allows the user lines that represents walls and roof, floor if forms a polygon //////////
if (!plane.current) return; if (!plane.current) return;
let intersects = raycaster.intersectObject(plane.current, true); let intersects = raycaster.intersectObject(plane.current, true);
let intersectsLines = raycaster.intersectObjects( let intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true);
floorPlanGroupLine.current.children, let intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true);
true
);
let intersectsPoint = raycaster.intersectObjects(
floorPlanGroupPoint.current.children,
true
);
const VisibleintersectsPoint = intersectsPoint.find( const VisibleintersectsPoint = intersectsPoint.find((intersect) => intersect.object.visible);
(intersect) => intersect.object.visible const visibleIntersect = intersectsLines.find(
); (intersect) =>
const visibleIntersect = intersectsLines.find( intersect.object.visible &&
(intersect) => intersect.object.name !== CONSTANTS.lineConfig.referenceName &&
intersect.object.visible && intersect.object.userData.linePoints[0][3] ===
intersect.object.name !== CONSTANTS.lineConfig.referenceName && CONSTANTS.lineConfig.wallName
intersect.object.userData.linePoints[0][3] === );
CONSTANTS.lineConfig.wallName
);
if ( if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) {
(intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && ////////// Clicked on a preexisting Line //////////
intersectsLines.length > 0 &&
!isSnapped.current &&
!ispreSnapped.current
) {
////////// Clicked on a preexisting Line //////////
if (visibleIntersect && intersects) { if (visibleIntersect && intersects) {
let IntersectsPoint = new THREE.Vector3( let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z);
intersects[0].point.x,
0.01,
intersects[0].point.z
);
if (isAngleSnapped.current && anglesnappedPoint.current) { if (isAngleSnapped.current && anglesnappedPoint.current) {
IntersectsPoint = anglesnappedPoint.current; IntersectsPoint = anglesnappedPoint.current;
} }
if (visibleIntersect.object instanceof THREE.Mesh) { if (visibleIntersect.object instanceof THREE.Mesh) {
const ThroughPoint = const ThroughPoint = visibleIntersect.object.geometry.parameters.path.getPoints(CONSTANTS.lineConfig.lineIntersectionPoints);
visibleIntersect.object.geometry.parameters.path.getPoints( let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint);
CONSTANTS.lineConfig.lineIntersectionPoints
);
let intersectionPoint = getClosestIntersection(
ThroughPoint,
IntersectsPoint
);
if (intersectionPoint) { if (intersectionPoint) {
const newLines = splitLine( const newLines = splitLine(
visibleIntersect, visibleIntersect,
intersectionPoint, intersectionPoint,
currentLayerPoint, currentLayerPoint,
floorPlanGroupPoint, floorPlanGroupPoint,
dragPointControls, dragPointControls,
isSnappedUUID, isSnappedUUID,
lines, lines,
setDeletedLines, setDeletedLines,
floorPlanGroupLine, floorPlanGroupLine,
socket, socket,
CONSTANTS.pointConfig.wallOuterColor, CONSTANTS.pointConfig.wallOuterColor,
CONSTANTS.lineConfig.wallColor, CONSTANTS.lineConfig.wallColor,
CONSTANTS.lineConfig.wallName, CONSTANTS.lineConfig.wallName,
projectId, projectId,
versionId versionId
); );
setNewLines([newLines[0], newLines[1]]); setNewLines([newLines[0], newLines[1]]);
(line.current as Types.Line).push([ (line.current as Types.Line).push([
new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
isSnappedUUID.current!, isSnappedUUID.current!,
activeLayer, activeLayer,
CONSTANTS.lineConfig.wallName, CONSTANTS.lineConfig.wallName,
]); ]);
if (line.current.length >= 2 && line.current[0] && line.current[1]) { if (line.current.length >= 2 && line.current[0] && line.current[1]) {
const data = arrayLineToObject(line.current as Types.Line); const data = arrayLineToObject(line.current as Types.Line);
//REST //REST
// setLine(organization, data.layer!, data.line!, data.type!); // setLine(organization, data.layer!, data.line!, data.type!);
//SOCKET //SOCKET
const input = { const input = {
organization, organization,
layer: data.layer, layer: data.layer,
line: data.line, line: data.line,
type: data.type, type: data.type,
socketId: socket.id, socketId: socket.id,
versionId, versionId,
projectId, projectId,
userId, userId,
}; };
socket.emit("v1:Line:create", input); socket.emit("v1:Line:create", input);
setNewLines([newLines[0], newLines[1], line.current]); setNewLines([newLines[0], newLines[1], line.current]);
lines.current.push(line.current as Types.Line); lines.current.push(line.current as Types.Line);
addLineToScene( addLineToScene(
line.current[0][0], line.current[0][0],
line.current[1][0], line.current[1][0],
CONSTANTS.lineConfig.wallColor, CONSTANTS.lineConfig.wallColor,
line.current, line.current,
floorPlanGroupLine floorPlanGroupLine
); );
let lastPoint = line.current[line.current.length - 1]; let lastPoint = line.current[line.current.length - 1];
line.current = [lastPoint]; line.current = [lastPoint];
} }
return; return;
} }
} }
} }
} }
if (intersects && intersects.length > 0) { if (intersects && intersects.length > 0) {
////////// Clicked on a emply place or a point ////////// ////////// Clicked on a emply place or a point //////////
let intersectionPoint = intersects[0].point; let intersectionPoint = intersects[0].point;
if ( if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) {
isAngleSnapped.current && intersectionPoint = anglesnappedPoint.current;
line.current.length > 0 && }
anglesnappedPoint.current if (isSnapped.current && line.current.length > 0 && snappedPoint.current) {
) { intersectionPoint = snappedPoint.current;
intersectionPoint = anglesnappedPoint.current; }
} if (ispreSnapped.current && snappedPoint.current) {
if (isSnapped.current && line.current.length > 0 && snappedPoint.current) { intersectionPoint = snappedPoint.current;
intersectionPoint = snappedPoint.current; }
}
if (ispreSnapped.current && snappedPoint.current) {
intersectionPoint = snappedPoint.current;
}
if (!isSnapped.current && !ispreSnapped.current) { if (!isSnapped.current && !ispreSnapped.current) {
addPointToScene( addPointToScene(
intersectionPoint, intersectionPoint,
CONSTANTS.pointConfig.wallOuterColor, CONSTANTS.pointConfig.wallOuterColor,
currentLayerPoint, currentLayerPoint,
floorPlanGroupPoint, floorPlanGroupPoint,
dragPointControls, dragPointControls,
isSnappedUUID, isSnappedUUID,
CONSTANTS.lineConfig.wallName CONSTANTS.lineConfig.wallName
); );
} else { } else {
ispreSnapped.current = false; ispreSnapped.current = false;
isSnapped.current = false; isSnapped.current = false;
} }
(line.current as Types.Line).push([ (line.current as Types.Line).push([
new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z), new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
isSnappedUUID.current!, isSnappedUUID.current!,
activeLayer, activeLayer,
CONSTANTS.lineConfig.wallName, CONSTANTS.lineConfig.wallName,
]); ]);
if (line.current.length >= 2 && line.current[0] && line.current[1]) { if (line.current.length >= 2 && line.current[0] && line.current[1]) {
const data = arrayLineToObject(line.current as Types.Line); const data = arrayLineToObject(line.current as Types.Line);
//REST //REST
// setLine(organization, data.layer!, data.line!, data.type!); // setLine(organization, data.layer!, data.line!, data.type!);
//SOCKET //SOCKET
const input = { const input = {
organization, organization,
layer: data.layer, layer: data.layer,
line: data.line, line: data.line,
type: data.type, type: data.type,
socketId: socket.id, socketId: socket.id,
versionId, versionId,
projectId, projectId,
userId, userId,
}; };
socket.emit("v1:Line:create", input); socket.emit("v1:Line:create", input);
setNewLines([line.current]); setNewLines([line.current]);
lines.current.push(line.current as Types.Line); lines.current.push(line.current as Types.Line);
addLineToScene( addLineToScene(
line.current[0][0], line.current[0][0],
line.current[1][0], line.current[1][0],
CONSTANTS.lineConfig.wallColor, CONSTANTS.lineConfig.wallColor,
line.current, line.current,
floorPlanGroupLine floorPlanGroupLine
); );
let lastPoint = line.current[line.current.length - 1]; let lastPoint = line.current[line.current.length - 1];
line.current = [lastPoint]; line.current = [lastPoint];
} }
if (isSnapped.current) { if (isSnapped.current) {
removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line); removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
} }
} }
} }
export default drawWall; export default drawWall;

View File

@@ -107,6 +107,7 @@ function splitLine(
userId, userId,
}; };
console.log('input1: ', input1);
socket.emit("v1:Line:create", input1); socket.emit("v1:Line:create", input1);
//REST //REST
@@ -126,6 +127,7 @@ function splitLine(
userId, userId,
}; };
console.log('input2: ', input2);
socket.emit("v1:Line:create", input2); socket.emit("v1:Line:create", input2);
lines.current.push(newLine1, newLine2); lines.current.push(newLine1, newLine2);

View File

@@ -1,11 +1,11 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import * as Constants from '../../../types/world/worldConstants';
import { DragControls, Tube } from '@react-three/drei'; import { DragControls, Tube } from '@react-three/drei';
import { useToolMode } from '../../../store/builder/store'; import { useToolMode } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore'; import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useWallStore } from '../../../store/builder/useWallStore'; import { useSceneContext } from '../../scene/sceneContext';
import { useThree } from '@react-three/fiber'; import * as Constants from '../../../types/world/worldConstants';
interface LineProps { interface LineProps {
points: [Point, Point]; points: [Point, Point];
@@ -17,7 +17,8 @@ function Line({ points }: Readonly<LineProps>) {
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isDeletable, setIsDeletable] = useState(false); const [isDeletable, setIsDeletable] = useState(false);
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { removeWallByPoints, setPosition } = useWallStore(); const { wallStore } = useSceneContext();
const { removeWallByPoints, setPosition } = wallStore();
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null); const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore(); const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore();
@@ -79,6 +80,7 @@ function Line({ points }: Readonly<LineProps>) {
if (toolMode === '2D-Delete') { if (toolMode === '2D-Delete') {
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') { if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
removeWallByPoints(points); removeWallByPoints(points);
setHoveredLine(null);
} }
gl.domElement.style.cursor = 'default'; gl.domElement.style.cursor = 'default';
} }

View File

@@ -1,6 +1,5 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useWallStore } from '../../../../store/builder/useWallStore';
import { useSceneContext } from '../../../scene/sceneContext'; import { useSceneContext } from '../../../scene/sceneContext';
const POINT_SNAP_THRESHOLD = 0.5; // Distance threshold for snapping in meters const POINT_SNAP_THRESHOLD = 0.5; // Distance threshold for snapping in meters
@@ -12,9 +11,9 @@ const ANGLE_SNAP_DISTANCE_THRESHOLD = 0.5; // Distance threshold for snapping i
const CAN_ANGLE_SNAP = true; // Whether snapping is enabled or not const CAN_ANGLE_SNAP = true; // Whether snapping is enabled or not
export const usePointSnapping = (currentPoint: { uuid: string, pointType: string, position: [number, number, number] } | null) => { export const usePointSnapping = (currentPoint: { uuid: string, pointType: string, position: [number, number, number] } | null) => {
const { aisleStore } = useSceneContext(); const { aisleStore, wallStore } = useSceneContext();
const { aisles, getConnectedPoints: getConnectedAislePoints } = aisleStore(); const { aisles, getConnectedPoints: getConnectedAislePoints } = aisleStore();
const { walls, getConnectedPoints: getConnectedWallPoints } = useWallStore(); const { walls, getConnectedPoints: getConnectedWallPoints } = wallStore();
// Wall Snapping // Wall Snapping

View File

@@ -6,7 +6,6 @@ import { DragControls } from '@react-three/drei';
import { useThree } from '@react-three/fiber'; import { useThree } from '@react-three/fiber';
import { useBuilderStore } from '../../../store/builder/useBuilderStore'; import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { usePointSnapping } from './helpers/usePointSnapping'; import { usePointSnapping } from './helpers/usePointSnapping';
import { useWallStore } from '../../../store/builder/useWallStore';
import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi'; import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { createAisleApi } from '../../../services/factoryBuilder/aisle/createAisleApi'; import { createAisleApi } from '../../../services/factoryBuilder/aisle/createAisleApi';
@@ -20,9 +19,9 @@ function Point({ point }: { readonly point: Point }) {
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null); const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { aisleStore } = useSceneContext(); const { aisleStore, wallStore } = useSceneContext();
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore(); const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
const { setPosition: setWallPosition, removePoint: removeWallPoint } = useWallStore(); const { setPosition: setWallPosition, removePoint: removeWallPoint } = wallStore();
const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position }); const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
const { hoveredPoint, setHoveredPoint } = useBuilderStore(); const { hoveredPoint, setHoveredPoint } = useBuilderStore();
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
@@ -31,6 +30,10 @@ function Point({ point }: { readonly point: Point }) {
const boxScale: [number, number, number] = Constants.pointConfig.boxScale; const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
const colors = getColor(point); const colors = getColor(point);
useEffect(() => {
gl.domElement.style.cursor = 'default';
}, [toolMode])
function getColor(point: Point) { function getColor(point: Point) {
if (point.pointType === 'Aisle') { if (point.pointType === 'Aisle') {
return { return {

View File

@@ -1,18 +1,26 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Base } from '@react-three/csg';
import { useMemo, useRef, useState } from 'react'; import { useMemo, useRef, useState } from 'react';
import * as Constants from '../../../../../types/world/worldConstants'; import { Decal, MeshDiscardMaterial } from '@react-three/drei';
import { useFrame, useThree } from '@react-three/fiber';
import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png'; import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png';
import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg'; import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg';
import { useWallStore } from '../../../../../store/builder/useWallStore';
import useModuleStore from '../../../../../store/useModuleStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useWallClassification } from './helpers/useWallClassification'; import { useWallClassification } from './helpers/useWallClassification';
import { useFrame, useThree } from '@react-three/fiber'; import { useToggleView, useWallVisibility } from '../../../../../store/builder/store';
import { useWallVisibility } from '../../../../../store/builder/store'; import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
import { Decal } from '@react-three/drei'; import * as Constants from '../../../../../types/world/worldConstants';
import { Base } from '@react-three/csg'; import DecalInstance from '../../../Decal/decalInstance';
function Wall({ wall }: { readonly wall: Wall }) { function Wall({ wall }: { readonly wall: Wall }) {
const { walls } = useWallStore(); const { wallStore } = useSceneContext();
const { walls, addDecal } = wallStore();
const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore();
const { togglView } = useToggleView();
const { activeModule } = useModuleStore();
const { camera } = useThree(); const { camera } = useThree();
const { wallVisibility } = useWallVisibility(); const { wallVisibility } = useWallVisibility();
const { getWallType, isWallFlipped } = useWallClassification(walls); const { getWallType, isWallFlipped } = useWallClassification(walls);
@@ -67,7 +75,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
new THREE.MeshStandardMaterial({ new THREE.MeshStandardMaterial({
color: Constants.wallConfig.defaultColor, color: Constants.wallConfig.defaultColor,
side: THREE.DoubleSide, side: THREE.DoubleSide,
map: wall.outsideMaterial === 'Default Material`' ? defaultWallTexture : material1WallTexture, map: wall.outsideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture,
}), }),
]; ];
}, [defaultWallTexture, material1WallTexture, wall]); }, [defaultWallTexture, material1WallTexture, wall]);
@@ -100,29 +108,52 @@ function Wall({ wall }: { readonly wall: Wall }) {
geometry={geometry} geometry={geometry}
position={[centerX, centerY, centerZ]} position={[centerX, centerY, centerZ]}
rotation={[0, -angle, 0]} rotation={[0, -angle, 0]}
userData={wall}
> >
{materials.map((material, index) => ( {materials.map((material, index) => (
<primitive key={index} visible={visible} object={material} attach={`material-${index}`} /> <primitive key={index} visible={visible} object={material} attach={`material-${index}`} />
))} ))}
{wall.decals.map((decal) => {
return (
<Decal
// debug
position={[decal.decalPosition[0], decal.decalPosition[1], wall.wallThickness / 2]}
rotation={[0, 0, decal.decalRotation]}
scale={[decal.decalScale, decal.decalScale, 0.001]}
>
<meshBasicMaterial
map={material1WallTexture}
side={THREE.DoubleSide}
polygonOffset
polygonOffsetFactor={-1}
/>
</Decal>
)
})}
</Base> </Base>
<mesh
castShadow
geometry={geometry}
position={[centerX, centerY, centerZ]}
rotation={[0, -angle, 0]}
userData={wall}
name={`WallReference_${wall.wallUuid}`}
onClick={(e) => {
if (visible && !togglView && activeModule === 'builder') {
if (e.object.userData.wallUuid) {
setSelectedWall(e.object);
setSelectedDecal(null);
if (wall.decals.length > 0) return;
const decal: Decal = {
decalUuid: THREE.MathUtils.generateUUID(),
decalName: 'Decal',
decalId: 'Default Decal',
decalPosition: [0, 0, wall.wallThickness / 2 + 0.001],
decalRotation: 0,
decalScale: 1,
decalType: { type: 'Wall', wallUuid: wall.wallUuid }
}
addDecal(wall.wallUuid, decal);
}
}
}}
onPointerMissed={() => {
if (selectedWall && selectedWall.userData.wallUuid === wall.wallUuid) {
setSelectedWall(null);
}
}}
>
<MeshDiscardMaterial />
{wall.decals.map((decal) => (
<DecalInstance visible={visible} key={decal.decalUuid} decal={decal} />
))}
</mesh>
</mesh> </mesh>
); );
} }

View File

@@ -2,9 +2,10 @@ import React, { useEffect, useMemo } from 'react';
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three'; import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
import { Geometry } from '@react-three/csg'; import { Geometry } from '@react-three/csg';
import { Html, Extrude } from '@react-three/drei'; import { Html, Extrude } from '@react-three/drei';
import { useWallStore } from '../../../../store/builder/useWallStore' import { useLoader } from '@react-three/fiber';
import { useWallClassification } from './instance/helpers/useWallClassification'; import { useSceneContext } from '../../../scene/sceneContext';
import { useToggleView } from '../../../../store/builder/store'; import { useToggleView } from '../../../../store/builder/store';
import { useWallClassification } from './instance/helpers/useWallClassification';
import Line from '../../line/line'; import Line from '../../line/line';
import Point from '../../point/point'; import Point from '../../point/point';
import WallInstance from './instance/wallInstance'; import WallInstance from './instance/wallInstance';
@@ -12,10 +13,10 @@ import * as Constants from '../../../../types/world/worldConstants';
import texturePath from "../../../../assets/textures/floor/white.png"; import texturePath from "../../../../assets/textures/floor/white.png";
import texturePathDark from "../../../../assets/textures/floor/black.png"; import texturePathDark from "../../../../assets/textures/floor/black.png";
import { useLoader } from '@react-three/fiber';
function WallInstances() { function WallInstances() {
const { walls } = useWallStore(); const { wallStore } = useSceneContext();
const { walls } = wallStore();
const { rooms } = useWallClassification(walls) const { rooms } = useWallClassification(walls)
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
@@ -41,7 +42,7 @@ function WallInstances() {
return ( return (
<> <>
{!toggleView && ( {!toggleView && walls.length > 1 && (
<> <>
<mesh name='Walls-Group'> <mesh name='Walls-Group'>
<Geometry useGroups> <Geometry useGroups>

View File

@@ -3,7 +3,7 @@ import { useEffect, useMemo, useRef, useState } from 'react'
import { useThree } from '@react-three/fiber'; import { useThree } from '@react-three/fiber';
import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store'; import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
import * as Constants from '../../../../types/world/worldConstants'; import * as Constants from '../../../../types/world/worldConstants';
import { useWallStore } from '../../../../store/builder/useWallStore'; import { useSceneContext } from '../../../scene/sceneContext';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore'; import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
import ReferencePoint from '../../point/reference/referencePoint'; import ReferencePoint from '../../point/reference/referencePoint';
import ReferenceWall from './referenceWall'; import ReferenceWall from './referenceWall';
@@ -16,7 +16,8 @@ function WallCreator() {
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { activeLayer } = useActiveLayer(); const { activeLayer } = useActiveLayer();
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const { addWall, getWallPointById, removeWall, getWallByPoints } = useWallStore(); const { wallStore } = useSceneContext();
const { addWall, getWallPointById, removeWall, getWallByPoints } = wallStore();
const drag = useRef(false); const drag = useRef(false);
const isLeftMouseDown = useRef(false); const isLeftMouseDown = useRef(false);
const { wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint } = useBuilderStore(); const { wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint } = useBuilderStore();

View File

@@ -1,7 +1,22 @@
import { useEffect } from 'react';
import { useToggleView } from '../../../store/builder/store'
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import WallCreator from './wallCreator/wallCreator' import WallCreator from './wallCreator/wallCreator'
import WallInstances from './Instances/wallInstances' import WallInstances from './Instances/wallInstances'
import useModuleStore from '../../../store/useModuleStore';
function WallGroup() { function WallGroup() {
const { togglView } = useToggleView();
const { setSelectedWall, setSelectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore();
useEffect(() => {
if (togglView || activeModule !== 'builder') {
setSelectedWall(null);
setSelectedDecal(null);
}
}, [togglView, activeModule])
return ( return (
<> <>

View File

@@ -15,7 +15,7 @@ export default function PostProcessing() {
const { selectedWallItem } = useSelectedWallItem(); const { selectedWallItem } = useSelectedWallItem();
const { selectedFloorItem } = useSelectedFloorItem(); const { selectedFloorItem } = useSelectedFloorItem();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { selectedAisle } = useBuilderStore(); const { selectedAisle, selectedWall, selectedDecal } = useBuilderStore();
function flattenChildren(children: any[]) { function flattenChildren(children: any[]) {
const allChildren: any[] = []; const allChildren: any[] = [];
@@ -40,6 +40,10 @@ export default function PostProcessing() {
// console.log('selectedAisle: ', selectedAisle); // console.log('selectedAisle: ', selectedAisle);
}, [selectedAisle]) }, [selectedAisle])
useEffect(() => {
// console.log('selectedWall: ', selectedWall);
}, [selectedWall])
return ( return (
<EffectComposer autoClear={false}> <EffectComposer autoClear={false}>
<N8AO <N8AO
@@ -66,6 +70,36 @@ export default function PostProcessing() {
xRay={false} xRay={false}
/> />
)} )}
{selectedWall && (
<Outline
selection={selectedWall}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{selectedDecal && (
<Outline
selection={selectedDecal}
selectionLayer={10}
width={2000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
blur={true}
xRay={true}
/>
)}
{deletableFloorItem && ( {deletableFloorItem && (
<Outline <Outline
selection={flattenChildren(deletableFloorItem.children)} selection={flattenChildren(deletableFloorItem.children)}

View File

@@ -1,7 +1,11 @@
import { createContext, useContext, useMemo } from 'react'; import { createContext, useContext, useMemo } from 'react';
import { createAssetStore, AssetStoreType } from '../../store/builder/useAssetStore'; import { createAssetStore, AssetStoreType } from '../../store/builder/useAssetStore';
import { createWallAssetStore, WallAssetStoreType } from '../../store/builder/useWallAssetStore';
import { createWallStore, WallStoreType } from '../../store/builder/useWallStore';
import { createAisleStore, AisleStoreType } from '../../store/builder/useAisleStore'; import { createAisleStore, AisleStoreType } from '../../store/builder/useAisleStore';
import { createZoneStore, ZoneStoreType } from '../../store/builder/useZoneStore';
import { createFloorStore, FloorStoreType } from '../../store/builder/useFloorStore';
import { createEventStore, EventStoreType } from '../../store/simulation/useEventsStore'; import { createEventStore, EventStoreType } from '../../store/simulation/useEventsStore';
import { createProductStore, ProductStoreType } from '../../store/simulation/useProductStore'; import { createProductStore, ProductStoreType } from '../../store/simulation/useProductStore';
@@ -16,7 +20,11 @@ import { createStorageUnitStore, StorageUnitStoreType } from '../../store/simula
type SceneContextValue = { type SceneContextValue = {
assetStore: AssetStoreType, assetStore: AssetStoreType,
wallAssetStore: WallAssetStoreType,
wallStore: WallStoreType,
aisleStore: AisleStoreType, aisleStore: AisleStoreType,
zoneStore: ZoneStoreType,
floorStore: FloorStoreType,
eventStore: EventStoreType, eventStore: EventStoreType,
productStore: ProductStoreType, productStore: ProductStoreType,
@@ -44,7 +52,11 @@ export function SceneProvider({
}) { }) {
const assetStore = useMemo(() => createAssetStore(), []); const assetStore = useMemo(() => createAssetStore(), []);
const wallAssetStore = useMemo(() => createWallAssetStore(), []);
const wallStore = useMemo(() => createWallStore(), []);
const aisleStore = useMemo(() => createAisleStore(), []); const aisleStore = useMemo(() => createAisleStore(), []);
const zoneStore = useMemo(() => createZoneStore(), []);
const floorStore = useMemo(() => createFloorStore(), []);
const eventStore = useMemo(() => createEventStore(), []); const eventStore = useMemo(() => createEventStore(), []);
const productStore = useMemo(() => createProductStore(), []); const productStore = useMemo(() => createProductStore(), []);
@@ -58,7 +70,11 @@ export function SceneProvider({
const clearStores = useMemo(() => () => { const clearStores = useMemo(() => () => {
assetStore.getState().clearAssets(); assetStore.getState().clearAssets();
wallAssetStore.getState().clearWallAssets();
wallStore.getState().clearWalls();
aisleStore.getState().clearAisles(); aisleStore.getState().clearAisles();
zoneStore.getState().clearZones();
floorStore.getState().clearFloors();
eventStore.getState().clearEvents(); eventStore.getState().clearEvents();
productStore.getState().clearProducts(); productStore.getState().clearProducts();
materialStore.getState().clearMaterials(); materialStore.getState().clearMaterials();
@@ -67,12 +83,16 @@ export function SceneProvider({
conveyorStore.getState().clearConveyors(); conveyorStore.getState().clearConveyors();
vehicleStore.getState().clearVehicles(); vehicleStore.getState().clearVehicles();
storageUnitStore.getState().clearStorageUnits(); storageUnitStore.getState().clearStorageUnits();
}, [assetStore, aisleStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore]); }, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore]);
const contextValue = useMemo(() => ( const contextValue = useMemo(() => (
{ {
assetStore, assetStore,
wallAssetStore,
wallStore,
aisleStore, aisleStore,
zoneStore,
floorStore,
eventStore, eventStore,
productStore, productStore,
materialStore, materialStore,
@@ -84,7 +104,7 @@ export function SceneProvider({
clearStores, clearStores,
layout layout
} }
), [assetStore, aisleStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, clearStores, layout]); ), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, clearStores, layout]);
return ( return (
<SceneContext.Provider value={contextValue}> <SceneContext.Provider value={contextValue}>

View File

@@ -106,17 +106,17 @@ export default function Dropped3dWidgets() {
const hasEntered = { current: false }; const hasEntered = { current: false };
const handleDragEnter = (event: DragEvent) => { const handleDragEnter = (event: DragEvent) => {
console.log("dragEnter");
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
if (hasEntered.current || !widgetSelect.startsWith("ui")) return; if (hasEntered.current || !widgetSelect.startsWith("ui")) return;
console.log('hasEntered.current : ', hasEntered.current );
hasEntered.current = true; hasEntered.current = true;
const group1 = scene.getObjectByName("itemsGroup"); // const group1 = scene.getObjectByName("itemsGroup");
console.log('group1: ', group1); //
if (!group1) return; // if (!group1) return;
const rect = canvasElement.getBoundingClientRect(); const rect = canvasElement.getBoundingClientRect();
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
@@ -139,7 +139,7 @@ export default function Dropped3dWidgets() {
intersect.object.type !== "GridHelper" intersect.object.type !== "GridHelper"
); );
console.log('intersects: ', intersects);
if (intersects.length > 0) { if (intersects.length > 0) {
const { x, y, z } = intersects[0].point; const { x, y, z } = intersects[0].point;
const newWidget: WidgetData = { const newWidget: WidgetData = {
@@ -238,10 +238,11 @@ export default function Dropped3dWidgets() {
organization, organization,
widget: newWidget, widget: newWidget,
zoneUuid: selectedZone.zoneUuid, zoneUuid: selectedZone.zoneUuid,
version: selectedVersion?.versionId || '', versionId: selectedVersion?.versionId || '',
projectId, projectId,
userId userId
}; };
if (visualizationSocket) { if (visualizationSocket) {
visualizationSocket.emit("v1:viz-3D-widget:add", add3dWidget); visualizationSocket.emit("v1:viz-3D-widget:add", add3dWidget);
@@ -276,7 +277,7 @@ export default function Dropped3dWidgets() {
const widgetToDuplicate = activeZoneWidgets.find( const widgetToDuplicate = activeZoneWidgets.find(
(w: WidgetData) => w.id === rightClickSelected (w: WidgetData) => w.id === rightClickSelected
); );
console.log("3d widget to duplecate", widgetToDuplicate);
if (!widgetToDuplicate) return; if (!widgetToDuplicate) return;
const newWidget: any = { const newWidget: any = {
@@ -301,6 +302,7 @@ export default function Dropped3dWidgets() {
projectId, projectId,
userId userId
}; };
if (visualizationSocket) { if (visualizationSocket) {
visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget); visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
} }
@@ -470,20 +472,20 @@ export default function Dropped3dWidgets() {
} }
// if (rightSelect === "Vertical Move") { // if (rightSelect === "Vertical Move") {
// // console.log('rightSelect: ', rightSelect); // //
// // console.log('floorPlanesVertical: ', floorPlanesVertical); // //
// // console.log('planeIntersect.current: ', planeIntersect.current); // //
// // const intersect = raycaster.ray.intersectPlane( // // const intersect = raycaster.ray.intersectPlane(
// // floorPlanesVertical, // // floorPlanesVertical,
// // planeIntersect.current // // planeIntersect.current
// // ); // // );
// // console.log('intersect: ', intersect); // //
// let intersect = event.clientY // let intersect = event.clientY
// if (intersect && typeof intersectcontextmenu === "number") { // if (intersect && typeof intersectcontextmenu === "number") {
// console.log('intersect: ', intersect); //
// const diff = intersect - intersectcontextmenu; // const diff = intersect - intersectcontextmenu;
// const unclampedY = selectedWidget.position[1] + diff; // const unclampedY = selectedWidget.position[1] + diff;
// const newY = Math.max(0, unclampedY); // Prevent going below floor (y=0) // const newY = Math.max(0, unclampedY); // Prevent going below floor (y=0)
@@ -495,7 +497,7 @@ export default function Dropped3dWidgets() {
// newY, // newY,
// selectedWidget.position[2], // selectedWidget.position[2],
// ]; // ];
// console.log('newPosition: ', newPosition); //
// updateWidgetPosition(selectedzoneUuid, rightClickSelected, newPosition); // updateWidgetPosition(selectedzoneUuid, rightClickSelected, newPosition);

View File

@@ -18,6 +18,8 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import useChartStore from "../../../../../store/visualization/useChartStore"; import useChartStore from "../../../../../store/visualization/useChartStore";
import { getUserData } from "../../../../../functions/getUserData"; import { getUserData } from "../../../../../functions/getUserData";
import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput"; import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { useParams } from "react-router-dom";
// Register ChartJS components // Register ChartJS components
ChartJS.register( ChartJS.register(
@@ -70,6 +72,9 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({
}); });
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const { userName, userId, organization, email } = getUserData(); const { userName, userId, organization, email } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams()
// Chart data for a week // Chart data for a week
const defaultChartData = { const defaultChartData = {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], // Days of the week
@@ -171,12 +176,15 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (id !== "") { if (id !== "") {
let response = await get3dWidgetInput(id, organization) let response = await get3dWidgetInput(id, organization, projectId, selectedVersion?.versionId || "")
console.log('response: ', response);
if (response.message === "Widget not found") {
return
}
if (response) { if (response) {
setmeasurements(response.data.Data.measurements); setmeasurements(response.Datastructure.measurements);
setDuration(response.data.Data.duration); setDuration(response.Datastructure.duration);
setName(response.data.widgetName); setName(response.widgetName);
} }
// try { // try {
// const response = await axios.get( // const response = await axios.get(
@@ -215,7 +223,7 @@ const ProductionCapacity: React.FC<ProductionCapacityProps> = ({
scale={scale} scale={scale}
rotation={rotation} rotation={rotation}
// class // class
wrapperClass="pointer-none" // wrapperClass="pointer-none"
// other // other
transform transform
zIndexRange={[1, 0]} zIndexRange={[1, 0]}

View File

@@ -19,6 +19,8 @@ import useChartStore from "../../../../../store/visualization/useChartStore";
import { WavyIcon } from "../../../../../components/icons/3dChartIcons"; import { WavyIcon } from "../../../../../components/icons/3dChartIcons";
import { getUserData } from "../../../../../functions/getUserData"; import { getUserData } from "../../../../../functions/getUserData";
import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput"; import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { useParams } from "react-router-dom";
// Register Chart.js components // Register Chart.js components
ChartJS.register( ChartJS.register(
@@ -79,6 +81,9 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({
datasets: [], datasets: [],
}); });
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams()
const { userName, userId, organization, email } = getUserData(); const { userName, userId, organization, email } = getUserData();
// Improved sample data for the smooth curve graph (single day) // Improved sample data for the smooth curve graph (single day)
const graphData: ChartData<"line"> = { const graphData: ChartData<"line"> = {
@@ -200,8 +205,11 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (id !== "") { if (id !== "") {
let response = await get3dWidgetInput(id, organization) let response = await get3dWidgetInput(id, organization, projectId, selectedVersion?.versionId || "")
console.log('response: ', response);
if (response.message === "Widget not found") {
return
}
if (response) { if (response) {
setmeasurements(response.data.Data.measurements); setmeasurements(response.data.Data.measurements);
setDuration(response.data.Data.duration); setDuration(response.data.Data.duration);
@@ -216,11 +224,11 @@ const ReturnOfInvestment: React.FC<ReturnOfInvestmentProps> = ({
// setDuration(response.data.Data.duration); // setDuration(response.data.Data.duration);
// setName(response.data.widgetName); // setName(response.data.widgetName);
// } else { // } else {
// // console.log("Unexpected response:", response); // //
// } // }
// } catch (error) { // } catch (error) {
// echo.error("Failed to fetch saved inputs"); // echo.error("Failed to fetch saved inputs");
// console.error("There was an error!", error); //
// } // }
} }
}; };

View File

@@ -7,6 +7,8 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import useChartStore from "../../../../../store/visualization/useChartStore"; import useChartStore from "../../../../../store/visualization/useChartStore";
import { getUserData } from "../../../../../functions/getUserData"; import { getUserData } from "../../../../../functions/getUserData";
import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput"; import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { useParams } from "react-router-dom";
// import image from "../../../../assets/image/temp/image.png"; // import image from "../../../../assets/image/temp/image.png";
interface StateWorkingProps { interface StateWorkingProps {
@@ -41,6 +43,9 @@ const StateWorking: React.FC<StateWorkingProps> = ({
const [datas, setDatas] = useState<any>({}); const [datas, setDatas] = useState<any>({});
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const { userName, userId, organization, email } = getUserData(); const { userName, userId, organization, email } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams()
// const datas = [ // const datas = [
// { key: "Oil Tank:", value: "24/341" }, // { key: "Oil Tank:", value: "24/341" },
// { key: "Oil Refin:", value: 36.023 }, // { key: "Oil Refin:", value: 36.023 },
@@ -78,12 +83,15 @@ const StateWorking: React.FC<StateWorkingProps> = ({
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (id !== "") { if (id !== "") {
let response = await get3dWidgetInput(id, organization) let response = await get3dWidgetInput(id, organization, projectId, selectedVersion?.versionId || "")
console.log('response: ', response);
if (response.message === "Widget not found") {
return
}
if (response) { if (response) {
setmeasurements(response.data.Data.measurements); setmeasurements(response.Datastructure.measurements);
setDuration(response.data.Data.duration); setDuration(response.Datastructure.duration);
setName(response.data.widgetName); setName(response.widgetName);
} }
// try { // try {
// const response = await axios.get( // const response = await axios.get(
@@ -94,17 +102,17 @@ const StateWorking: React.FC<StateWorkingProps> = ({
// setDuration(response.data.Data.duration); // setDuration(response.data.Data.duration);
// setName(response.data.widgetName); // setName(response.data.widgetName);
// } else { // } else {
// // console.log("Unexpected response:", response); // //
// } // }
// } catch (error) { // } catch (error) {
// echo.error("Failed to fetch saved inputs"); // echo.error("Failed to fetch saved inputs");
// console.error("There was an error!", error); //
// } // }
} }
}; };
useEffect(() => { useEffect(() => {
fetchSavedInputes(); // fetchSavedInputes();
}, []); }, []);
useEffect(() => { useEffect(() => {

View File

@@ -21,6 +21,8 @@ import useChartStore from "../../../../../store/visualization/useChartStore";
import { ThroughputIcon } from "../../../../../components/icons/3dChartIcons"; import { ThroughputIcon } from "../../../../../components/icons/3dChartIcons";
import { getUserData } from "../../../../../functions/getUserData"; import { getUserData } from "../../../../../functions/getUserData";
import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput"; import { get3dWidgetInput } from "../../../../../services/visulization/zone/get3dWidgetInput";
import { useVersionContext } from "../../../../builder/version/versionContext";
import { useParams } from "react-router-dom";
// Register Chart.js components // Register Chart.js components
ChartJS.register( ChartJS.register(
@@ -83,6 +85,9 @@ const Throughput: React.FC<ThroughputProps> = ({
}); });
const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL;
const { userName, userId, organization, email } = getUserData(); const { userName, userId, organization, email } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams()
@@ -180,12 +185,15 @@ const Throughput: React.FC<ThroughputProps> = ({
const fetchSavedInputes = async () => { const fetchSavedInputes = async () => {
if (id !== "") { if (id !== "") {
let response = await get3dWidgetInput(id, organization) let response = await get3dWidgetInput(id, organization, projectId, selectedVersion?.versionId || "")
console.log('response: ', response);
if (response.message === "Widget not found") {
return
}
if (response) { if (response) {
setmeasurements(response.data.Data.measurements); setmeasurements(response.Datastructure.measurements);
setDuration(response.data.Data.duration); setDuration(response.Datastructure.duration);
setName(response.data.widgetName); setName(response.widgetName);
} }
// try { // try {
// const response = await axios.get( // const response = await axios.get(
@@ -196,17 +204,17 @@ const Throughput: React.FC<ThroughputProps> = ({
// setDuration(response.data.Data.duration); // setDuration(response.data.Data.duration);
// setName(response.data.widgetName); // setName(response.data.widgetName);
// } else { // } else {
// // console.log("Unexpected response:", response); // //
// } // }
// } catch (error) { // } catch (error) {
// echo.error("Failed to fetch saved inputs"); // echo.error("Failed to fetch saved inputs");
// console.error("There was an error!", error); //
// } // }
} }
}; };
useEffect(() => { useEffect(() => {
fetchSavedInputes(); // fetchSavedInputes();
}, []); }, []);
useEffect(() => { useEffect(() => {

View File

@@ -6,8 +6,10 @@ export const adding3dWidgets = async (
widget: {}, widget: {},
projectId?: string, projectId?: string,
versionId?: string versionId?: string
) => { ) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/widget3d/save`, { const response = await fetch(`${url_Backend_dwinzo}/api/V1/widget3d/save`, {
method: "POST", method: "POST",
@@ -20,15 +22,16 @@ export const adding3dWidgets = async (
body: JSON.stringify({ organization, zoneUuid, widget, projectId, versionId }), body: JSON.stringify({ organization, zoneUuid, widget, projectId, versionId }),
}); });
const newAccessToken = response.headers.get("x-access-token"); const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) { if (newAccessToken) {
//console.log("New token received:", newAccessToken); //
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
console.error("Failed to add 3dwidget in the zone");
} }
const result = await response.json(); const result = await response.json();
@@ -36,9 +39,9 @@ export const adding3dWidgets = async (
} catch (error) { } catch (error) {
echo.error("Failed to add 3d widget"); echo.error("Failed to add 3d widget");
if (error instanceof Error) { if (error instanceof Error) {
console.log(error.message);
} else { } else {
console.log("An unknown error occurred");
} }
} }
}; };

View File

@@ -2,9 +2,13 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR
export const get3dWidgetInput = async (chartId: string, organization: string, projectId?: string, versionId?: string) => { export const get3dWidgetInput = async (chartId: string, organization: string, projectId?: string, versionId?: string) => {
try { try {
const response = await fetch( const response = await fetch(
`${url_Backend_dwinzo}/api/v2/widget3D/${chartId}/${organization}`, `${url_Backend_dwinzo}/api/V1/widget3dData/${chartId}/${projectId}/${versionId}`,
{ {
method: "GET", method: "GET",
headers: { headers: {
@@ -15,9 +19,10 @@ export const get3dWidgetInput = async (chartId: string, organization: string, pr
}, },
} }
); );
const newAccessToken = response.headers.get("x-access-token"); const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) { if (newAccessToken) {
//console.log("New token received:", newAccessToken); //
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
@@ -25,10 +30,10 @@ export const get3dWidgetInput = async (chartId: string, organization: string, pr
throw new Error("Failed to fetch zoneDatas"); throw new Error("Failed to fetch zoneDatas");
} }
const result = await response.json(); const result = await response.json();
console.log('result: ', result);
return result; return result;
} catch (error: any) { } catch (error: any) {
echo.error("Failed to fetch 2d widget data"); echo.error("Failed to fetch 2d widget data");
console.log(error.message);
} }
}; };

View File

@@ -3,74 +3,64 @@ import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
interface BuilderState { interface BuilderState {
// Common properties // Point & Line Interaction
hoveredPoint: Point | null; hoveredPoint: Point | null;
snappedPoint: Point | null; snappedPoint: Point | null;
snappedPosition: [number, number, number] | null; snappedPosition: [number, number, number] | null;
hoveredLine: [Point, Point] | null; hoveredLine: [Point, Point] | null;
// Wall // Wall Settings
selectedWall: Object3D | null;
wallThickness: number; wallThickness: number;
wallHeight: number; wallHeight: number;
outsideMaterial: string; outsideMaterial: string;
insideMaterial: string; insideMaterial: string;
setWallThickness: (thickness: number) => void; // Decal Settings
setWallHeight: (height: number) => void; selectedDecal: Object3D | null;
setWallMaterial: (material: string, side: 'inside' | 'outside') => void;
// Aisle
// Aisle General
selectedAisle: Object3D | null; selectedAisle: Object3D | null;
aisleType: AisleTypes; aisleType: AisleTypes;
aisleWidth: number; aisleWidth: number;
aisleColor: AisleColors; aisleColor: AisleColors;
// Dashed aisle properties // Aisle Specific Styles
dashLength: number; dashLength: number;
gapLength: number; gapLength: number;
// Dotted aisle properties
dotRadius: number; dotRadius: number;
// Arrows aisle properties
aisleLength: number; aisleLength: number;
// Junction aisle properties
isFlipped: boolean; isFlipped: boolean;
// Setters for common properties // Setters - Point/Line
setHoveredPoint: (point: Point | null) => void; setHoveredPoint: (point: Point | null) => void;
setSnappedPoint: (point: Point | null) => void; setSnappedPoint: (point: Point | null) => void;
setSnappedPosition: (position: [number, number, number] | null) => void; setSnappedPosition: (position: [number, number, number] | null) => void;
setHoveredLine: (line: [Point, Point] | null) => void; setHoveredLine: (line: [Point, Point] | null) => void;
setSelectedAisle: (aisle: Object3D | null) => void; // Setters - Wall
setSelectedWall: (wall: Object3D | null) => void;
setWallThickness: (thickness: number) => void;
setWallHeight: (height: number) => void;
setWallMaterial: (material: string, side: 'inside' | 'outside') => void;
// Setters - Decal
setSelectedDecal: (decal: Object3D | null) => void;
// Setters - Aisle General
setSelectedAisle: (aisle: Object3D | null) => void;
setAisleType: (type: AisleTypes) => void; setAisleType: (type: AisleTypes) => void;
setAisleWidth: (width: number) => void; setAisleWidth: (width: number) => void;
setAisleColor: (color: AisleColors) => void; setAisleColor: (color: AisleColors) => void;
// Setters for dashed aisle // Setters - Aisle Specific
setDashLength: (length: number) => void; setDashLength: (length: number) => void;
setGapLength: (length: number) => void; setGapLength: (length: number) => void;
// Setters for dotted aisle
setDotRadius: (radius: number) => void; setDotRadius: (radius: number) => void;
// Setters for arrows aisle
setAisleLength: (length: number) => void; setAisleLength: (length: number) => void;
// Setters for junction aisle
setIsFlipped: (isFlipped: boolean) => void; setIsFlipped: (isFlipped: boolean) => void;
// Batch setters // Batch Setters
setDashedAisleProperties: (width: number, dashLength: number, gapLength: number) => void; setDashedAisleProperties: (width: number, dashLength: number, gapLength: number) => void;
setDottedAisleProperties: (width: number, dotRadius: number, gapLength: number) => void; setDottedAisleProperties: (width: number, dotRadius: number, gapLength: number) => void;
setArrowsAisleProperties: (width: number, aisleLength: number, gapLength: number) => void; setArrowsAisleProperties: (width: number, aisleLength: number, gapLength: number) => void;
@@ -79,20 +69,64 @@ interface BuilderState {
export const useBuilderStore = create<BuilderState>()( export const useBuilderStore = create<BuilderState>()(
immer((set) => ({ immer((set) => ({
// Default values // === Defaults ===
hoveredPoint: null, hoveredPoint: null,
snappedPoint: null, snappedPoint: null,
snappedPosition: null, snappedPosition: null,
hoveredLine: null, hoveredLine: null,
// Wall selectedWall: null,
wallThickness: 0.5, wallThickness: 0.5,
wallHeight: 7, wallHeight: 7,
outsideMaterial: 'Default Material', outsideMaterial: 'Default Material',
insideMaterial: 'Default Material', insideMaterial: 'Material 1',
selectedDecal: null,
selectedAisle: null,
aisleType: 'solid-aisle',
aisleWidth: 0.1,
aisleColor: 'yellow',
dashLength: 0.5,
gapLength: 0.3,
dotRadius: 0.1,
aisleLength: 0.6,
isFlipped: false,
// === Setters: Point/Line ===
setHoveredPoint: (point: Point | null) => {
set((state) => {
state.hoveredPoint = point;
});
},
setSnappedPoint: (point: Point | null) => {
set((state) => {
state.snappedPoint = point;
});
},
setSnappedPosition: (position: [number, number, number] | null) => {
set((state) => {
state.snappedPosition = position;
});
},
setHoveredLine: (line: [Point, Point] | null) => {
set((state) => {
state.hoveredLine = line;
})
},
// === Setters: Wall ===
setSelectedWall: (wall: Object3D | null) => {
set((state) => {
state.selectedWall = wall;
})
},
setWallThickness: (thickness: number) => { setWallThickness: (thickness: number) => {
set((state) => { set((state) => {
@@ -113,44 +147,15 @@ export const useBuilderStore = create<BuilderState>()(
}); });
}, },
// Aisle // === Setters: Decal ===
selectedAisle: null, setSelectedDecal: (decal: Object3D | null) => {
aisleType: 'solid-aisle',
aisleWidth: 0.1,
aisleColor: 'yellow',
dashLength: 0.5,
gapLength: 0.3,
dotRadius: 0.1,
aisleLength: 0.6,
isFlipped: false,
// Individual setters
setHoveredPoint: (point: Point | null) => {
set((state) => { set((state) => {
state.hoveredPoint = point; state.selectedDecal = decal;
});
},
setHoveredLine: (line: [Point, Point] | null) => {
set((state) => {
state.hoveredLine = line;
}) })
}, },
setSnappedPoint: (point: Point | null) => { // === Setters: Aisle General ===
set((state) => {
state.snappedPoint = point;
});
},
setSnappedPosition: (position: [number, number, number] | null) => {
set((state) => {
state.snappedPosition = position;
});
},
setSelectedAisle: (aisle: Object3D | null) => { setSelectedAisle: (aisle: Object3D | null) => {
set((state) => { set((state) => {
@@ -163,73 +168,78 @@ export const useBuilderStore = create<BuilderState>()(
state.aisleType = type; state.aisleType = type;
}); });
}, },
setAisleWidth: (width) => { setAisleWidth: (width) => {
set((state) => { set((state) => {
state.aisleWidth = width; state.aisleWidth = width;
}); });
}, },
setAisleColor: (color) => { setAisleColor: (color) => {
set((state) => { set((state) => {
state.aisleColor = color; state.aisleColor = color;
}); });
}, },
// === Setters: Aisle Specific ===
setDashLength: (length) => { setDashLength: (length) => {
set((state) => { set((state) => {
state.dashLength = length; state.dashLength = length;
}); });
}, },
setGapLength: (length) => { setGapLength: (length) => {
set((state) => { set((state) => {
state.gapLength = length; state.gapLength = length;
}); });
}, },
setDotRadius: (radius) => { setDotRadius: (radius) => {
set((state) => { set((state) => {
state.dotRadius = radius; state.dotRadius = radius;
}); });
}, },
setAisleLength: (length) => { setAisleLength: (length) => {
set((state) => { set((state) => {
state.aisleLength = length; state.aisleLength = length;
}); });
}, },
setIsFlipped: (isFlipped) => { setIsFlipped: (isFlipped) => {
set((state) => { set((state) => {
state.isFlipped = isFlipped; state.isFlipped = isFlipped;
}); });
}, },
// Batch setters // === Batch Setters ===
setDashedAisleProperties: (width, dashLength, gapLength) => {
set((state) => { setDashedAisleProperties: (width, dashLength, gapLength) => set((state) => {
state.aisleType = 'dashed-aisle'; state.aisleType = 'dashed-aisle';
state.aisleWidth = width; state.aisleWidth = width;
state.dashLength = dashLength; state.dashLength = dashLength;
state.gapLength = gapLength; state.gapLength = gapLength;
}); }),
},
setDottedAisleProperties: (width, dotRadius, gapLength) => { setDottedAisleProperties: (width, dotRadius, gapLength) => set((state) => {
set((state) => { state.aisleType = 'dotted-aisle';
state.aisleType = 'dotted-aisle'; state.aisleWidth = width;
state.aisleWidth = width; state.dotRadius = dotRadius;
state.dotRadius = dotRadius; state.gapLength = gapLength;
state.gapLength = gapLength; }),
});
}, setArrowsAisleProperties: (width, aisleLength, gapLength) => set((state) => {
setArrowsAisleProperties: (width, aisleLength, gapLength) => { state.aisleType = 'arrows-aisle';
set((state) => { state.aisleWidth = width;
state.aisleType = 'arrows-aisle'; state.aisleLength = aisleLength;
state.aisleWidth = width; state.gapLength = gapLength;
state.aisleLength = aisleLength; }),
state.gapLength = gapLength;
}); setAisleProperties: (type, width, color) => set((state) => {
}, state.aisleType = type;
setAisleProperties: (type, width, color) => { state.aisleWidth = width;
set((state) => { state.aisleColor = color;
state.aisleType = type; })
state.aisleWidth = width;
state.aisleColor = color;
});
}
})) }))
); );

View File

@@ -0,0 +1,90 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface FloorStore {
floors: Floor[];
setFloors: (floors: Floor[]) => void;
addFloor: (floor: Floor) => void;
updateFloor: (uuid: string, updated: Partial<Floor>) => void;
removeFloor: (uuid: string) => void;
removePointFromFloors: (pointUuid: string) => void;
clearFloors: () => void;
setIsBeveled: (uuid: string, isBeveled: boolean) => void;
setBevelStrength: (uuid: string, strength: number) => void;
setDepth: (uuid: string, depth: number) => void;
setMaterial: (uuid: string, sideMaterial: string, topMaterial: string) => void;
getFloorById: (uuid: string) => Floor | undefined;
}
export const createFloorStore = () => {
return create<FloorStore>()(
immer((set, get) => ({
floors: [],
setFloors: (floors) => set(state => {
state.floors = floors;
}),
addFloor: (floor) => set(state => {
state.floors.push(floor);
}),
updateFloor: (uuid, updated) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
Object.assign(floor, updated);
}
}),
removeFloor: (uuid) => set(state => {
state.floors = state.floors.filter(f => f.floorUuid !== uuid);
}),
removePointFromFloors: (pointUuid) => set(state => {
for (const floor of state.floors) {
floor.points = floor.points.filter(p => p.pointUuid !== pointUuid);
}
}),
clearFloors: () => set(state => {
state.floors = [];
}),
setIsBeveled: (uuid, isBeveled) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
floor.isBeveled = isBeveled;
}
}),
setBevelStrength: (uuid, strength) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
floor.bevelStrength = strength;
}
}),
setDepth: (uuid, depth) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
floor.floorDepth = depth;
}
}),
setMaterial: (uuid, sideMaterial, topMaterial) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
floor.sideMaterial = sideMaterial;
floor.topMaterial = topMaterial;
}
}),
getFloorById: (uuid) => {
return get().floors.find(f => f.floorUuid === uuid);
},
}))
);
};
export type FloorStoreType = ReturnType<typeof createFloorStore>;

View File

@@ -0,0 +1,82 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface WallAssetStore {
wallAssets: WallAsset[];
setWallAssets: (assets: WallAsset[]) => void;
addWallAsset: (asset: WallAsset) => void;
updateWallAsset: (uuid: string, updated: Partial<WallAsset>) => void;
removeWallAsset: (uuid: string) => void;
clearWallAssets: () => void;
setVisibility: (uuid: string, isVisible: boolean) => void;
setLock: (uuid: string, isLocked: boolean) => void;
setOpacity: (uuid: string, opacity: number) => void;
getWallAssetById: (uuid: string) => WallAsset | undefined;
getAssetsByWall: (wallUuid: string) => WallAsset[];
}
export const createWallAssetStore = () => {
return create<WallAssetStore>()(
immer((set, get) => ({
wallAssets: [],
setWallAssets: (assets) => set(state => {
state.wallAssets = assets;
}),
addWallAsset: (asset) => set(state => {
state.wallAssets.push(asset);
}),
updateWallAsset: (uuid, updated) => set(state => {
const asset = state.wallAssets.find(a => a.modelUuid === uuid);
if (asset) {
Object.assign(asset, updated);
}
}),
removeWallAsset: (uuid) => set(state => {
state.wallAssets = state.wallAssets.filter(a => a.modelUuid !== uuid);
}),
clearWallAssets: () => {
set(state => {
state.wallAssets = [];
})
},
setVisibility: (uuid, isVisible) => set(state => {
const asset = state.wallAssets.find(a => a.modelUuid === uuid);
if (asset) {
asset.isVisible = isVisible;
}
}),
setLock: (uuid, isLocked) => set(state => {
const asset = state.wallAssets.find(a => a.modelUuid === uuid);
if (asset) {
asset.isLocked = isLocked;
}
}),
setOpacity: (uuid, opacity) => set(state => {
const asset = state.wallAssets.find(a => a.modelUuid === uuid);
if (asset) {
asset.opacity = opacity;
}
}),
getWallAssetById: (uuid) => {
return get().wallAssets.find(a => a.modelUuid === uuid);
},
getAssetsByWall: (wallUuid) => {
return get().wallAssets.filter(a => a.wallUuid === wallUuid);
},
}))
);
};
export type WallAssetStoreType = ReturnType<typeof createWallAssetStore>;

View File

@@ -0,0 +1,211 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface WallStore {
walls: Wall[];
setWalls: (walls: Wall[]) => void;
addWall: (wall: Wall) => void;
updateWall: (uuid: string, updated: Partial<Wall>) => void;
removeWall: (uuid: string) => void;
clearWalls: () => void;
removeWallByPoints: (Points: [Point, Point]) => Wall | undefined;
addDecal: (wallUuid: string, decal: Decal) => void;
updateDecal: (decalUuid: string, decal: Decal) => void;
removeDecal: (decalUuid: string) => void;
updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void;
updateDecalRotation: (decalUuid: string, rotation: number) => void;
updateDecalScale: (decalUuid: string, scale: number) => void;
removePoint: (pointUuid: string) => Wall[];
setPosition: (pointUuid: string, position: [number, number, number]) => void;
setLayer: (pointUuid: string, layer: number) => void;
getWallById: (uuid: string) => Wall | undefined;
getWallByPointId: (uuid: string) => Wall | undefined;
getWallByPoints: (points: Point[]) => Wall | undefined;
getWallPointById: (uuid: string) => Point | undefined;
getConnectedPoints: (uuid: string) => Point[];
}
export const createWallStore = () => {
return create<WallStore>()(
immer((set, get) => ({
walls: [],
setWalls: (walls) => set((state) => {
state.walls = walls;
}),
addWall: (wall) => set((state) => {
state.walls.push(wall);
}),
updateWall: (uuid, updated) => set((state) => {
const wall = state.walls.find(w => w.wallUuid === uuid);
if (wall) {
Object.assign(wall, updated);
}
}),
removeWall: (uuid) => set((state) => {
state.walls = state.walls.filter(w => w.wallUuid !== uuid);
}),
clearWalls: () => {
set((state) => {
state.walls = [];
})
},
removeWallByPoints: (points) => {
let removedWall: Wall | undefined;
const [pointA, pointB] = points;
set((state) => {
state.walls = state.walls.filter(wall => {
const wallPoints = wall.points.map(p => p.pointUuid);
const hasBothPoints = wallPoints.includes(pointA.pointUuid) && wallPoints.includes(pointB.pointUuid);
if (hasBothPoints) {
removedWall = JSON.parse(JSON.stringify(wall));
return false;
}
return true;
});
});
return removedWall;
},
addDecal: (wallUuid, decal) => set((state) => {
const wallToUpdate = state.walls.find(w => w.wallUuid === wallUuid);
if (wallToUpdate) {
wallToUpdate.decals.push(decal);
}
}),
updateDecal: (decalUuid, decal) => set((state) => {
for (const wall of state.walls) {
const decalToUpdate = wall.decals.find(d => d.decalUuid === decalUuid);
if (decalToUpdate) {
Object.assign(decalToUpdate, decal);
}
}
}),
removeDecal: (decalUuid) => set((state) => {
for (const wall of state.walls) {
wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid);
}
}),
updateDecalPosition: (decalUuid, position) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalPosition = position;
break;
}
}
}),
updateDecalRotation: (decalUuid, rotation) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalRotation = rotation;
break;
}
}
}),
updateDecalScale: (decalUuid, scale) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalScale = scale;
break;
}
}
}),
removePoint: (pointUuid) => {
const removedWalls: Wall[] = [];
set((state) => {
state.walls = state.walls.filter((wall) => {
const hasPoint = wall.points.some(p => p.pointUuid === pointUuid);
if (hasPoint) {
removedWalls.push(JSON.parse(JSON.stringify(wall)));
return false;
}
return true;
});
});
return removedWalls;
},
setPosition: (pointUuid, position) => set((state) => {
for (const wall of state.walls) {
const point = wall.points.find(p => p.pointUuid === pointUuid);
if (point) {
point.position = position;
}
}
}),
setLayer: (pointUuid, layer) => set((state) => {
for (const wall of state.walls) {
const point = wall.points.find(p => p.pointUuid === pointUuid);
if (point) {
point.layer = layer;
}
}
}),
getWallById: (uuid) => {
return get().walls.find(w => w.wallUuid === uuid);
},
getWallByPointId: (uuid) => {
for (const wall of get().walls) {
if (wall.points.some(p => p.pointUuid === uuid)) {
return wall;
}
}
return undefined;
},
getWallByPoints: (point) => {
for (const wall of get().walls) {
if (((wall.points[0].pointUuid === point[0].pointUuid) || (wall.points[1].pointUuid === point[0].pointUuid)) &&
((wall.points[0].pointUuid === point[1].pointUuid) || (wall.points[1].pointUuid === point[1].pointUuid))) {
return wall;
}
}
return undefined;
},
getWallPointById: (uuid) => {
for (const wall of get().walls) {
const point = wall.points.find(p => p.pointUuid === uuid);
if (point) return point;
}
return undefined;
},
getConnectedPoints: (uuid) => {
const connected: Point[] = [];
for (const wall of get().walls) {
for (const point of wall.points) {
if (point.pointUuid === uuid) {
connected.push(...wall.points.filter(p => p.pointUuid !== uuid));
}
}
}
return connected;
},
}))
)
}
export type WallStoreType = ReturnType<typeof createWallStore>;

View File

@@ -1,200 +0,0 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface WallStore {
walls: Wall[];
setWalls: (walls: Wall[]) => void;
addWall: (wall: Wall) => void;
updateWall: (uuid: string, updated: Partial<Wall>) => void;
removeWall: (uuid: string) => void;
removeWallByPoints: (Points: [Point, Point]) => Wall | undefined;
addDecal: (wallUuid: string, decal: Decal) => void;
updateDecal: (decalUuid: string, decal: Decal) => void;
removeDecal: (decalUuid: string) => void;
updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void;
updateDecalRotation: (decalUuid: string, rotation: number) => void;
updateDecalScale: (decalUuid: string, scale: number) => void;
removePoint: (pointUuid: string) => Wall[];
setPosition: (pointUuid: string, position: [number, number, number]) => void;
setLayer: (pointUuid: string, layer: number) => void;
getWallById: (uuid: string) => Wall | undefined;
getWallByPointId: (uuid: string) => Wall | undefined;
getWallByPoints: (points: Point[]) => Wall | undefined;
getWallPointById: (uuid: string) => Point | undefined;
getConnectedPoints: (uuid: string) => Point[];
}
export const useWallStore = create<WallStore>()(
immer((set, get) => ({
walls: [],
setWalls: (walls) => set((state) => {
state.walls = walls;
}),
addWall: (wall) => set((state) => {
state.walls.push(wall);
}),
updateWall: (uuid, updated) => set((state) => {
const wall = state.walls.find(w => w.wallUuid === uuid);
if (wall) {
Object.assign(wall, updated);
}
}),
removeWall: (uuid) => set((state) => {
state.walls = state.walls.filter(w => w.wallUuid !== uuid);
}),
removeWallByPoints: (points) => {
let removedWall: Wall | undefined;
const [pointA, pointB] = points;
set((state) => {
state.walls = state.walls.filter(wall => {
const wallPoints = wall.points.map(p => p.pointUuid);
const hasBothPoints = wallPoints.includes(pointA.pointUuid) && wallPoints.includes(pointB.pointUuid);
if (hasBothPoints) {
removedWall = JSON.parse(JSON.stringify(wall));
return false;
}
return true;
});
});
return removedWall;
},
addDecal: (wallUuid, decal) => set((state) => {
const wallToUpdate = state.walls.find(w => w.wallUuid === wallUuid);
if (wallToUpdate) {
wallToUpdate.decals.push(decal);
}
}),
updateDecal: (decalUuid, decal) => set((state) => {
for (const wall of state.walls) {
const decalToUpdate = wall.decals.find(d => d.decalUuid === decalUuid);
if (decalToUpdate) {
Object.assign(decalToUpdate, decal);
}
}
}),
removeDecal: (decalUuid) => set((state) => {
for (const wall of state.walls) {
wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid);
}
}),
updateDecalPosition: (decalUuid, position) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalPosition = position;
break;
}
}
}),
updateDecalRotation: (decalUuid, rotation) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalRotation = rotation;
break;
}
}
}),
updateDecalScale: (decalUuid, scale) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalScale = scale;
break;
}
}
}),
removePoint: (pointUuid) => {
const removedWalls: Wall[] = [];
set((state) => {
state.walls = state.walls.filter((wall) => {
const hasPoint = wall.points.some(p => p.pointUuid === pointUuid);
if (hasPoint) {
removedWalls.push(JSON.parse(JSON.stringify(wall)));
return false;
}
return true;
});
});
return removedWalls;
},
setPosition: (pointUuid, position) => set((state) => {
for (const wall of state.walls) {
const point = wall.points.find(p => p.pointUuid === pointUuid);
if (point) {
point.position = position;
}
}
}),
setLayer: (pointUuid, layer) => set((state) => {
for (const wall of state.walls) {
const point = wall.points.find(p => p.pointUuid === pointUuid);
if (point) {
point.layer = layer;
}
}
}),
getWallById: (uuid) => {
return get().walls.find(w => w.wallUuid === uuid);
},
getWallByPointId: (uuid) => {
for (const wall of get().walls) {
if (wall.points.some(p => p.pointUuid === uuid)) {
return wall;
}
}
return undefined;
},
getWallByPoints: (point) => {
for (const wall of get().walls) {
if (((wall.points[0].pointUuid === point[0].pointUuid) || (wall.points[1].pointUuid === point[0].pointUuid)) &&
((wall.points[0].pointUuid === point[1].pointUuid) || (wall.points[1].pointUuid === point[1].pointUuid))) {
return wall;
}
}
return undefined;
},
getWallPointById: (uuid) => {
for (const wall of get().walls) {
const point = wall.points.find(p => p.pointUuid === uuid);
if (point) return point;
}
return undefined;
},
getConnectedPoints: (uuid) => {
const connected: Point[] = [];
for (const wall of get().walls) {
for (const point of wall.points) {
if (point.pointUuid === uuid) {
connected.push(...wall.points.filter(p => p.pointUuid !== uuid));
}
}
}
return connected;
},
}))
);

View File

@@ -0,0 +1,74 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface ZoneStore {
zones: Zone[];
setZones: (zones: Zone[]) => void;
addZone: (zone: Zone) => void;
updateZone: (uuid: string, updated: Partial<Zone>) => void;
removeZone: (uuid: string) => void;
removePointFromZones: (pointUuid: string) => void;
clearZones: () => void;
setViewPort: (uuid: string, position: [number, number, number], target: [number, number, number]) => void;
setColor: (uuid: string, color: string) => void;
getZoneById: (uuid: string) => Zone | undefined;
}
export const createZoneStore = () => {
return create<ZoneStore>()(
immer((set, get) => ({
zones: [],
setZones: (zones) => set(state => {
state.zones = zones;
}),
addZone: (zone) => set(state => {
state.zones.push(zone);
}),
updateZone: (uuid, updated) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
Object.assign(zone, updated);
}
}),
removeZone: (uuid) => set(state => {
state.zones = state.zones.filter(z => z.zoneUuid !== uuid);
}),
removePointFromZones: (pointUuid) => set(state => {
for (const zone of state.zones) {
zone.points = zone.points.filter(p => p.pointUuid !== pointUuid);
}
}),
clearZones: () => set(state => {
state.zones = [];
}),
setViewPort: (uuid, position, target) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
zone.viewPortPosition = position;
zone.viewPortTarget = target;
}
}),
setColor: (uuid, color) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
zone.zoneColor = color;
}
}),
getZoneById: (uuid) => {
return get().zones.find(z => z.zoneUuid === uuid);
},
}))
);
};
export type ZoneStoreType = ReturnType<typeof createZoneStore>;

View File

@@ -1657,8 +1657,13 @@
.sidebar-right-wrapper { .sidebar-right-wrapper {
.wall-properties-container { .wall-properties-container {
.wall-properties-section{
padding: 14px;
padding-bottom: 0;
margin-bottom: 8px;
}
.header { .header {
color: var(--background-color-button); color: var(--text-color);
} }
.wall-properties { .wall-properties {
@@ -1692,7 +1697,7 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 15px; gap: 15px;
background: var(--Grays-Gray-6, #f2f2f7); background: var(--background-color-secondary);
padding: 18px 25px; padding: 18px 25px;
.sides-wrapper { .sides-wrapper {
@@ -1736,8 +1741,10 @@
} }
.preview { .preview {
width: 90%; width: 100%;
height: 111px; height: 111px;
border-radius: 20px;
overflow: hidden;
img { img {
width: 100%; width: 100%;
@@ -1750,7 +1757,8 @@
.materials { .materials {
max-height: 250px; max-height: 250px;
overflow: auto; overflow: auto;
margin-bottom: 6px; margin-top: 12px;
margin-bottom: 16px;
padding: 0 12px; padding: 0 12px;
.material-container { .material-container {

View File

@@ -10,6 +10,7 @@ interface Version {
type VersionHistory = Version[]; type VersionHistory = Version[];
// Asset // Asset
interface Asset { interface Asset {
@@ -45,6 +46,22 @@ interface Asset {
type Assets = Asset[]; type Assets = Asset[];
// Wall-Asset
interface WallAsset {
modelUuid: string;
modelName: string;
assetId: string;
wallUuid: string;
position: [number, number, number];
isLocked: boolean;
isVisible: boolean;
opacity: number;
}
type WallAssets = WallAsset[];
// Point // Point
type PointTypes = 'Aisle' | 'Wall' | 'Floor' | 'Zone'; type PointTypes = 'Aisle' | 'Wall' | 'Floor' | 'Zone';
@@ -63,11 +80,22 @@ interface Decal {
decalUuid: string; decalUuid: string;
decalName: string; decalName: string;
decalId: string; decalId: string;
decalType: WallDecal | FloorDecal;
decalPosition: [number, number, number]; decalPosition: [number, number, number];
decalRotation: number; decalRotation: number;
decalScale: number; decalScale: number;
} }
interface WallDecal {
type: 'Wall';
wallUuid: string;
}
interface FloorDecal {
type: 'Floor';
floorUuid: string;
}
interface Wall { interface Wall {
wallUuid: string; wallUuid: string;
points: [Point, Point]; points: [Point, Point];
@@ -75,12 +103,42 @@ interface Wall {
insideMaterial: string; insideMaterial: string;
wallThickness: number; wallThickness: number;
wallHeight: number; wallHeight: number;
decals: Decal[] decals: Decal[];
} }
type Walls = Wall[]; type Walls = Wall[];
// Floor
interface Floor {
floorUuid: string;
points: Point[];
sideMaterial: string;
topMaterial: string;
floorDepth: number;
isBeveled: boolean;
bevelStrength: number;
decals: Decal[];
}
type Floors = Floor[];
// Zone
interface Zone {
zoneUuid: string;
zoneName: string;
zoneColor: string;
points: Point[];
viewPortTarget: [number, number, number];
viewPortPosition: [number, number, number];
}
type Zones = Zone[];
// Aisle // Aisle
type AisleTypes = 'solid-aisle' | 'dashed-aisle' | 'stripped-aisle' | 'dotted-aisle' | 'arrow-aisle' | 'arrows-aisle' | 'arc-aisle' | 'circle-aisle' | 'junction-aisle'; type AisleTypes = 'solid-aisle' | 'dashed-aisle' | 'stripped-aisle' | 'dotted-aisle' | 'arrow-aisle' | 'arrows-aisle' | 'arc-aisle' | 'circle-aisle' | 'junction-aisle';