remove wall and aisle creator bug and added zone properties

This commit is contained in:
2025-09-29 12:45:06 +05:30
parent 6ee922a760
commit a064244eaf
13 changed files with 2442 additions and 2314 deletions

View File

@@ -21,6 +21,8 @@ import SelectedWallProperties from "./properties/SelectedWallProperties";
import SelectedFloorProperties from "./properties/SelectedFloorProperties"; import SelectedFloorProperties from "./properties/SelectedFloorProperties";
import SelectedDecalProperties from "./properties/SelectedDecalProperties"; import SelectedDecalProperties from "./properties/SelectedDecalProperties";
import SelectedAisleProperties from "./properties/SelectedAisleProperties"; import SelectedAisleProperties from "./properties/SelectedAisleProperties";
import SelectedZoneProperties from "./properties/SelectedZoneProperties";
import ResourceManagement from "./resourceManagement/ResourceManagement"; import ResourceManagement from "./resourceManagement/ResourceManagement";
import { useSceneContext } from "../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../modules/scene/sceneContext";
@@ -35,6 +37,7 @@ type DisplayComponent =
| "selectedFloorProperties" | "selectedFloorProperties"
| "selectedDecalProperties" | "selectedDecalProperties"
| "selectedAisleProperties" | "selectedAisleProperties"
| "selectedZoneProperties"
| "zoneProperties" | "zoneProperties"
| "simulations" | "simulations"
| "mechanics" | "mechanics"
@@ -44,12 +47,11 @@ type DisplayComponent =
| "none"; | "none";
const SideBarRight: React.FC = () => { const SideBarRight: React.FC = () => {
const { selectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { toggleUIRight } = useToggleStore(); const { toggleUIRight } = useToggleStore();
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { subModule, setSubModule } = useSubModuleStore(); const { subModule, setSubModule } = useSubModuleStore();
const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); const { selectedWall, selectedFloor, selectedAisle, selectedZone, selectedDecal } = useBuilderStore();
const { selectedEventData } = useSelectedEventData(); const { selectedEventData } = useSelectedEventData();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { versionStore, assetStore } = useSceneContext(); const { versionStore, assetStore } = useSceneContext();
@@ -114,26 +116,30 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("assetProperties"); setDisplayComponent("assetProperties");
return; return;
} }
if (selectedAssets.length !== 1 && !selectedFloor && !selectedAisle && !selectedDecal && selectedWall) { if (selectedAssets.length !== 1 && !selectedFloor && !selectedAisle && !selectedDecal && !selectedZone && selectedWall) {
setDisplayComponent("selectedWallProperties"); setDisplayComponent("selectedWallProperties");
return; return;
} }
if (selectedAssets.length !== 1 && !selectedWall && !selectedAisle && !selectedDecal && selectedFloor) { if (selectedAssets.length !== 1 && !selectedWall && !selectedAisle && !selectedDecal && !selectedZone && selectedFloor) {
setDisplayComponent("selectedFloorProperties"); setDisplayComponent("selectedFloorProperties");
return; return;
} }
if (viewVersionHistory && selectedAssets.length !== 1 && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal) { if (viewVersionHistory && selectedAssets.length !== 1 && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal && !selectedZone) {
setDisplayComponent("versionHistory"); setDisplayComponent("versionHistory");
return; return;
} }
if (selectedAssets.length !== 1 && !selectedFloor && !selectedAisle && !selectedWall && selectedDecal) { if (selectedAssets.length !== 1 && !selectedFloor && !selectedAisle && !selectedWall && !selectedZone && selectedDecal) {
setDisplayComponent("selectedDecalProperties"); setDisplayComponent("selectedDecalProperties");
return; return;
} }
if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && selectedAisle) { if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedZone && selectedAisle) {
setDisplayComponent("selectedAisleProperties"); setDisplayComponent("selectedAisleProperties");
return; return;
} }
if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle && selectedZone) {
setDisplayComponent("selectedZoneProperties");
return;
}
if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) { if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) {
if (toolMode === "Aisle") { if (toolMode === "Aisle") {
setDisplayComponent("aisleProperties"); setDisplayComponent("aisleProperties");
@@ -158,7 +164,7 @@ const SideBarRight: React.FC = () => {
} }
setDisplayComponent("none"); setDisplayComponent("none");
}, [viewVersionHistory, activeModule, subModule, isComparing, selectedAssets, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]); }, [viewVersionHistory, activeModule, subModule, isComparing, selectedAssets, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal, selectedZone]);
const renderComponent = () => { const renderComponent = () => {
switch (displayComponent) { switch (displayComponent) {
@@ -184,6 +190,8 @@ const SideBarRight: React.FC = () => {
return <SelectedDecalProperties />; return <SelectedDecalProperties />;
case "selectedAisleProperties": case "selectedAisleProperties":
return <SelectedAisleProperties />; return <SelectedAisleProperties />;
case "selectedZoneProperties":
return <SelectedZoneProperties />;
case "simulations": case "simulations":
return <Simulations />; return <Simulations />;
case "mechanics": case "mechanics":

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react"; import React, { useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { ArrowIcon } from "../../../icons/ExportCommonIcons"; import { ArrowIcon } from "../../../icons/ExportCommonIcons";
@@ -351,7 +351,7 @@ const SelectedAisleProperties: React.FC = () => {
return ( return (
<div className="aisle-properties-container"> <div className="aisle-properties-container">
<div className="header">Properties</div> <div className="header">Aisle Properties</div>
{/* Basic Properties */} {/* Basic Properties */}
<section> <section>

View File

@@ -100,6 +100,8 @@ const SelectedFloorProperties = () => {
return ( return (
<div className="wall-properties-container"> <div className="wall-properties-container">
<div className="header">Floor Properties</div>
<section className="wall-properties-section"> <section className="wall-properties-section">
<div className="header">Floor</div> <div className="header">Floor</div>
<div className="wall-properties"> <div className="wall-properties">

View File

@@ -14,12 +14,12 @@ import useWallResponseHandler from "../../../../modules/collaboration/responseHa
import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi"; import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
const SelectedWallProperties = () => { const SelectedWallProperties = () => {
const { projectId } = useParams();
const { selectedWall } = useBuilderStore(); const { selectedWall } = useBuilderStore();
const { wallStore, versionStore } = useSceneContext(); const { wallStore, versionStore } = useSceneContext();
const { selectedVersion } = versionStore(); const { selectedVersion } = versionStore();
const { builderSocket } = useSocketStore(); const { builderSocket } = useSocketStore();
const { userId, organization } = getUserData(); const { userId, organization } = getUserData();
const { projectId } = useParams();
const { peekUpdateWall } = wallStore(); const { peekUpdateWall } = wallStore();
const { updateWallInScene } = useWallResponseHandler(); const { updateWallInScene } = useWallResponseHandler();
@@ -99,6 +99,8 @@ const SelectedWallProperties = () => {
return ( return (
<div className="wall-properties-container"> <div className="wall-properties-container">
<div className="header">Wall Properties</div>
<section className="wall-properties-section"> <section className="wall-properties-section">
<div className="header">Wall</div> <div className="header">Wall</div>
<div className="wall-properties"> <div className="wall-properties">

View File

@@ -0,0 +1,134 @@
import { useState } from "react";
import { useParams } from "react-router-dom";
import { ArrowIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { useSocketStore } from "../../../../store/socket/useSocketStore";
import { getUserData } from "../../../../functions/getUserData";
import useZoneResponseHandler from "../../../../modules/collaboration/responseHandler/useZoneResponseHandler";
import { upsertZoneApi } from "../../../../services/factoryBuilder/zone/upsertZoneApi";
interface TextureList {
color: string;
id: string;
zoneType: string;
}
export const zoneTextureList: TextureList[] = [
{ color: "blue", id: "#0000ff", zoneType: "" },
{ color: "red", id: "#ff0000", zoneType: "" },
{ color: "yellow", id: "#FBE50E", zoneType: "" },
{ color: "white", id: "#ffffff", zoneType: "" },
{ color: "green", id: "#43C06D", zoneType: "" },
{ color: "orange", id: "#FF711B", zoneType: "" },
{ color: "purple", id: "#AF52DE", zoneType: "" },
];
function SelectedZoneProperties() {
const { projectId } = useParams();
const { selectedZone } = useBuilderStore();
const { zoneStore, versionStore } = useSceneContext();
const { selectedVersion } = versionStore();
const { builderSocket } = useSocketStore();
const { userId, organization } = getUserData();
const { peekUpdateZone } = zoneStore();
const { updateZoneInScene } = useZoneResponseHandler();
const [collapseTexture, setCollapseTexture] = useState(true);
if (!selectedZone?.zoneMesh) return null;
const updateZoneToBackend = (updatedZone: Zone | undefined) => {
if (projectId && updatedZone) {
if (!builderSocket?.connected) {
// API
upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone)
.then((data) => {
if (!data.message || !data.data) {
echo.error(`Error updating zone: ${updatedZone.zoneUuid}`);
return;
}
if (data.message === "Zone Updated Successfully") {
updateZoneInScene(updatedZone, () => {
echo.info(`Updated zone: ${updatedZone.zoneUuid}`);
});
} else {
echo.error(`Error updating zone: ${updatedZone.zoneUuid}`);
}
})
.catch(() => {
echo.error(`Error updating zone: ${updatedZone.zoneUuid}`);
});
} else {
// SOCKET
const data = {
zoneData: updatedZone,
projectId: projectId,
versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
};
builderSocket.emit("v1:zone:add", data);
}
}
};
const handleHeightChange = (val: string) => {
const height = parseFloat(val);
if (!isNaN(height)) {
const updatedZone = peekUpdateZone(selectedZone.zoneData.zoneUuid, { zoneHeight: height });
updateZoneToBackend(updatedZone);
}
};
const handleColorChange = (val: string) => {
const updatedZone = peekUpdateZone(selectedZone.zoneData.zoneUuid, { zoneColor: val });
updateZoneToBackend(updatedZone);
};
return (
<div className="zone-properties-container">
<div className="header">Zone Properties</div>
{/* Basic Properties */}
<section className="zone-properties-section">
<div className="header">{selectedZone.zoneData.zoneName}</div>
<div className="zone-properties">
<InputWithDropDown label="Height" value={selectedZone.zoneData.zoneHeight.toString()} min={1} max={25} step={1} onChange={handleHeightChange} />
</div>
</section>
{/* Texture */}
<section>
<button className="header" onClick={() => setCollapseTexture(!collapseTexture)} aria-expanded={!collapseTexture}>
<div className="value">Zone Texture</div>
<div className="icon" style={{ rotate: collapseTexture ? "" : "-90deg" }}>
<ArrowIcon />
</div>
</button>
{collapseTexture && (
<div className="zone-texture-container">
{zoneTextureList.map((val) => (
<button
key={val.id}
className={`zone-list ${selectedZone.zoneData.zoneColor === val.id ? "selected" : ""}`}
onClick={() => handleColorChange(val.id)}
aria-pressed={selectedZone.zoneData.zoneColor === val.id}
>
<div className={`texture-display ${val.id}`} style={{ background: val.id }}></div>
<div className="zone-color">{val.color}</div>
</button>
))}
<input type="color" className="custom-color-picker" value={selectedZone.zoneData.zoneColor} onChange={(e) => handleColorChange(e.target.value)} />
</div>
)}
</section>
</div>
);
}
export default SelectedZoneProperties;

View File

@@ -191,6 +191,7 @@ function AisleCreator() {
addAilseToBackend(aisle); addAilseToBackend(aisle);
setTempPoints([newPoint]); setTempPoints([newPoint]);
setIsCreating(true);
}; };
const onContext = (event: any) => { const onContext = (event: any) => {

View File

@@ -334,6 +334,7 @@ function WallCreator() {
}); });
setTempPoints([newPoint]); setTempPoints([newPoint]);
setIsCreating(true);
} }
return; return;
@@ -403,6 +404,7 @@ function WallCreator() {
}); });
setTempPoints([newPoint]); setTempPoints([newPoint]);
setIsCreating(true);
} }
}; };

View File

@@ -12,7 +12,7 @@ import useZoneResponseHandler from "../responseHandler/useZoneResponseHandler";
function BuilderResponses() { function BuilderResponses() {
const { assetStore } = useSceneContext(); const { assetStore } = useSceneContext();
const { getAssetById, movedObjects, initialStates, updateAsset, resetAsset, setInitialState } = assetStore(); const { getAssetById, movedObjects, initialStates, updateAsset, resetAsset, setInitialState } = assetStore();
const { selectedAisle, setSelectedAisle, selectedWall, setSelectedWall, selectedFloor, setSelectedFloor } = useBuilderStore(); const { selectedAisle, setSelectedAisle, selectedWall, setSelectedWall, selectedFloor, setSelectedFloor, selectedZone, setSelectedZone } = useBuilderStore();
const { builderSocket } = useSocketStore(); const { builderSocket } = useSocketStore();
const { addAssetToScene, updateAssetInScene, removeAssetFromScene } = useAssetResponseHandler(); const { addAssetToScene, updateAssetInScene, removeAssetFromScene } = useAssetResponseHandler();
const { addWallAssetToScene, updateWallAssetInScene, removeWallAssetFromScene } = useWallAssetResponseHandler(); const { addWallAssetToScene, updateWallAssetInScene, removeWallAssetFromScene } = useWallAssetResponseHandler();
@@ -510,9 +510,9 @@ function BuilderResponses() {
}; };
updateZoneInScene(zone, () => { updateZoneInScene(zone, () => {
// if (selectedZone?.zoneData.zoneUuid === zone.zoneUuid) { if (selectedZone?.zoneData.zoneUuid === zone.zoneUuid) {
// setSelectedZone({ zoneData: zone, zoneMesh: selectedZone.zoneMesh }); setSelectedZone({ zoneData: zone, zoneMesh: selectedZone.zoneMesh });
// } }
echo.info(`Updated zone: ${zone.zoneName}`); echo.info(`Updated zone: ${zone.zoneName}`);
}); });
@@ -543,7 +543,7 @@ function BuilderResponses() {
builderSocket.off("v1:zone:response:delete"); builderSocket.off("v1:zone:response:delete");
} }
}; };
}, [builderSocket]); }, [builderSocket, selectedZone]);
//#endregion //#endregion
return null; return null;

View File

@@ -26,6 +26,7 @@ export const upsertProductOrEventApi = async (body: any) => {
} }
const result = await response.json(); const result = await response.json();
console.log('result: ', result);
return result; return result;
} catch { } catch {
echo.error("Failed to upsert product or event"); echo.error("Failed to upsert product or event");

View File

@@ -28,6 +28,7 @@ export const deleteEventDataApi = async (body: any) => {
} }
const result = await response.json(); const result = await response.json();
console.log('result: ', result);
return result; return result;
} catch { } catch {
echo.error("Failed to delete event data"); echo.error("Failed to delete event data");

View File

@@ -26,6 +26,7 @@ export const deleteProductApi = async (body: any) => {
} }
const result = await response.json(); const result = await response.json();
console.log('result: ', result);
return result; return result;
} catch { } catch {
echo.error("Failed to delete product"); echo.error("Failed to delete product");

View File

@@ -6,6 +6,7 @@ interface ZoneStore {
setZones: (zones: Zone[]) => void; setZones: (zones: Zone[]) => void;
addZone: (zone: Zone) => void; addZone: (zone: Zone) => void;
updateZone: (uuid: string, updated: Partial<Zone>) => void; updateZone: (uuid: string, updated: Partial<Zone>) => void;
peekUpdateZone: (uuid: string, updated: Partial<Zone>) => Zone | undefined;
setZoneName: (uuid: string, name: string) => void; setZoneName: (uuid: string, name: string) => void;
setZoneHeight: (uuid: string, height: number) => void; setZoneHeight: (uuid: string, height: number) => void;
setZoneColor: (uuid: string, color: string) => void; setZoneColor: (uuid: string, color: string) => void;
@@ -48,6 +49,15 @@ export const createZoneStore = () => {
} }
}), }),
peekUpdateZone: (uuid, updated) => {
const zone = get().zones.find((z) => z.zoneUuid === uuid);
if (!zone) return undefined;
return {
...JSON.parse(JSON.stringify(zone)),
...updated,
} as Zone;
},
setZoneName: (uuid, name) => setZoneName: (uuid, name) =>
set((state) => { set((state) => {
const zone = state.zones.find((z) => z.zoneUuid === uuid); const zone = state.zones.find((z) => z.zoneUuid === uuid);

View File

@@ -1436,11 +1436,8 @@
background: var(--background-color); background: var(--background-color);
padding: 12px; padding: 12px;
border-radius: #{$border-radius-large}; border-radius: #{$border-radius-large};
outline: 1px solid var(--border-color); outline: 1px solid var(--border-color);
outline-offset: -1px; outline-offset: -1px;
border-radius: 12px;
background: var(--background-color);
.compare-simulations-header { .compare-simulations-header {
font-weight: var(--font-weight-medium); font-weight: var(--font-weight-medium);
@@ -1475,15 +1472,18 @@
} }
} }
.aisle-properties-container { .aisle-properties-container,
.zone-properties-container {
max-height: 65vh; max-height: 65vh;
overflow: auto; overflow: auto;
.aisle-texture-container { .aisle-texture-container,
.zone-texture-container {
max-height: 40vh; max-height: 40vh;
overflow: auto; overflow: auto;
.aisle-list { .aisle-list,
.zone-list {
width: calc(100% - 8px); width: calc(100% - 8px);
text-align: start; text-align: start;
padding: 4px 6px; padding: 4px 6px;
@@ -1503,28 +1503,17 @@
&.yellow-black { &.yellow-black {
background-color: black; background-color: black;
background-size: 10px 10px; background-size: 10px 10px;
background-image: repeating-linear-gradient( background-image: repeating-linear-gradient(45deg, #fbe50e 0, #fbe50e 2px, black 0, black 50%);
45deg,
#FBE50E 0,
#FBE50E 2px,
black 0,
black 50%
);
} }
&.white-black { &.white-black {
background-color: black; background-color: black;
background-size: 10px 10px; background-size: 10px 10px;
background-image: repeating-linear-gradient( background-image: repeating-linear-gradient(45deg, white 0, white 2px, black 0, black 50%);
45deg,
white 0,
white 2px,
black 0,
black 50%
);
} }
} }
.aisle-color { .aisle-color,
.zone-color {
text-transform: capitalize; text-transform: capitalize;
} }
@@ -1535,19 +1524,10 @@
&.selected { &.selected {
background: var(--highlight-accent-color); background: var(--highlight-accent-color);
// .aisle-color {
// color: var(--text-button-color);
// }
// &:hover {
// background: var(--background-color-accent);
// }
} }
&:hover { &:hover {
background: var(--highlight-accent-color); background: var(--highlight-accent-color);
// background: var(--background-color-secondary);
} }
} }
} }
@@ -2040,8 +2020,7 @@
&:hover { &:hover {
background: var(--background-color-solid); background: var(--background-color-solid);
.back-arrow { .back-arrow {
transform: translateX(-2px) translateY(-1px) scale(1.6) transform: translateX(-2px) translateY(-1px) scale(1.6) rotate(90deg);
rotate(90deg);
} }
} }
} }
@@ -2120,11 +2099,7 @@
&:nth-child(2) { &:nth-child(2) {
&::after { &::after {
// @include gradient-by-child(4); // Second child uses the second color // @include gradient-by-child(4); // Second child uses the second color
background: linear-gradient( background: linear-gradient(144.19deg, rgba(197, 137, 26, 0.5) 16.62%, rgba(69, 48, 10, 0.5) 85.81%);
144.19deg,
rgba(197, 137, 26, 0.5) 16.62%,
rgba(69, 48, 10, 0.5) 85.81%
);
} }
} }
@@ -2209,11 +2184,6 @@
.sub-catagory { .sub-catagory {
color: #ffffff; color: #ffffff;
} }
// svg {
// stroke: white;
// fill: white;
// }
} }
} }
} }
@@ -2262,11 +2232,7 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
font-size: var(--font-size-regular); font-size: var(--font-size-regular);
background: linear-gradient( background: linear-gradient(0deg, rgba(37, 24, 51, 0) 0%, rgba(52, 41, 61, 0.5) 100%);
0deg,
rgba(37, 24, 51, 0) 0%,
rgba(52, 41, 61, 0.5) 100%
);
pointer-events: none; pointer-events: none;
backdrop-filter: blur(8px); backdrop-filter: blur(8px);
opacity: 0; opacity: 0;