From 69329dba7aed234c8fced65fdf0d02a6f738ad3d Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 23 Aug 2025 10:24:21 +0530 Subject: [PATCH 01/11] name and schema chmage for assembly to manufacturer --- ...-assembly.glb => human-ui-manufacture.glb} | Bin ...semblyAction.tsx => ManufactureAction.tsx} | 28 +- .../mechanics/humanMechanics.tsx | 40 +- app/src/modules/builder/asset/assetsGroup.tsx | 2 +- .../builder/asset/functions/addAssetModel.ts | 2 +- .../Instances/Instance/floorInstance.tsx | 383 +++++++++--------- .../builder/wall/Instances/instance/wall.tsx | 19 +- .../selection3D/copyPasteControls3D.tsx | 2 +- .../selection3D/duplicationControls3D.tsx | 2 +- ...lyHandler.ts => useManufacturerHandler.ts} | 12 +- .../actions/human/useHumanActions.ts | 16 +- .../simulation/actions/useActionHandler.ts | 2 +- .../eventManager/useHumanEventManager.ts | 16 +- ...rAnimator.tsx => manufacturerAnimator.tsx} | 12 +- .../instances/animator/materialAnimator.tsx | 2 +- .../instances/animator/workerAnimator.tsx | 4 +- ...rInstance.tsx => manufacturerInstance.tsx} | 38 +- .../instances/instance/humanInstance.tsx | 6 +- .../human/instances/instance/humanUi.tsx | 72 ++-- .../triggerHandler/useTriggerHandler.ts | 2 +- .../instances/instance/vehicleInstance.tsx | 2 +- .../store/simulation/useSimulationStore.ts | 8 +- app/src/types/simulationTypes.d.ts | 10 +- 23 files changed, 327 insertions(+), 353 deletions(-) rename app/src/assets/gltf-glb/ui/{human-ui-assembly.glb => human-ui-manufacture.glb} (100%) rename app/src/components/layout/sidebarRight/properties/eventProperties/actions/{AssemblyAction.tsx => ManufactureAction.tsx} (74%) rename app/src/modules/simulation/actions/human/actionHandler/{useAssemblyHandler.ts => useManufacturerHandler.ts} (72%) rename app/src/modules/simulation/human/instances/animator/{assemblerAnimator.tsx => manufacturerAnimator.tsx} (93%) rename app/src/modules/simulation/human/instances/instance/actions/{assemberInstance.tsx => manufacturerInstance.tsx} (89%) diff --git a/app/src/assets/gltf-glb/ui/human-ui-assembly.glb b/app/src/assets/gltf-glb/ui/human-ui-manufacture.glb similarity index 100% rename from app/src/assets/gltf-glb/ui/human-ui-assembly.glb rename to app/src/assets/gltf-glb/ui/human-ui-manufacture.glb diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/AssemblyAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/ManufactureAction.tsx similarity index 74% rename from app/src/components/layout/sidebarRight/properties/eventProperties/actions/AssemblyAction.tsx rename to app/src/components/layout/sidebarRight/properties/eventProperties/actions/ManufactureAction.tsx index e371f6f..5d66ceb 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/AssemblyAction.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/ManufactureAction.tsx @@ -3,7 +3,7 @@ import InputRange from "../../../../../ui/inputs/InputRange"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; import SwapAction from "./SwapAction"; -interface AssemblyActionProps { +interface ManufactureActionProps { processTime: { value: number; min: number; @@ -11,7 +11,7 @@ interface AssemblyActionProps { disabled?: boolean, onChange: (value: number) => void; }; - assemblyCount: { + manufactureCount: { value: number; min: number; max: number; @@ -26,9 +26,9 @@ interface AssemblyActionProps { clearPoints: () => void; } -const AssemblyAction: React.FC = ({ +const ManufactureAction: React.FC = ({ processTime, - assemblyCount, + manufactureCount, swapOptions, swapDefaultOption, onSwapSelect, @@ -46,18 +46,18 @@ const AssemblyAction: React.FC = ({ onChange={processTime.onChange} /> - {assemblyCount && ( + {manufactureCount && ( { }} - onChange={(value) => assemblyCount.onChange(parseInt(value))} + onChange={(value) => manufactureCount.onChange(parseInt(value))} /> )} = ({ ); }; -export default AssemblyAction; +export default ManufactureAction; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx index 22bdbbf..0e003b1 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx @@ -7,7 +7,7 @@ import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import Trigger from "../trigger/Trigger"; import ActionsList from "../components/ActionsList"; import WorkerAction from "../actions/WorkerAction"; -import AssemblyAction from "../actions/AssemblyAction"; +import ManufactureAction from "../actions/ManufactureAction"; import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore"; import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi"; @@ -17,10 +17,10 @@ import { useSceneContext } from "../../../../../../modules/scene/sceneContext"; import { useParams } from "react-router-dom"; function HumanMechanics() { - const [activeOption, setActiveOption] = useState<"worker" | "assembly" | "operator">("worker"); + const [activeOption, setActiveOption] = useState<"worker" | "manufacturer" | "operator">("worker"); const [speed, setSpeed] = useState("0.5"); const [loadCount, setLoadCount] = useState(0); - const [assemblyCount, setAssemblyCount] = useState(0); + const [manufactureCount, setManufactureCount] = useState(0); const [loadCapacity, setLoadCapacity] = useState("1"); const [processTime, setProcessTime] = useState(10); const [swappedMaterial, setSwappedMaterial] = useState("Default material"); @@ -58,7 +58,7 @@ function HumanMechanics() { setLoadCapacity(firstAction.loadCapacity.toString()); setActiveOption(firstAction.actionType); setLoadCount(firstAction.loadCount || 0); - setAssemblyCount(firstAction.assemblyCount || 0); + setManufactureCount(firstAction.manufactureCount || 0); setProcessTime(firstAction.processTime || 10); setSwappedMaterial(firstAction.swapMaterial || "Default material"); } @@ -79,7 +79,7 @@ function HumanMechanics() { const newCurrentAction = getActionByUuid(selectedProduct.productUuid, actionUuid); - if (newCurrentAction && (newCurrentAction.actionType === 'assembly' || newCurrentAction?.actionType === 'worker' || newCurrentAction?.actionType === "operator")) { + if (newCurrentAction && (newCurrentAction.actionType === 'manufacturer' || newCurrentAction?.actionType === 'worker' || newCurrentAction?.actionType === "operator")) { if (!selectedAction.actionId) { setSelectedAction(newCurrentAction.actionUuid, newCurrentAction.actionName); } @@ -87,9 +87,9 @@ function HumanMechanics() { setActiveOption(newCurrentAction.actionType); setLoadCapacity(newCurrentAction.loadCapacity.toString()); setLoadCount(newCurrentAction.loadCount || 0); - setAssemblyCount(newCurrentAction.assemblyCount || 0); + setManufactureCount(newCurrentAction.manufactureCount || 0); - if (newCurrentAction.actionType === 'assembly') { + if (newCurrentAction.actionType === 'manufacturer') { setProcessTime(newCurrentAction.processTime || 10); setSwappedMaterial(newCurrentAction.swapMaterial || "Default material"); } @@ -118,7 +118,7 @@ function HumanMechanics() { const handleSelectActionType = (actionType: string) => { if (!selectedAction.actionId || !currentAction || !selectedPointData) return; - const updatedAction = { ...currentAction, actionType: actionType as "worker" | "assembly" | "operator" }; + const updatedAction = { ...currentAction, actionType: actionType as "worker" | "manufacturer" | "operator" }; const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action); const updatedPoint = { ...selectedPointData, actions: updatedActions }; @@ -203,10 +203,10 @@ function HumanMechanics() { setLoadCount(value); }; - const handleAssemblyCountChange = (value: number) => { + const handleManufactureCountChange = (value: number) => { if (!currentAction || !selectedPointData || !selectedAction.actionId) return; - const updatedAction = { ...currentAction, assemblyCount: value }; + const updatedAction = { ...currentAction, manufactureCount: value }; const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action); const updatedPoint = { ...selectedPointData, actions: updatedActions }; @@ -222,7 +222,7 @@ function HumanMechanics() { setCurrentAction(updatedAction); setSelectedPointData(updatedPoint); - setAssemblyCount(value); + setManufactureCount(value); }; const handleProcessTimeChange = (value: number) => { @@ -274,8 +274,8 @@ function HumanMechanics() { const updatedAction: HumanAction = JSON.parse(JSON.stringify(currentAction)); - if (updatedAction.actionType === 'assembly') { - updatedAction.assemblyPoint = { position: null, rotation: null, } + if (updatedAction.actionType === 'manufacturer') { + updatedAction.manufacturePoint = { position: null, rotation: null, } } else { updatedAction.pickUpPoint = { position: null, rotation: null, }; updatedAction.dropPoint = { position: null, rotation: null, } @@ -306,7 +306,7 @@ function HumanMechanics() { actionName: `Action ${selectedPointData.actions.length + 1}`, actionType: "worker", loadCount: 1, - assemblyCount: 1, + manufactureCount: 1, loadCapacity: 1, processTime: 10, triggers: [], @@ -397,7 +397,7 @@ function HumanMechanics() { @@ -425,22 +425,22 @@ function HumanMechanics() { clearPoints={handleClearPoints} /> } - {currentAction.actionType === 'assembly' && - = { + "Default Material": { + map: savedTheme === "dark" ? texturePathDark : texturePath, + }, + "Material 1": { + map: material1, + }, + "Material 2": { + map: material2Map, + roughnessMap: material2MetalicRoughnessMap, + metalnessMap: material2MetalicRoughnessMap, + normalMap: material2NormalMap, + textureTileScale: [0.1, 0.1], + }, + "Material 3": { + map: material3Map, + roughnessMap: material3MetalicRoughnessMap, + metalnessMap: material3MetalicRoughnessMap, + normalMap: material3NormalMap, + textureTileScale: [0.35, 0.5], + }, + "Material 4": { + map: material4Map, + roughnessMap: material4RoughnessMap, + metalnessMap: material4MetalicMap, + normalMap: material4NormalMap, + }, + }; + + const shape = useMemo(() => { + const shape = new Shape(); + const points = floor.points.map( + (p) => new Vector2(p.position[0], p.position[2]) + ); + if (points.length < 3) return null; + shape.moveTo(points[0].x, points[0].y); + for (let i = 1; i < points.length; i++) { + shape.lineTo(points[i].x, points[i].y); + } + return shape; + }, [floor]); + + const textureScale = Constants.floorConfig.textureScale; + + // Helper function to handle texture maps and filter out null values + function getMaterialMaps(material: any, defaultMap: any) { + const materialMap = material.map || defaultMap; + const normalMap = material.normalMap || null; + const roughnessMap = material.roughnessMap || null; + const metalnessMap = material.metalnessMap || null; + + return [materialMap, normalMap, roughnessMap, metalnessMap].filter( + (texture): texture is string => texture !== null + ); } - > = { - "Default Material": { - map: savedTheme === "dark" ? texturePathDark : texturePath, - }, - "Material 1": { - map: material1, - }, - "Material 2": { - map: material2Map, - roughnessMap: material2MetalicRoughnessMap, - metalnessMap: material2MetalicRoughnessMap, - normalMap: material2NormalMap, - textureTileScale: [0.1, 0.1], - }, - "Material 3": { - map: material3Map, - roughnessMap: material3MetalicRoughnessMap, - metalnessMap: material3MetalicRoughnessMap, - normalMap: material3NormalMap, - textureTileScale: [0.35, 0.5], - }, - "Material 4": { - map: material4Map, - roughnessMap: material4RoughnessMap, - metalnessMap: material4MetalicMap, - normalMap: material4NormalMap, - }, - }; - const shape = useMemo(() => { - const shape = new Shape(); - const points = floor.points.map( - (p) => new Vector2(p.position[0], p.position[2]) - ); - if (points.length < 3) return null; - shape.moveTo(points[0].x, points[0].y); - for (let i = 1; i < points.length; i++) { - shape.lineTo(points[i].x, points[i].y); - } - return shape; - }, [floor]); + // Default material map + const defaultMaterialMap = materials["Default Material"].map; - const textureScale = Constants.floorConfig.textureScale; + // Get top and side material maps + const topMaterial = materials[floor.topMaterial]; + const sideMaterial = materials[floor.sideMaterial]; - // Helper function to handle texture maps and filter out null values - function getMaterialMaps(material: any, defaultMap: any) { - const materialMap = material.map || defaultMap; - const normalMap = material.normalMap || null; - const roughnessMap = material.roughnessMap || null; - const metalnessMap = material.metalnessMap || null; + // Get the filtered lists for top and side textures + const topTexturesList = getMaterialMaps(topMaterial, defaultMaterialMap); + const sideTexturesList = getMaterialMaps(sideMaterial, defaultMaterialMap); - return [materialMap, normalMap, roughnessMap, metalnessMap].filter( - (texture): texture is string => texture !== null - ); - } + // Use loader to load top and side textures + const [topTexture, topNormalTexture, topRoughnessTexture, topMetalicTexture] = useLoader(TextureLoader, topTexturesList); - // Default material map - const defaultMaterialMap = materials["Default Material"].map; - - // Get top and side material maps - const topMaterial = materials[floor.topMaterial]; - const sideMaterial = materials[floor.sideMaterial]; - - // Get the filtered lists for top and side textures - const topTexturesList = getMaterialMaps(topMaterial, defaultMaterialMap); - const sideTexturesList = getMaterialMaps(sideMaterial, defaultMaterialMap); - - // Use loader to load top and side textures - const [topTexture, topNormalTexture, topRoughnessTexture, topMetalicTexture] = - useLoader(TextureLoader, topTexturesList); - - const [ - sideTexture, - sideNormalTexture, - sideRoughnessTexture, - sideMetalicTexture, - ] = useLoader(TextureLoader, sideTexturesList); - - // Early exit if materials are missing - if (!materials[floor.topMaterial] || !materials[floor.sideMaterial]) - return null; - - // Combine and pair textures with their corresponding material - const textureMaterialMap = [ - { - textures: [ - topTexture, - topNormalTexture, - topRoughnessTexture, - topMetalicTexture, - ], - materialKey: floor.topMaterial, - }, - { - textures: [ + const [ sideTexture, sideNormalTexture, sideRoughnessTexture, sideMetalicTexture, - ], - materialKey: floor.sideMaterial, - }, - ]; + ] = useLoader(TextureLoader, sideTexturesList); - // Apply texture settings - textureMaterialMap.forEach(({ textures, materialKey }) => { - const tileScale = materials[materialKey]?.textureTileScale ?? [ - textureScale, - textureScale, + // Early exit if materials are missing + if (!materials[floor.topMaterial] || !materials[floor.sideMaterial]) + return null; + + // Combine and pair textures with their corresponding material + const textureMaterialMap = [ + { + textures: [ + topTexture, + topNormalTexture, + topRoughnessTexture, + topMetalicTexture, + ], + materialKey: floor.topMaterial, + }, + { + textures: [ + sideTexture, + sideNormalTexture, + sideRoughnessTexture, + sideMetalicTexture, + ], + materialKey: floor.sideMaterial, + }, ]; - textures.forEach((tex, idx) => { - if (!tex) return; - tex.wrapS = tex.wrapT = RepeatWrapping; - tex.repeat.set(tileScale[0], tileScale[1]); - tex.anisotropy = 16; - // First texture is always the color map (use SRGB), others should be linear - tex.colorSpace = idx < 1 ? SRGBColorSpace : NoColorSpace; + // Apply texture settings + textureMaterialMap.forEach(({ textures, materialKey }) => { + const tileScale = materials[materialKey]?.textureTileScale ?? [ + textureScale, + textureScale, + ]; + + textures.forEach((tex, idx) => { + if (!tex) return; + tex.wrapS = tex.wrapT = RepeatWrapping; + tex.repeat.set(tileScale[0], tileScale[1]); + tex.anisotropy = 16; + // First texture is always the color map (use SRGB), others should be linear + tex.colorSpace = idx < 1 ? SRGBColorSpace : NoColorSpace; + }); }); - }); - if (!shape) return null; + if (!shape) return null; - return ( - { - if (!togglView && activeModule === "builder") { - if (e.object.userData.floorUuid) { - e.stopPropagation(); - setSelectedFloor(e.object); - setSelectedDecal(null); - } - } - }} - onPointerMissed={() => { - if ( - selectedFloor && - selectedFloor.userData.floorUuid === floor.floorUuid - ) { - setSelectedFloor(null); - } - }} - > - - - - - - ); + return ( + { + if (!togglView && activeModule === "builder") { + if (e.object.userData.floorUuid) { + e.stopPropagation(); + setSelectedFloor(e.object); + setSelectedDecal(null); + } + } + }} + onPointerMissed={() => { + if ( + selectedFloor && + selectedFloor.userData.floorUuid === floor.floorUuid + ) { + setSelectedFloor(null); + } + }} + > + + + + + + ); } export default FloorInstance; diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx index 9023dc6..283ec23 100644 --- a/app/src/modules/builder/wall/Instances/instance/wall.tsx +++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx @@ -10,7 +10,7 @@ import { useToggleView, useWallVisibility } from '../../../../../store/builder/s import { useBuilderStore } from '../../../../../store/builder/useBuilderStore'; import * as Constants from '../../../../../types/world/worldConstants'; -// import DecalInstance from '../../../Decal/decalInstance'; +import DecalInstance from '../../../Decal/decalInstance'; import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png'; import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg'; @@ -150,19 +150,6 @@ function Wall({ wall }: { readonly wall: Wall }) { e.stopPropagation(); 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); - } } }} @@ -174,9 +161,9 @@ function Wall({ wall }: { readonly wall: Wall }) { > - {/* {wall.decals.map((decal) => ( + {wall.decals.map((decal) => ( - ))} */} + ))} ); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx index a8a8c8d..c11a50e 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx @@ -430,7 +430,7 @@ const CopyPasteControls3D = ({ actionName: "Action 1", actionType: "worker", loadCapacity: 1, - assemblyCount: 1, + manufactureCount: 1, loadCount: 1, processTime: 10, triggers: [] diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx index 551cdaf..01c74d0 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx @@ -497,7 +497,7 @@ const DuplicationControls3D = ({ actionName: "Action 1", actionType: "worker", loadCapacity: 1, - assemblyCount: 1, + manufactureCount: 1, loadCount: 1, processTime: 10, triggers: [] diff --git a/app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts b/app/src/modules/simulation/actions/human/actionHandler/useManufacturerHandler.ts similarity index 72% rename from app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts rename to app/src/modules/simulation/actions/human/actionHandler/useManufacturerHandler.ts index 602de27..25dee10 100644 --- a/app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts +++ b/app/src/modules/simulation/actions/human/actionHandler/useManufacturerHandler.ts @@ -2,7 +2,7 @@ import { useCallback } from "react"; import { useSceneContext } from "../../../../scene/sceneContext"; import { useProductContext } from "../../../products/productContext"; -export function useAssemblyHandler() { +export function useManufacturerHandler() { const { materialStore, humanStore, productStore } = useSceneContext(); const { getMaterialById } = materialStore(); const { getModelUuidByActionUuid } = productStore(); @@ -10,12 +10,12 @@ export function useAssemblyHandler() { const { selectedProduct } = selectedProductStore(); const { incrementHumanLoad, addCurrentMaterial, addCurrentAction } = humanStore(); - const assemblyLogStatus = (materialUuid: string, status: string) => { + const manufactureLogStatus = (materialUuid: string, status: string) => { echo.info(`${materialUuid}, ${status}`); } - const handleAssembly = useCallback((action: HumanAction, materialId?: string) => { - if (!action || action.actionType !== 'assembly' || !materialId) return; + const handleManufacturer = useCallback((action: HumanAction, materialId?: string) => { + if (!action || action.actionType !== 'manufacturer' || !materialId) return; const material = getMaterialById(materialId); if (!material) return; @@ -27,11 +27,11 @@ export function useAssemblyHandler() { addCurrentAction(modelUuid, action.actionUuid); addCurrentMaterial(modelUuid, material.materialType, material.materialId); - assemblyLogStatus(material.materialName, `performing assembly action`); + manufactureLogStatus(material.materialName, `performing manufacturer action`); }, [getMaterialById]); return { - handleAssembly, + handleManufacturer, }; } \ No newline at end of file diff --git a/app/src/modules/simulation/actions/human/useHumanActions.ts b/app/src/modules/simulation/actions/human/useHumanActions.ts index ba29a1b..301669e 100644 --- a/app/src/modules/simulation/actions/human/useHumanActions.ts +++ b/app/src/modules/simulation/actions/human/useHumanActions.ts @@ -1,18 +1,18 @@ import { useEffect, useCallback } from 'react'; import { useWorkerHandler } from './actionHandler/useWorkerHandler'; -import { useAssemblyHandler } from './actionHandler/useAssemblyHandler'; +import { useManufacturerHandler } from './actionHandler/useManufacturerHandler'; export function useHumanActions() { const { handleWorker } = useWorkerHandler(); - const { handleAssembly } = useAssemblyHandler(); + const { handleManufacturer } = useManufacturerHandler(); const handleWorkerAction = useCallback((action: HumanAction, materialId: string) => { handleWorker(action, materialId); }, [handleWorker]); - const handleAssemblyAction = useCallback((action: HumanAction, materialId: string) => { - handleAssembly(action, materialId); - }, [handleAssembly]); + const handleManufactureAction = useCallback((action: HumanAction, materialId: string) => { + handleManufacturer(action, materialId); + }, [handleManufacturer]); const handleHumanAction = useCallback((action: HumanAction, materialId: string) => { if (!action) return; @@ -21,13 +21,13 @@ export function useHumanActions() { case 'worker': handleWorkerAction(action, materialId); break; - case 'assembly': - handleAssemblyAction(action, materialId); + case 'manufacturer': + handleManufactureAction(action, materialId); break; default: console.warn(`Unknown Human action type: ${action.actionType}`); } - }, [handleWorkerAction, handleAssemblyAction]); + }, [handleWorkerAction, handleManufactureAction]); const cleanup = useCallback(() => { }, []); diff --git a/app/src/modules/simulation/actions/useActionHandler.ts b/app/src/modules/simulation/actions/useActionHandler.ts index 99d8225..ec02943 100644 --- a/app/src/modules/simulation/actions/useActionHandler.ts +++ b/app/src/modules/simulation/actions/useActionHandler.ts @@ -41,7 +41,7 @@ export function useActionHandler() { case 'store': case 'retrieve': handleStorageAction(action as StorageAction, materialId as string); break; - case 'worker': case 'assembly': + case 'worker': case 'manufacturer': handleHumanAction(action as HumanAction, materialId as string); break; case 'pickAndDrop': diff --git a/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts b/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts index 1dec0d9..4a41f6f 100644 --- a/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts +++ b/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts @@ -25,7 +25,7 @@ export function useHumanEventManager() { const addHumanToMonitor = (humanId: string, callback: () => void, actionUuid: string) => { const human = getHumanById(humanId); const action = getActionByUuid(selectedProduct.productUuid, actionUuid); - if (!human || !action || (action.actionType !== 'assembly' && action.actionType !== 'worker' && action.actionType !== 'operator') || !humanEventManagerRef.current) return; + if (!human || !action || (action.actionType !== 'manufacturer' && action.actionType !== 'worker' && action.actionType !== 'operator') || !humanEventManagerRef.current) return; let state = humanEventManagerRef.current.humanStates.find(h => h.humanId === humanId); if (!state) { @@ -42,8 +42,8 @@ export function useHumanEventManager() { existingAction.isMonitored = true; existingAction.isCompleted = false; } - } else if (existingAction.actionType === 'assembly') { - if (currentCount < existingAction.maxAssemblyCount) { + } else if (existingAction.actionType === 'manufacturer') { + if (currentCount < existingAction.maxManufactureCount) { existingAction.callback = callback; existingAction.isMonitored = true; existingAction.isCompleted = false; @@ -57,7 +57,7 @@ export function useHumanEventManager() { actionUuid, actionName: action.actionName, maxLoadCount: action.loadCount ?? 0, - maxAssemblyCount: action.assemblyCount ?? 0, + maxManufactureCount: action.manufactureCount ?? 0, count: 0, isMonitored: true, isCompleted: false, @@ -101,11 +101,11 @@ export function useHumanEventManager() { if (currentAction.actionType === 'worker' || currentAction.actionType === 'operator') { if ((action.actionType === 'worker' || action.actionType === 'operator') && human.currentLoad < currentAction.loadCapacity) { conditionMet = true; - } else if (action.actionType === 'assembly') { + } else if (action.actionType === 'manufacturer') { conditionMet = true; } - } else if (currentAction.actionType === 'assembly') { - if (action.actionType === 'assembly') { + } else if (currentAction.actionType === 'manufacturer') { + if (action.actionType === 'manufacturer') { conditionMet = true; } else if ((action.actionType === 'worker' || action.actionType === 'operator') && human.currentLoad < currentAction.loadCapacity) { conditionMet = true; @@ -122,7 +122,7 @@ export function useHumanEventManager() { action.count = (action.count ?? 0) + 1; action.isMonitored = false; if (((action.actionType === 'worker' || action.actionType === 'operator') && action.count >= action.maxLoadCount) || - (action.actionType === 'assembly' && action.count >= action.maxAssemblyCount)) { + (action.actionType === 'manufacturer' && action.count >= action.maxManufactureCount)) { action.isCompleted = true; } humanState.isCooldown = true; diff --git a/app/src/modules/simulation/human/instances/animator/assemblerAnimator.tsx b/app/src/modules/simulation/human/instances/animator/manufacturerAnimator.tsx similarity index 93% rename from app/src/modules/simulation/human/instances/animator/assemblerAnimator.tsx rename to app/src/modules/simulation/human/instances/animator/manufacturerAnimator.tsx index d891d8f..45d7658 100644 --- a/app/src/modules/simulation/human/instances/animator/assemblerAnimator.tsx +++ b/app/src/modules/simulation/human/instances/animator/manufacturerAnimator.tsx @@ -6,14 +6,14 @@ import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useRese import { useSceneContext } from '../../../../scene/sceneContext'; import { useProductContext } from '../../../products/productContext'; -interface AssemblerAnimatorProps { +interface ManufacturerAnimatorProps { path: [number, number, number][]; handleCallBack: () => void; reset: () => void; human: HumanStatus; } -function AssemblerAnimator({ path, handleCallBack, human, reset }: Readonly) { +function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly) { const { humanStore, assetStore, productStore } = useSceneContext(); const { getActionByUuid } = productStore(); const { selectedProductStore } = useProductContext(); @@ -27,16 +27,16 @@ function AssemblerAnimator({ path, handleCallBack, human, reset }: Readonly(0); const completedRef = useRef(false); const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || ''); - const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>((action as HumanAction)?.assemblyPoint?.rotation || [0, 0, 0]); + const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>((action as HumanAction)?.manufacturePoint?.rotation || [0, 0, 0]); const [restRotation, setRestingRotation] = useState(true); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); const { scene } = useThree(); useEffect(() => { if (!human.currentAction?.actionUuid) return; - if (human.currentPhase === 'init-assembly' && path.length > 0) { + if (human.currentPhase === 'init-manufacture' && path.length > 0) { setCurrentPath(path); - setObjectRotation((action as HumanAction)?.assemblyPoint?.rotation ?? null); + setObjectRotation((action as HumanAction)?.manufacturePoint?.rotation ?? null); } }, [human.currentPhase, path, objectRotation, selectedProduct, human.currentAction?.actionUuid]); @@ -169,4 +169,4 @@ function AssemblerAnimator({ path, handleCallBack, human, reset }: Readonly { return ( <> - {hasLoad && action && (action as HumanAction).actionType === 'worker' && human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-assembly' && human.currentPhase !== 'drop-pickup') && ( + {hasLoad && action && (action as HumanAction).actionType === 'worker' && human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-manufacture' && human.currentPhase !== 'drop-pickup') && ( 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-assembly' && human.currentPhase !== 'drop-pickup')) { + if (human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-manufacture' && human.currentPhase !== 'drop-pickup')) { setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true); } else { setCurrentAnimation(human.modelUuid, 'walking', true, true, true); } } else { - if (human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-assembly' && human.currentPhase !== 'drop-pickup')) { + if (human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-manufacture' && human.currentPhase !== 'drop-pickup')) { setCurrentAnimation(human.modelUuid, 'idle_with_box', true, true, true); } else { setCurrentAnimation(human.modelUuid, 'idle', true, true, true); diff --git a/app/src/modules/simulation/human/instances/instance/actions/assemberInstance.tsx b/app/src/modules/simulation/human/instances/instance/actions/manufacturerInstance.tsx similarity index 89% rename from app/src/modules/simulation/human/instances/instance/actions/assemberInstance.tsx rename to app/src/modules/simulation/human/instances/instance/actions/manufacturerInstance.tsx index 881a2ec..ae74a14 100644 --- a/app/src/modules/simulation/human/instances/instance/actions/assemberInstance.tsx +++ b/app/src/modules/simulation/human/instances/instance/actions/manufacturerInstance.tsx @@ -8,9 +8,9 @@ import { useTriggerHandler } from '../../../../triggers/triggerHandler/useTrigge import { useSceneContext } from '../../../../../scene/sceneContext'; import { useProductContext } from '../../../../products/productContext'; -import AssemblerAnimator from '../../animator/assemblerAnimator'; +import ManufacturerAnimator from '../../animator/manufacturerAnimator'; -function AssemblerInstance({ human }: { human: HumanStatus }) { +function ManufacturerInstance({ human }: { human: HumanStatus }) { const { navMesh } = useNavMesh(); const { isPlaying } = usePlayButtonStore(); const { scene } = useThree(); @@ -99,24 +99,24 @@ function AssemblerInstance({ human }: { human: HumanStatus }) { if (isPlaying) { const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || ''); - if (!action || !(action as HumanAction).assemblyPoint || (action as HumanAction).actionType === 'worker') return; + if (!action || !(action as HumanAction).manufacturePoint || (action as HumanAction).actionType === 'worker') return; if (!human.isActive && human.state === 'idle' && human.currentPhase === 'init') { const humanMesh = scene.getObjectByProperty('uuid', human.modelUuid); if (!humanMesh) return; - const toPickupPath = computePath(humanMesh.position.toArray(), (action as HumanAction)?.assemblyPoint?.position || [0, 0, 0]); + const toPickupPath = computePath(humanMesh.position.toArray(), (action as HumanAction)?.manufacturePoint?.position || [0, 0, 0]); setPath(toPickupPath); setHumanState(human.modelUuid, 'idle'); - setCurrentPhase(human.modelUuid, 'init-assembly'); + setCurrentPhase(human.modelUuid, 'init-manufacture'); setHumanActive(human.modelUuid, false); setCurrentAnimation(human.modelUuid, 'idle', true, true, true); - humanStatus(human.modelUuid, 'Human is waiting for material in assembly'); + humanStatus(human.modelUuid, 'Human is waiting for material in manufacture'); } else if (!human.isActive && human.state === 'idle' && human.currentPhase === 'waiting') { if (human.currentMaterials.length > 0 && humanAsset && humanAsset.animationState?.current !== 'working_standing') { setCurrentAnimation(human.modelUuid, 'working_standing', true, true, false); setHumanState(human.modelUuid, 'running'); - setCurrentPhase(human.modelUuid, 'assembling'); + setCurrentPhase(human.modelUuid, 'manufacturing'); setHumanActive(human.modelUuid, true); processStartTimeRef.current = performance.now(); @@ -127,16 +127,16 @@ function AssemblerInstance({ human }: { human: HumanStatus }) { hasLoggedCompleted.current = false; if (!processAnimationIdRef.current) { - processAnimationIdRef.current = requestAnimationFrame(trackAssemblyProcess); + processAnimationIdRef.current = requestAnimationFrame(trackManufactureProcess); } } } else if (human.isActive && human.state === 'running' && human.currentMaterials.length > 0 && humanAsset && humanAsset.animationState?.current === 'working_standing' && humanAsset.animationState?.isCompleted) { - if ((action as HumanAction).assemblyPoint && human.currentPhase === 'assembling') { + if ((action as HumanAction).manufacturePoint && human.currentPhase === 'manufacturing') { setHumanState(human.modelUuid, 'idle'); setCurrentPhase(human.modelUuid, 'waiting'); setHumanActive(human.modelUuid, false); setCurrentAnimation(human.modelUuid, 'idle', true, true, true); - humanStatus(human.modelUuid, 'Human is waiting for material in assembly'); + humanStatus(human.modelUuid, 'Human is waiting for material in manufacture'); decrementHumanLoad(human.modelUuid, 1); const material = removeLastMaterial(human.modelUuid); @@ -150,7 +150,7 @@ function AssemblerInstance({ human }: { human: HumanStatus }) { } }, [human, human.currentPhase, path, isPlaying, humanAsset?.animationState?.isCompleted]); - const trackAssemblyProcess = useCallback(() => { + const trackManufactureProcess = useCallback(() => { const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || ''); const now = performance.now(); @@ -163,7 +163,7 @@ function AssemblerInstance({ human }: { human: HumanStatus }) { if (!lastPauseTimeRef.current) { lastPauseTimeRef.current = now; } - processAnimationIdRef.current = requestAnimationFrame(trackAssemblyProcess); + processAnimationIdRef.current = requestAnimationFrame(trackManufactureProcess); return; } else if (lastPauseTimeRef.current) { accumulatedPausedTimeRef.current += now - lastPauseTimeRef.current; @@ -178,7 +178,7 @@ function AssemblerInstance({ human }: { human: HumanStatus }) { if (human.currentMaterials.length > 0) { setMaterial(human.currentMaterials[0].materialId, (action as HumanAction).swapMaterial || 'Default Material'); } - humanStatus(human.modelUuid, `🟡 Human ${human.modelUuid} reached halfway in assembly.`); + humanStatus(human.modelUuid, `🟡 Human ${human.modelUuid} reached halfway in manufacture.`); } if (elapsed >= totalProcessTimeMs && !hasLoggedCompleted.current) { @@ -188,27 +188,27 @@ function AssemblerInstance({ human }: { human: HumanStatus }) { cancelAnimationFrame(processAnimationIdRef.current); processAnimationIdRef.current = null; } - humanStatus(human.modelUuid, `✅ Human ${human.modelUuid} completed assembly process.`); + humanStatus(human.modelUuid, `✅ Human ${human.modelUuid} completed manufacture process.`); return; } - processAnimationIdRef.current = requestAnimationFrame(trackAssemblyProcess); + processAnimationIdRef.current = requestAnimationFrame(trackManufactureProcess); }, [human.modelUuid, human.currentMaterials]); function handleCallBack() { - if (human.currentPhase === 'init-assembly') { + if (human.currentPhase === 'init-manufacture') { setCurrentPhase(human.modelUuid, 'waiting'); setHumanState(human.modelUuid, 'idle'); setHumanActive(human.modelUuid, false); setCurrentAnimation(human.modelUuid, 'idle', true, true, true); - humanStatus(human.modelUuid, 'Reached assembly point, waiting for material'); + humanStatus(human.modelUuid, 'Reached manufacture point, waiting for material'); setPath([]); } } return ( <> - } - {action && action.actionType === 'assembly' && - + {action && action.actionType === 'manufacturer' && + } {action && action.actionType === 'operator' && diff --git a/app/src/modules/simulation/human/instances/instance/humanUi.tsx b/app/src/modules/simulation/human/instances/instance/humanUi.tsx index 043811a..abaceb5 100644 --- a/app/src/modules/simulation/human/instances/instance/humanUi.tsx +++ b/app/src/modules/simulation/human/instances/instance/humanUi.tsx @@ -10,16 +10,16 @@ import { useVersionContext } from '../../../../builder/version/versionContext'; import { useParams } from 'react-router-dom'; import startPoint from "../../../../../assets/gltf-glb/ui/human-ui-green.glb"; import startEnd from "../../../../../assets/gltf-glb/ui/human-ui-orange.glb"; -import assembly from "../../../../../assets/gltf-glb/ui/human-ui-assembly.glb"; +import manufacture from "../../../../../assets/gltf-glb/ui/human-ui-manufacture.glb"; import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi'; function HumanUi() { const { scene: startScene } = useGLTF(startPoint) as any; const { scene: endScene } = useGLTF(startEnd) as any; - const { scene: assemblyScene } = useGLTF(assembly) as any; + const { scene: manufactureScene } = useGLTF(manufacture) as any; const startMarker = useRef(null); const endMarker = useRef(null); - const assemblyMarker = useRef(null); + const manufactureMarker = useRef(null); const outerGroup = useRef(null); const prevMousePos = useRef({ x: 0, y: 0 }); const { controls, raycaster, camera } = useThree(); @@ -31,9 +31,9 @@ function HumanUi() { const { updateEvent, getActionByUuid } = productStore(); const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 1, 0]); const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 1, 0]); - const [assemblyPosition, setAssemblyPosition] = useState<[number, number, number]>([0, 1, 0]); + const [manufacturePosition, setManufacturePosition] = useState<[number, number, number]>([0, 1, 0]); const [startRotation, setStartRotation] = useState<[number, number, number]>([0, Math.PI, 0]); - const [assemblyRotation, setAssemblyRotation] = useState<[number, number, number]>([0, 0, 0]); + const [manufactureRotation, setManufactureRotation] = useState<[number, number, number]>([0, 0, 0]); const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]); const { isDragging, setIsDragging } = useIsDragging(); const { isRotating, setIsRotating } = useIsRotating(); @@ -51,7 +51,7 @@ function HumanUi() { const { projectId } = useParams(); const currentAction = getActionByUuid(selectedProduct.productUuid, selectedAction.actionId || ''); - const isAssembly = currentAction?.actionType === 'assembly'; + const isManufacture = currentAction?.actionType === 'manufacturer'; const updateBackend = ( productName: string, @@ -90,15 +90,15 @@ function HumanUi() { const action = selectedHuman.point.actions.find(a => a.actionUuid === selectedAction.actionId); if (!action) return; - if (isAssembly) { - if (action.assemblyPoint?.position && outerGroup.current) { - const worldPos = new Vector3(...action.assemblyPoint.position); + if (isManufacture) { + if (action.manufacturePoint?.position && outerGroup.current) { + const worldPos = new Vector3(...action.manufacturePoint.position); const localPosition = outerGroup.current.worldToLocal(worldPos.clone()); - setAssemblyPosition([localPosition.x, 1, localPosition.z]); - setAssemblyRotation(action.assemblyPoint.rotation || [0, 0, 0]); + setManufacturePosition([localPosition.x, 1, localPosition.z]); + setManufactureRotation(action.manufacturePoint.rotation || [0, 0, 0]); } else { - setAssemblyPosition([0, 1, 0]); - setAssemblyRotation([0, 0, 0]); + setManufacturePosition([0, 1, 0]); + setManufactureRotation([0, 0, 0]); } } else { if (action.pickUpPoint?.position && outerGroup.current) { @@ -125,8 +125,8 @@ function HumanUi() { const handlePointerDown = ( e: any, - state: "start" | "end" | "assembly", - rotation: "start" | "end" | "assembly" + state: "start" | "end" | "manufacture", + rotation: "start" | "end" | "manufacture" ) => { e.stopPropagation(); const intersection = new Vector3(); @@ -153,7 +153,7 @@ function HumanUi() { const marker = state === "start" ? startMarker.current : state === "end" ? endMarker.current : - assemblyMarker.current; + manufactureMarker.current; if (marker && localPoint) { const markerPos = new Vector3().copy(marker.position); dragOffset.current.copy(markerPos.sub(localPoint)); @@ -176,17 +176,17 @@ function HumanUi() { const updatedActions = selectedHuman.point.actions.map(action => { if (action.actionUuid !== currentAction.actionUuid) return action; - if (isAssembly) { - if (!assemblyMarker.current || !outerGroup.current) return action; + if (isManufacture) { + if (!manufactureMarker.current || !outerGroup.current) return action; - const worldPosAssembly = new Vector3(...assemblyPosition); - const globalAssemblyPosition = outerGroup.current.localToWorld(worldPosAssembly.clone()); + const worldPosManufacture = new Vector3(...manufacturePosition); + const globalManufacturePosition = outerGroup.current.localToWorld(worldPosManufacture.clone()); return { ...action, - assemblyPoint: { - position: [globalAssemblyPosition.x, globalAssemblyPosition.y, globalAssemblyPosition.z] as [number, number, number], - rotation: assemblyRotation + manufacturePoint: { + position: [globalManufacturePosition.x, globalManufacturePosition.y, globalManufacturePosition.z] as [number, number, number], + rotation: manufactureRotation }, }; } else { @@ -246,8 +246,8 @@ function HumanUi() { setStartPosition([localPoint.x, 1, localPoint.z]); } else if (isDragging === "end") { setEndPosition([localPoint.x, 1, localPoint.z]); - } else if (isDragging === "assembly") { - setAssemblyPosition([localPoint.x, 1, localPoint.z]); + } else if (isDragging === "manufacture") { + setManufacturePosition([localPoint.x, 1, localPoint.z]); } }); @@ -260,7 +260,7 @@ function HumanUi() { const marker = isRotating === "start" ? startMarker.current : isRotating === "end" ? endMarker.current : - assemblyMarker.current; + manufactureMarker.current; if (marker) { const rotationSpeed = 10; @@ -279,7 +279,7 @@ function HumanUi() { marker.rotation.z, ]); } else { - setAssemblyRotation([ + setManufactureRotation([ marker.rotation.x, marker.rotation.y, marker.rotation.z, @@ -303,7 +303,7 @@ function HumanUi() { return () => { window.removeEventListener("pointerup", handleGlobalPointerUp); }; - }, [isDragging, isRotating, startPosition, startRotation, endPosition, endRotation, assemblyPosition, assemblyRotation]); + }, [isDragging, isRotating, startPosition, startRotation, endPosition, endRotation, manufacturePosition, manufactureRotation]); return ( <> @@ -313,16 +313,16 @@ function HumanUi() { ref={outerGroup} rotation={[0, Math.PI, 0]} > - {isAssembly ? ( + {isManufacture ? ( ) } } else if (model.type === 'human') { const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid); - if (action && (triggeredAction?.actionType === 'assembly' || triggeredAction?.actionType === 'worker')) { + if (action && (triggeredAction?.actionType === 'manufacturer' || triggeredAction?.actionType === 'worker')) { handleMaterialDropToHuman(model, triggeredAction); } } else if (model.type === 'crane') { diff --git a/app/src/store/simulation/useSimulationStore.ts b/app/src/store/simulation/useSimulationStore.ts index 2220afd..d1240bb 100644 --- a/app/src/store/simulation/useSimulationStore.ts +++ b/app/src/store/simulation/useSimulationStore.ts @@ -203,8 +203,8 @@ export const useSelectedAnimation = create()( ); interface IsDraggingState { - isDragging: "start" | "end" | "assembly" | null; - setIsDragging: (state: "start" | "end" | "assembly" | null) => void; + isDragging: "start" | "end" | "manufacture" | null; + setIsDragging: (state: "start" | "end" | "manufacture" | null) => void; } export const useIsDragging = create()( @@ -219,8 +219,8 @@ export const useIsDragging = create()( ); interface IsRotatingState { - isRotating: "start" | "end" | "assembly" | null; - setIsRotating: (state: "start" | "end" | "assembly" | null) => void; + isRotating: "start" | "end" | "manufacture" | null; + setIsRotating: (state: "start" | "end" | "manufacture" | null) => void; } export const useIsRotating = create()( diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 1578b5a..abff4bc 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -96,14 +96,14 @@ interface StorageAction { interface HumanAction { actionUuid: string; actionName: string; - actionType: "worker" | "assembly" | "operator"; + actionType: "worker" | "manufacturer" | "operator"; processTime: number; swapMaterial?: string; - assemblyPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } + manufacturePoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } pickUpPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } dropPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } loadCount: number; - assemblyCount: number; + manufactureCount: number; loadCapacity: number; triggers: TriggerSchema[]; } @@ -324,11 +324,11 @@ interface CraneStatus extends CraneEventSchema { type HumanEventState = { humanId: string; actionQueue: { - actionType: 'worker' | 'assembly' | 'operator'; + actionType: 'worker' | 'manufacturer' | 'operator'; actionUuid: string; actionName: string; maxLoadCount: number; - maxAssemblyCount: number; + maxManufactureCount: number; count?: number; isMonitored: boolean; isCompleted: boolean; From 8b01372d086efaf8316e7069716b39e737b4639b Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 23 Aug 2025 10:33:10 +0530 Subject: [PATCH 02/11] human and sidepannel bug fix --- app/src/components/Dashboard/SidePannel.tsx | 2 +- .../properties/eventProperties/mechanics/humanMechanics.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/components/Dashboard/SidePannel.tsx b/app/src/components/Dashboard/SidePannel.tsx index 89ce5ea..f38f0bc 100644 --- a/app/src/components/Dashboard/SidePannel.tsx +++ b/app/src/components/Dashboard/SidePannel.tsx @@ -64,7 +64,7 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { const handleResponse = (data: any) => { if (data.message === "Project created successfully") { setLoadingProgress(1) - navigate(`/${data.data.projectId}`); + navigate(`/projects/${data.data.projectId}`); } projectSocket.off("v1-project:response:add", handleResponse); // Clean up }; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx index 0e003b1..40ad31d 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx @@ -397,7 +397,7 @@ function HumanMechanics() { From 21cd12b518f56f395771445cb8e40c0492e16b06 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 23 Aug 2025 12:26:45 +0530 Subject: [PATCH 03/11] added wall asset visiblity toggle and code optimization --- .../mechanics/humanMechanics.tsx | 9 +++- app/src/modules/builder/asset/assetsGroup.tsx | 5 ++ .../builder/asset/functions/addAssetModel.ts | 5 ++ .../builder/wall/Instances/instance/wall.tsx | 27 ++++++---- .../contextControls/contextControls.tsx | 30 ++++++++++- .../selection2D/moveControls2D.tsx | 4 +- .../selection2D/selectionControls2D.tsx | 6 +-- .../selection3D/copyPasteControls3D.tsx | 23 ++++---- .../selection3D/duplicationControls3D.tsx | 19 +++---- .../selection3D/moveControls3D.tsx | 20 ++----- .../selection3D/rotateControls3D.tsx | 19 ++----- .../selection3D/selectionControls3D.tsx | 26 ++++------ app/src/store/builder/useAssetStore.ts | 52 +++++++++++++++++++ app/src/store/builder/useWallAssetStore.ts | 4 +- app/src/types/simulationTypes.d.ts | 12 ++++- 15 files changed, 172 insertions(+), 89 deletions(-) diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx index 40ad31d..99c1a0c 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx @@ -17,7 +17,7 @@ import { useSceneContext } from "../../../../../../modules/scene/sceneContext"; import { useParams } from "react-router-dom"; function HumanMechanics() { - const [activeOption, setActiveOption] = useState<"worker" | "manufacturer" | "operator">("worker"); + const [activeOption, setActiveOption] = useState<"worker" | "manufacturer" | "operator" | "assembler">("worker"); const [speed, setSpeed] = useState("0.5"); const [loadCount, setLoadCount] = useState(0); const [manufactureCount, setManufactureCount] = useState(0); @@ -118,7 +118,7 @@ function HumanMechanics() { const handleSelectActionType = (actionType: string) => { if (!selectedAction.actionId || !currentAction || !selectedPointData) return; - const updatedAction = { ...currentAction, actionType: actionType as "worker" | "manufacturer" | "operator" }; + const updatedAction = { ...currentAction, actionType: actionType as "worker" | "manufacturer" | "operator" | "assembler" }; const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action); const updatedPoint = { ...selectedPointData, actions: updatedActions }; @@ -306,6 +306,11 @@ function HumanMechanics() { actionName: `Action ${selectedPointData.actions.length + 1}`, actionType: "worker", loadCount: 1, + assemblyCount: 1, + assemblyCondition: { + conditionType: 'material', + materialType: "Default material" + }, manufactureCount: 1, loadCapacity: 1, processTime: 10, diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index 494af0b..9d36efc 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -271,6 +271,11 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) { actionName: "Action 1", actionType: "worker", loadCount: 1, + assemblyCount: 1, + assemblyCondition: { + conditionType: 'material', + materialType: "Default material" + }, manufactureCount: 1, loadCapacity: 1, processTime: 10, diff --git a/app/src/modules/builder/asset/functions/addAssetModel.ts b/app/src/modules/builder/asset/functions/addAssetModel.ts index 19485bb..3eac4a2 100644 --- a/app/src/modules/builder/asset/functions/addAssetModel.ts +++ b/app/src/modules/builder/asset/functions/addAssetModel.ts @@ -389,6 +389,11 @@ async function handleModelLoad( actionName: "Action 1", actionType: "worker", loadCount: 1, + assemblyCount: 1, + assemblyCondition: { + conditionType: 'material', + materialType: "Default material" + }, manufactureCount: 1, loadCapacity: 1, processTime: 10, diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx index 283ec23..2f5b220 100644 --- a/app/src/modules/builder/wall/Instances/instance/wall.tsx +++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx @@ -17,9 +17,9 @@ import material1 from '../../../../../assets/textures/floor/factory wall texture function Wall({ wall }: { readonly wall: Wall }) { const { wallStore, wallAssetStore } = useSceneContext(); - const { walls, addDecal } = wallStore(); - const { wallAssets, getAssetsByWall } = wallAssetStore(); - const assets = getAssetsByWall(wall.wallUuid); + const { walls } = wallStore(); + const { wallAssets, getWallAssetsByWall, setVisibility } = wallAssetStore(); + const assets = getWallAssetsByWall(wall.wallUuid); const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore(); const { togglView } = useToggleView(); const { activeModule } = useModuleStore(); @@ -28,6 +28,7 @@ function Wall({ wall }: { readonly wall: Wall }) { const { getWallType, isWallFlipped } = useWallClassification(walls); const [visible, setVisible] = useState(true); const meshRef = useRef(); + const prevVisibleRef = useRef(null); const wallType = getWallType(wall); const wallFlipped = isWallFlipped(wall); @@ -89,15 +90,23 @@ function Wall({ wall }: { readonly wall: Wall }) { const v = new THREE.Vector3(); const u = new THREE.Vector3(); - if (!wallVisibility && wallType.type === 'room') { + let nextVisible = true; + + if (!wallVisibility && wallType.type === "room") { meshRef.current.getWorldDirection(v); camera.getWorldDirection(u); if (!u || !v) return; - setVisible((2 * v.dot(u)) <= 0.1); - } else { - setVisible(true); + nextVisible = (2 * v.dot(u)) <= 0.1; } - }) + + if (prevVisibleRef.current !== nextVisible) { + prevVisibleRef.current = nextVisible; + setVisible(nextVisible); + assets.forEach((asset) => { + setVisibility(asset.modelUuid, nextVisible); + }) + } + }); return ( - {(assets.length > 0 || (walls[0].wallUuid === wall.wallUuid && wallAssets.length > 0)) ? + {(assets.length > 0 || (walls[0].wallUuid === wall.wallUuid && wallAssets.length > 0)) && visible ? { if (selectedAssets.length === 1) { @@ -68,8 +70,28 @@ function ContextControls() { useEffect(() => { const canvasElement = gl.domElement; + const onPointerDown = (evt: any) => { + if (evt.button === 2) { + isRightMouseDown.current = true; + rightDrag.current = false; + } + }; + + const onPointerMove = () => { + if (isRightMouseDown.current) { + rightDrag.current = true; + } + }; + + const onPointerUp = (evt: any) => { + if (evt.button === 2) { + isRightMouseDown.current = false; + } + }; + const handleContextClick = (event: MouseEvent) => { event.preventDefault(); + if (rightDrag.current) return; if (selectedAssets.length > 0) { setMenuPosition({ x: event.clientX - gl.domElement.width / 2, y: event.clientY - gl.domElement.height / 2 }); setCanRender(true); @@ -85,6 +107,9 @@ function ContextControls() { }; if (selectedAssets.length > 0) { + canvasElement.addEventListener('pointerdown', onPointerDown); + canvasElement.addEventListener('pointermove', onPointerMove); + canvasElement.addEventListener('pointerup', onPointerUp); canvasElement.addEventListener('contextmenu', handleContextClick) } else { setCanRender(false); @@ -95,6 +120,9 @@ function ContextControls() { } return () => { + canvasElement.removeEventListener('pointerdown', onPointerDown); + canvasElement.removeEventListener('pointermove', onPointerMove); + canvasElement.removeEventListener('pointerup', onPointerUp); canvasElement.removeEventListener('contextmenu', handleContextClick); }; }, [gl, selectedAssets]); diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx index f6d04f0..2555a13 100644 --- a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx @@ -19,7 +19,7 @@ function MoveControls2D({ movedObjects, setMovedObjects, pastedObjects, - setpastedObjects, + setPastedObjects, duplicatedObjects, setDuplicatedObjects, rotatedObjects, @@ -525,7 +525,7 @@ function MoveControls2D({ }; const clearSelection = () => { - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); setMovedObjects([]); setRotatedObjects([]); diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx index 3ca6f99..0fd77ec 100644 --- a/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx @@ -28,7 +28,7 @@ const SelectionControls2D: React.FC = () => { const [movedObjects, setMovedObjects] = useState([]); const [rotatedObjects, setRotatedObjects] = useState([]); const [copiedObjects, setCopiedObjects] = useState([]); - const [pastedObjects, setpastedObjects] = useState([]); + const [pastedObjects, setPastedObjects] = useState([]); const [duplicatedObjects, setDuplicatedObjects] = useState([]); const { activeModule } = useModuleStore(); const { socket } = useSocketStore(); @@ -216,7 +216,7 @@ const SelectionControls2D: React.FC = () => { }, [selectionBox, pointer, controls, selectedPoints, setSelectedPoints]); const clearSelection = () => { - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); clearSelectedPoints(); }; @@ -594,7 +594,7 @@ const SelectionControls2D: React.FC = () => { return ( <> - + ); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx index c11a50e..b0542cb 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx @@ -12,17 +12,7 @@ import { useVersionContext } from "../../../../builder/version/versionContext"; // import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; -const CopyPasteControls3D = ({ - copiedObjects, - setCopiedObjects, - pastedObjects, - setpastedObjects, - setDuplicatedObjects, - movedObjects, - setMovedObjects, - rotatedObjects, - setRotatedObjects, -}: any) => { +const CopyPasteControls3D = () => { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const { toggleView } = useToggleView(); const { selectedAssets, setSelectedAssets } = useSelectedAssets(); @@ -32,7 +22,7 @@ const CopyPasteControls3D = ({ const { push3D } = undoRedo3DStore(); const { addEvent } = eventStore(); const { projectId } = useParams(); - const { assets, addAsset, updateAsset, removeAsset, getAssetById } = assetStore(); + const { assets, addAsset, updateAsset, removeAsset, getAssetById, copiedObjects, setCopiedObjects, pastedObjects, setPastedObjects, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { userId, organization } = getUserData(); @@ -177,7 +167,7 @@ const CopyPasteControls3D = ({ return clone; }); - setpastedObjects(newPastedObjects); + setPastedObjects(newPastedObjects); raycaster.setFromCamera(pointer, camera); const intersectionPoint = new THREE.Vector3(); @@ -430,6 +420,11 @@ const CopyPasteControls3D = ({ actionName: "Action 1", actionType: "worker", loadCapacity: 1, + assemblyCount: 1, + assemblyCondition: { + conditionType: 'material', + materialType: "Default material" + }, manufactureCount: 1, loadCount: 1, processTime: 10, @@ -593,7 +588,7 @@ const CopyPasteControls3D = ({ const clearSelection = () => { setMovedObjects([]); - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); setRotatedObjects([]); setSelectedAssets([]); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx index 01c74d0..ae44b21 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx @@ -13,15 +13,7 @@ import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap"; // import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; -const DuplicationControls3D = ({ - duplicatedObjects, - setDuplicatedObjects, - setpastedObjects, - movedObjects, - setMovedObjects, - rotatedObjects, - setRotatedObjects, -}: any) => { +const DuplicationControls3D = () => { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const { toggleView } = useToggleView(); const { selectedAssets, setSelectedAssets } = useSelectedAssets(); @@ -31,7 +23,7 @@ const DuplicationControls3D = ({ const { push3D } = undoRedo3DStore(); const { addEvent } = eventStore(); const { projectId } = useParams(); - const { assets, addAsset, updateAsset, removeAsset, getAssetById } = assetStore(); + const { assets, addAsset, updateAsset, removeAsset, getAssetById, duplicatedObjects, setDuplicatedObjects, setPastedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { userId, organization } = getUserData(); @@ -497,6 +489,11 @@ const DuplicationControls3D = ({ actionName: "Action 1", actionType: "worker", loadCapacity: 1, + assemblyCount: 1, + assemblyCondition: { + conditionType: 'material', + materialType: "Default material" + }, manufactureCount: 1, loadCount: 1, processTime: 10, @@ -660,7 +657,7 @@ const DuplicationControls3D = ({ const clearSelection = () => { setMovedObjects([]); - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); setRotatedObjects([]); setSelectedAssets([]); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx index 21ddd33..d68a17a 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx @@ -15,17 +15,7 @@ import { useVersionContext } from "../../../../builder/version/versionContext"; // import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi'; -function MoveControls3D({ - movedObjects, - setMovedObjects, - pastedObjects, - setpastedObjects, - duplicatedObjects, - setDuplicatedObjects, - rotatedObjects, - setRotatedObjects, - boundingBoxRef, -}: any) { +function MoveControls3D({ boundingBoxRef }: any) { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); @@ -38,7 +28,7 @@ function MoveControls3D({ const { projectId } = useParams(); const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext(); const { push3D } = undoRedo3DStore(); - const { updateAsset, getAssetById } = assetStore(); + const { updateAsset, getAssetById, movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects, rotatedObjects, setRotatedObjects } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); @@ -186,7 +176,7 @@ function MoveControls3D({ canvasElement.removeEventListener("keydown", onKeyDown); canvasElement?.removeEventListener("keyup", onKeyUp); }; - }, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent]); + }, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent, initialStates]); const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => { const pointPosition = new THREE.Vector3().copy(point.position); @@ -220,7 +210,7 @@ function MoveControls3D({ } }); setAxisConstraint(null); - }, 100) + }, 50) }, [movedObjects, initialStates, updateAsset]); useEffect(() => { @@ -462,7 +452,7 @@ function MoveControls3D({ }; const clearSelection = () => { - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); setMovedObjects([]); setRotatedObjects([]); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx index 8ea8e64..5af7a3e 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx @@ -14,16 +14,7 @@ import { handleAssetRotationSnap } from "./functions/handleAssetRotationSnap"; // import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi'; -function RotateControls3D({ - rotatedObjects, - setRotatedObjects, - movedObjects, - setMovedObjects, - pastedObjects, - setpastedObjects, - duplicatedObjects, - setDuplicatedObjects -}: any) { +function RotateControls3D() { const { camera, gl, scene, pointer, raycaster } = useThree(); const { toggleView } = useToggleView(); @@ -35,7 +26,7 @@ function RotateControls3D({ const { projectId } = useParams(); const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext(); const { push3D } = undoRedo3DStore(); - const { updateAsset } = assetStore(); + const { updateAsset, rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); @@ -161,7 +152,7 @@ function RotateControls3D({ canvasElement.removeEventListener("keydown", onKeyDown); canvasElement?.removeEventListener("keyup", onKeyUp); }; - }, [camera, scene, toggleView, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects, keyEvent]); + }, [camera, scene, toggleView, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects, keyEvent, initialPositions, initialRotations]); const resetToInitialRotations = useCallback(() => { setTimeout(() => { @@ -185,7 +176,7 @@ function RotateControls3D({ } } }); - }, 100) + }, 50) }, [rotatedObjects, initialRotations, initialPositions, updateAsset]); useFrame(() => { @@ -397,7 +388,7 @@ function RotateControls3D({ }, [rotatedObjects, eventStore, productStore, selectedProduct, updateBackend, projectId, updateAsset, organization, socket, selectedVersion, userId]); const clearSelection = () => { - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); setMovedObjects([]); setRotatedObjects([]); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx index 4dd2063..1dab7bc 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef } from "react"; import * as THREE from "three"; import { useThree } from "@react-three/fiber"; import { SelectionHelper } from "../selectionHelper"; @@ -23,18 +23,13 @@ const SelectionControls3D: React.FC = () => { const { camera, controls, gl, scene, raycaster, pointer } = useThree(); const { toggleView } = useToggleView(); const { selectedAssets, setSelectedAssets } = useSelectedAssets(); - const [movedObjects, setMovedObjects] = useState([]); - const [rotatedObjects, setRotatedObjects] = useState([]); - const [copiedObjects, setCopiedObjects] = useState([]); - const [pastedObjects, setpastedObjects] = useState([]); - const [duplicatedObjects, setDuplicatedObjects] = useState([]); const boundingBoxRef = useRef(); const { activeModule } = useModuleStore(); const { socket } = useSocketStore(); const { contextAction, setContextAction } = useContextActionStore() const { assetStore, eventStore, productStore, undoRedo3DStore } = useSceneContext(); const { push3D } = undoRedo3DStore(); - const { removeAsset, getAssetById } = assetStore(); + const { removeAsset, getAssetById, movedObjects, rotatedObjects, copiedObjects, pastedObjects, duplicatedObjects, setPastedObjects, setDuplicatedObjects } = assetStore(); const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]); const { toolMode } = useToolMode(); const { selectedVersionStore } = useVersionContext(); @@ -267,13 +262,13 @@ const SelectionControls3D: React.FC = () => { }, [selectionBox, pointer, controls, selectedAssets, setSelectedAssets]); const clearSelection = () => { - setpastedObjects([]); + setPastedObjects([]); setDuplicatedObjects([]); setSelectedAssets([]); }; const deleteSelection = () => { - if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { + if (selectedAssets.length > 0 && duplicatedObjects.length === 0 && pastedObjects.length === 0) { const undoActions: UndoRedo3DAction[] = []; const assetsToDelete: AssetData[] = []; @@ -366,21 +361,22 @@ const SelectionControls3D: React.FC = () => { selectedUUIDs.forEach((uuid: string) => { removeAsset(uuid); }); + + echo.success("Selected models removed!"); + clearSelection(); } - echo.success("Selected models removed!"); - clearSelection(); }; return ( <> - + - + - + - + ); diff --git a/app/src/store/builder/useAssetStore.ts b/app/src/store/builder/useAssetStore.ts index a72f1e2..6fd407c 100644 --- a/app/src/store/builder/useAssetStore.ts +++ b/app/src/store/builder/useAssetStore.ts @@ -1,8 +1,14 @@ +import { Object3D } from 'three'; import { create } from 'zustand'; import { immer } from 'zustand/middleware/immer'; interface AssetsStore { assets: Assets; + movedObjects: Object3D[]; + rotatedObjects: Object3D[]; + copiedObjects: Object3D[]; + pastedObjects: Object3D[]; + duplicatedObjects: Object3D[]; // Asset CRUD operations addAsset: (asset: Asset) => void; @@ -12,6 +18,12 @@ interface AssetsStore { resetAsset: (modelUuid: string) => void; setAssets: (assets: Assets) => void; + setMovedObjects: (objects: Object3D[]) => Object3D[]; + setRotatedObjects: (objects: Object3D[]) => Object3D[]; + setCopiedObjects: (objects: Object3D[]) => Object3D[]; + setPastedObjects: (objects: Object3D[]) => Object3D[]; + setDuplicatedObjects: (objects: Object3D[]) => Object3D[]; + // Asset properties setName: (modelUuid: string, newName: string) => void; setPosition: (modelUuid: string, position: [number, number, number]) => void; @@ -44,6 +56,11 @@ export const createAssetStore = () => { return create()( immer((set, get) => ({ assets: [], + movedObjects: [], + rotatedObjects: [], + copiedObjects: [], + pastedObjects: [], + duplicatedObjects: [], // Asset CRUD operations addAsset: (asset) => { @@ -94,6 +111,41 @@ export const createAssetStore = () => { }); }, + setMovedObjects: (objects) => { + set((state) => { + state.movedObjects = objects; + }); + return objects; + }, + + setRotatedObjects: (objects) => { + set((state) => { + state.rotatedObjects = objects; + }); + return objects; + }, + + setCopiedObjects: (objects) => { + set((state) => { + state.copiedObjects = objects; + }); + return objects; + }, + + setPastedObjects: (objects) => { + set((state) => { + state.pastedObjects = objects; + }); + return objects; + }, + + setDuplicatedObjects: (objects) => { + set((state) => { + state.duplicatedObjects = objects; + }); + return objects; + }, + // Asset properties setName: (modelUuid, newName) => { set((state) => { diff --git a/app/src/store/builder/useWallAssetStore.ts b/app/src/store/builder/useWallAssetStore.ts index d6081d7..dba00d9 100644 --- a/app/src/store/builder/useWallAssetStore.ts +++ b/app/src/store/builder/useWallAssetStore.ts @@ -15,7 +15,7 @@ interface WallAssetStore { setOpacity: (uuid: string, opacity: number) => void; getWallAssetById: (uuid: string) => WallAsset | undefined; - getAssetsByWall: (wallUuid: string) => WallAsset[]; + getWallAssetsByWall: (wallUuid: string) => WallAsset[]; } export const createWallAssetStore = () => { @@ -93,7 +93,7 @@ export const createWallAssetStore = () => { return get().wallAssets.find(a => a.modelUuid === uuid); }, - getAssetsByWall: (wallUuid) => { + getWallAssetsByWall: (wallUuid) => { return get().wallAssets.filter(a => a.wallUuid === wallUuid); }, })) diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index abff4bc..93d0373 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -96,12 +96,22 @@ interface StorageAction { interface HumanAction { actionUuid: string; actionName: string; - actionType: "worker" | "manufacturer" | "operator"; + actionType: "worker" | "manufacturer" | "operator" | "assembler"; processTime: number; swapMaterial?: string; manufacturePoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } + assemblyPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } pickUpPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } dropPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } + assemblyCount: number; + assemblyCondition: { + conditionType: "material"; + materialType: string; + source?: { + sourceUuid: string; + sourceActionUuid: string; + }[]; + } loadCount: number; manufactureCount: number; loadCapacity: number; From 51a580575669e0d1dd6a6fde17762131fa2b4077 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 23 Aug 2025 12:30:33 +0530 Subject: [PATCH 04/11] cod eoptimization --- .../Instances/Instance/floorInstance.tsx | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx index e450aa1..aa60691 100644 --- a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx +++ b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx @@ -30,8 +30,7 @@ import material4NormalMap from "../../../../../assets/textures/floor/tex3/metal_ function FloorInstance({ floor }: { floor: Floor }) { const { togglView } = useToggleView(); const { activeModule } = useModuleStore(); - const { selectedFloor, setSelectedFloor, setSelectedDecal } = - useBuilderStore(); + const { selectedFloor, setSelectedFloor, setSelectedDecal } = useBuilderStore(); const savedTheme = localStorage.getItem("theme"); const materials: Record< @@ -44,12 +43,8 @@ function FloorInstance({ floor }: { floor: Floor }) { textureTileScale?: [number, number]; } > = { - "Default Material": { - map: savedTheme === "dark" ? texturePathDark : texturePath, - }, - "Material 1": { - map: material1, - }, + "Default Material": { map: savedTheme === "dark" ? texturePathDark : texturePath, }, + "Material 1": { map: material1 }, "Material 2": { map: material2Map, roughnessMap: material2MetalicRoughnessMap, @@ -74,9 +69,7 @@ function FloorInstance({ floor }: { floor: Floor }) { const shape = useMemo(() => { const shape = new Shape(); - const points = floor.points.map( - (p) => new Vector2(p.position[0], p.position[2]) - ); + const points = floor.points.map((p) => new Vector2(p.position[0], p.position[2])); if (points.length < 3) return null; shape.moveTo(points[0].x, points[0].y); for (let i = 1; i < points.length; i++) { @@ -94,9 +87,7 @@ function FloorInstance({ floor }: { floor: Floor }) { const roughnessMap = material.roughnessMap || null; const metalnessMap = material.metalnessMap || null; - return [materialMap, normalMap, roughnessMap, metalnessMap].filter( - (texture): texture is string => texture !== null - ); + return [materialMap, normalMap, roughnessMap, metalnessMap].filter((texture): texture is string => texture !== null); } // Default material map @@ -113,16 +104,10 @@ function FloorInstance({ floor }: { floor: Floor }) { // Use loader to load top and side textures const [topTexture, topNormalTexture, topRoughnessTexture, topMetalicTexture] = useLoader(TextureLoader, topTexturesList); - const [ - sideTexture, - sideNormalTexture, - sideRoughnessTexture, - sideMetalicTexture, - ] = useLoader(TextureLoader, sideTexturesList); + const [sideTexture, sideNormalTexture, sideRoughnessTexture, sideMetalicTexture] = useLoader(TextureLoader, sideTexturesList); // Early exit if materials are missing - if (!materials[floor.topMaterial] || !materials[floor.sideMaterial]) - return null; + if (!materials[floor.topMaterial] || !materials[floor.sideMaterial]) return null; // Combine and pair textures with their corresponding material const textureMaterialMap = [ @@ -183,18 +168,14 @@ function FloorInstance({ floor }: { floor: Floor }) { } }} onPointerMissed={() => { - if ( - selectedFloor && - selectedFloor.userData.floorUuid === floor.floorUuid - ) { + if (selectedFloor && selectedFloor.userData.floorUuid === floor.floorUuid) { setSelectedFloor(null); } }} > Date: Sat, 23 Aug 2025 14:29:25 +0530 Subject: [PATCH 05/11] updated forget password functionality with backend --- app/src/components/Dashboard/SidePannel.tsx | 31 +-- .../components/forgotPassword/EmailInput.tsx | 53 +++-- .../components/forgotPassword/OTPInput.tsx | 107 +++++++++- .../forgotPassword/OTP_Verification.tsx | 114 +++++----- .../forgotPassword/PasswordSetup.tsx | 137 ++++++------ app/src/pages/ForgotPassword.tsx | 196 +++++++++++------- app/src/pages/UserAuth.tsx | 46 ++-- .../signInSignUp/changePasswordApi.ts | 29 +++ .../signInSignUp/checkEmailApi.ts | 25 +++ .../signInSignUp/verifyOtpApi.ts | 28 +++ 10 files changed, 519 insertions(+), 247 deletions(-) create mode 100644 app/src/services/factoryBuilder/signInSignUp/changePasswordApi.ts create mode 100644 app/src/services/factoryBuilder/signInSignUp/checkEmailApi.ts create mode 100644 app/src/services/factoryBuilder/signInSignUp/verifyOtpApi.ts diff --git a/app/src/components/Dashboard/SidePannel.tsx b/app/src/components/Dashboard/SidePannel.tsx index 89ce5ea..0fa30d6 100644 --- a/app/src/components/Dashboard/SidePannel.tsx +++ b/app/src/components/Dashboard/SidePannel.tsx @@ -38,11 +38,13 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { const handleCreateNewProject = async () => { const token = localStorage.getItem("token"); - const refreshToken = localStorage.getItem("refreshToken") - console.log('refreshToken: ', refreshToken); + const refreshToken = localStorage.getItem("refreshToken"); + console.log("refreshToken: ", refreshToken); try { const projectId = generateProjectId(); - useSocketStore.getState().initializeSocket(email, organization, token, refreshToken); + useSocketStore + .getState() + .initializeSocket(email, organization, token, refreshToken); //API for creating new Project // const project = await createProject( @@ -59,12 +61,12 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { projectUuid: projectId, }; - console.log('projectSocket: ', projectSocket); + console.log("projectSocket: ", projectSocket); if (projectSocket) { const handleResponse = (data: any) => { if (data.message === "Project created successfully") { - setLoadingProgress(1) - navigate(`/${data.data.projectId}`); + setLoadingProgress(1); + navigate(`/projects/${data.data.projectId}`); } projectSocket.off("v1-project:response:add", handleResponse); // Clean up }; @@ -88,7 +90,8 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => {
{userName - ? userName.charAt(0).toUpperCase() + userName.slice(1).toLowerCase() + ? userName.charAt(0).toUpperCase() + + userName.slice(1).toLowerCase() : "Anonymous"}
@@ -162,10 +165,14 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { Settings -
{ - localStorage.clear(); - navigate("/"); - }}> +
{ + localStorage.clear(); + navigate("/"); + }} + > Log out
@@ -179,4 +186,4 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { ); }; -export default SidePannel; \ No newline at end of file +export default SidePannel; diff --git a/app/src/components/forgotPassword/EmailInput.tsx b/app/src/components/forgotPassword/EmailInput.tsx index d3ca158..4df4d19 100644 --- a/app/src/components/forgotPassword/EmailInput.tsx +++ b/app/src/components/forgotPassword/EmailInput.tsx @@ -1,30 +1,39 @@ -import React from 'react'; +import React from "react"; interface Props { - email: string; - setEmail: (value: string) => void; - onSubmit: () => void; + email: string; + setEmail: (value: string) => void; + onSubmit: (e: React.FormEvent) => void; } const EmailInput: React.FC = ({ email, setEmail, onSubmit }) => { - return ( -
-

Forgot password

-

- Enter your email for the verification process, we will send a 4-digit code to your email. -

-
{ e.preventDefault(); onSubmit(); }}> - setEmail(e.target.value)} - required - /> - -
-
- ); + return ( +
+

Forgot password

+

+ Enter your email for the verification process, we will send a 4-digit + code to your email. +

+
{ + e.preventDefault(); + onSubmit(e); + }} + > + setEmail(e.target.value)} + required + /> + +
+
+ ); }; export default EmailInput; diff --git a/app/src/components/forgotPassword/OTPInput.tsx b/app/src/components/forgotPassword/OTPInput.tsx index e14b45e..3c6fef8 100644 --- a/app/src/components/forgotPassword/OTPInput.tsx +++ b/app/src/components/forgotPassword/OTPInput.tsx @@ -1,10 +1,95 @@ -import React, { useState, useRef, useEffect } from 'react'; +// import React, { useState, useRef, useEffect } from "react"; -const OTPInput: React.FC<{ length?: number; onComplete: (otp: string) => void }> = ({ length = 4, onComplete }) => { - const [otpValues, setOtpValues] = useState(Array(length).fill('')); +// const OTPInput: React.FC<{ +// length?: number; +// onComplete: (otp: string) => void; +// code: string; +// }> = ({ length = 4, onComplete, code }) => { +// const [otpValues, setOtpValues] = useState(Array(length).fill("")); +// const inputsRef = useRef<(HTMLInputElement | null)[]>([]); +// useEffect(() => { +// if (code) { +// console.log("code: ", code); + +// const codeString = String(code); // convert number → string +// setOtpValues(codeString.split("")); +// onComplete(codeString); +// } +// }, [code, length]); +// // Auto focus first input on mount +// useEffect(() => { +// inputsRef.current[0]?.focus(); +// }, []); + +// const handleChange = (value: string, index: number) => { +// if (/^[0-9]?$/.test(value)) { +// const newOtp = [...otpValues]; +// newOtp[index] = value; +// setOtpValues(newOtp); + +// if (value && index < length - 1) { +// inputsRef.current[index + 1]?.focus(); +// } + +// if (newOtp.every((digit) => digit !== "")) { +// console.log('newOtp.join(""): ', newOtp.join("")); +// onComplete(newOtp.join("")); +// } +// } +// }; + +// const handleKeyDown = ( +// e: React.KeyboardEvent, +// index: number +// ) => { +// if (e.key === "Backspace" && !otpValues[index] && index > 0) { +// inputsRef.current[index - 1]?.focus(); +// } +// }; + +// return ( +//
+// {otpValues.map((value, index) => ( +// handleChange(e.target.value, index)} +// onKeyDown={(e) => handleKeyDown(e, index)} +// ref={(el) => (inputsRef.current[index] = el)} +// /> +// ))} +//
+// ); +// }; + +// export default OTPInput; +import React, { useState, useRef, useEffect } from "react"; + +const OTPInput: React.FC<{ + length?: number; + onComplete: (otp: string) => void; + code: string | number; +}> = ({ length = 4, onComplete, code }) => { + const [otpValues, setOtpValues] = useState(Array(length).fill("")); const inputsRef = useRef<(HTMLInputElement | null)[]>([]); - // Auto focus first input on mount + // ✅ Pre-fill inputs if code is passed + useEffect(() => { + if (code) { + const codeString = String(code); + const filled = codeString.split("").slice(0, length); + const padded = filled.concat(Array(length - filled.length).fill("")); + setOtpValues(padded); + if (filled.length === length) { + onComplete(filled.join("")); + } + } + }, [code, length, onComplete]); + + // ✅ Focus first input on mount useEffect(() => { inputsRef.current[0]?.focus(); }, []); @@ -19,14 +104,18 @@ const OTPInput: React.FC<{ length?: number; onComplete: (otp: string) => void }> inputsRef.current[index + 1]?.focus(); } - if (newOtp.every((digit) => digit !== '')) { - onComplete(newOtp.join('')); + // ✅ Only trigger onComplete when all digits are filled + if (newOtp.every((digit) => digit !== "")) { + onComplete(newOtp.join("")); } } }; - const handleKeyDown = (e: React.KeyboardEvent, index: number) => { - if (e.key === 'Backspace' && !otpValues[index] && index > 0) { + const handleKeyDown = ( + e: React.KeyboardEvent, + index: number + ) => { + if (e.key === "Backspace" && !otpValues[index] && index > 0) { inputsRef.current[index - 1]?.focus(); } }; @@ -39,7 +128,7 @@ const OTPInput: React.FC<{ length?: number; onComplete: (otp: string) => void }> type="text" className="otp-input" maxLength={1} - value={value} + value={value ?? ""} onChange={(e) => handleChange(e.target.value, index)} onKeyDown={(e) => handleKeyDown(e, index)} ref={(el) => (inputsRef.current[index] = el)} diff --git a/app/src/components/forgotPassword/OTP_Verification.tsx b/app/src/components/forgotPassword/OTP_Verification.tsx index 8af7836..450f210 100644 --- a/app/src/components/forgotPassword/OTP_Verification.tsx +++ b/app/src/components/forgotPassword/OTP_Verification.tsx @@ -1,57 +1,77 @@ -import React, { useState } from 'react'; -import OTPInput from './OTPInput'; +import React, { FormEvent, useState } from "react"; +import OTPInput from "./OTPInput"; interface Props { - email: string; - timer: number; - setCode: (value: string) => void; - onSubmit: () => void; - resendCode: () => void; + email: string; + code: string; + timer: number; + setCode: (value: string) => void; + onSubmit: (e: React.FormEvent) => void; + resendCode: () => void; } -const OTPVerification: React.FC = ({ email, timer, setCode, onSubmit, resendCode }) => { - const [otp, setOtp] = useState(''); +const OTPVerification: React.FC = ({ + email, + timer, + setCode, + onSubmit, + resendCode, + code, +}) => { + const [otp, setOtp] = useState(""); - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - console.log('otp.length: ', otp.length); - if (otp.length === 4) { - onSubmit(); - } else { - alert('Please enter the 4-digit code'); - } - }; + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); - return ( -
-

Verification

-

- Enter the 4-digit code sent to {email}. -

-
- { setOtp(code); setCode(code); }} /> -
- {timer > 0 - ? `${String(Math.floor(timer / 60)).padStart(2, '0')}:${String(timer % 60).padStart(2, '0')}` - : ''} -
- - -
0 ? 'disabled' : ''}`} - onClick={timer === 0 ? resendCode : undefined} - style={{ cursor: timer === 0 ? 'pointer' : 'not-allowed', opacity: timer === 0 ? 1 : 0.5 }} - > - If you didn’t receive a code, Resend -
+ if (otp.length === 4) { + onSubmit(e); + } else { + alert("Please enter the 4-digit code"); + } + }; + + return ( +
+

Verification

+

+ Enter the 4-digit code sent to {email}. +

+
+ { + setOtp(code); + setCode(codes); + }} + code={code} + /> +
+ {timer > 0 + ? `${String(Math.floor(timer / 60)).padStart(2, "0")}:${String( + timer % 60 + ).padStart(2, "0")}` + : ""}
- ); + + +
0 ? "disabled" : ""}`} + onClick={timer === 0 ? resendCode : undefined} + style={{ + cursor: timer === 0 ? "pointer" : "not-allowed", + opacity: timer === 0 ? 1 : 0.5, + }} + > + If you didn’t receive a code, Resend +
+
+ ); }; export default OTPVerification; diff --git a/app/src/components/forgotPassword/PasswordSetup.tsx b/app/src/components/forgotPassword/PasswordSetup.tsx index 4c6af1c..f8f5658 100644 --- a/app/src/components/forgotPassword/PasswordSetup.tsx +++ b/app/src/components/forgotPassword/PasswordSetup.tsx @@ -1,77 +1,82 @@ -import React, { useState } from 'react'; -import { EyeIcon } from '../icons/ExportCommonIcons'; +import React, { useState } from "react"; +import { EyeIcon } from "../icons/ExportCommonIcons"; interface Props { - newPassword: string; - confirmPassword: string; - setNewPassword: (value: string) => void; - setConfirmPassword: (value: string) => void; - onSubmit: () => void; + newPassword: string; + confirmPassword: string; + setNewPassword: (value: string) => void; + setConfirmPassword: (value: string) => void; + onSubmit: (e: React.FormEvent) => void; } const PasswordSetup: React.FC = ({ - newPassword, - confirmPassword, - setNewPassword, - setConfirmPassword, - onSubmit + newPassword, + confirmPassword, + setNewPassword, + setConfirmPassword, + onSubmit, }) => { - const [showNewPassword, setShowNewPassword] = useState(false); - const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [showNewPassword, setShowNewPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); - return ( -
-

New Password

-

Set the new password for your account so you can login and access all features.

-
{ - e.preventDefault(); - if (newPassword !== confirmPassword) { - alert('Passwords do not match'); - return; - } - onSubmit(); - }} - > -
- setNewPassword(e.target.value)} - required - /> - -
- -
- setConfirmPassword(e.target.value)} - required - /> - -
- - -
+ return ( +
+

New Password

+

+ Set the new password for your account so you can login and access all + features. +

+
{ + e.preventDefault(); + if (newPassword !== confirmPassword) { + alert("Passwords do not match"); + return; + } + onSubmit(e); + }} + > +
+ setNewPassword(e.target.value)} + required + /> +
- ); + +
+ setConfirmPassword(e.target.value)} + required + /> + +
+ + +
+
+ ); }; export default PasswordSetup; diff --git a/app/src/pages/ForgotPassword.tsx b/app/src/pages/ForgotPassword.tsx index 8681996..c2d8374 100644 --- a/app/src/pages/ForgotPassword.tsx +++ b/app/src/pages/ForgotPassword.tsx @@ -1,92 +1,134 @@ -import React, { useState, useEffect } from 'react'; -import { LogoIconLarge } from '../components/icons/Logo'; -import EmailInput from '../components/forgotPassword/EmailInput'; -import OTPVerification from '../components/forgotPassword/OTP_Verification'; -import PasswordSetup from '../components/forgotPassword/PasswordSetup'; -import ConfirmationMessage from '../components/forgotPassword/ConfirmationMessgae'; +import React, { useState, useEffect, FormEvent } from "react"; +import { LogoIconLarge } from "../components/icons/Logo"; +import EmailInput from "../components/forgotPassword/EmailInput"; +import OTPVerification from "../components/forgotPassword/OTP_Verification"; +import PasswordSetup from "../components/forgotPassword/PasswordSetup"; +import ConfirmationMessage from "../components/forgotPassword/ConfirmationMessgae"; +import { changePasswordApi } from "../services/factoryBuilder/signInSignUp/changePasswordApi"; +import { checkEmailApi } from "../services/factoryBuilder/signInSignUp/checkEmailApi"; +import { verifyOtpApi } from "../services/factoryBuilder/signInSignUp/verifyOtpApi"; const ForgotPassword: React.FC = () => { - const [step, setStep] = useState(1); - const [email, setEmail] = useState(''); - const [code, setCode] = useState(''); - const [newPassword, setNewPassword] = useState(''); - const [confirmPassword, setConfirmPassword] = useState(''); - const [timer, setTimer] = useState(30); + const [step, setStep] = useState(1); + const [email, setEmail] = useState(""); + const [code, setCode] = useState(""); + const [newPassword, setNewPassword] = useState(""); + const [confirmPassword, setConfirmPassword] = useState(""); + const [timer, setTimer] = useState(30); + const [resetToken, setResetToken] = useState(""); - useEffect(() => { - let countdown: NodeJS.Timeout; - if (step === 2 && timer > 0) { - countdown = setTimeout(() => setTimer(prev => prev - 1), 1000); - } - return () => clearTimeout(countdown); - }, [step, timer]); - - const handleSubmitEmail = () => { - setStep(2); - setTimer(30); + useEffect(() => { + let countdown: NodeJS.Timeout; + if (step === 2 && timer > 0) { + countdown = setTimeout(() => setTimer((prev) => prev - 1), 1000); } - const resendCode = () => { - // TODO: call API to resend code - setTimer(30); - }; + return () => clearTimeout(countdown); + }, [step, timer]); - return ( -
-
-
- -
+ const resendCode = async () => { + // TODO: call API to resend code + setTimer(30); + try { + const emailResponse = await checkEmailApi(email); + if (emailResponse.message == "OTP sent Successfully") { + setCode(emailResponse.OTP); + } + } catch {} + }; + const handleEmailSubmit = async (e: FormEvent) => { + setTimer(30); + try { + const emailResponse = await checkEmailApi(email); - {step === 1 && ( - <> - - Login - + if (emailResponse.message == "OTP sent Successfully") { + setStep(2); + setCode(emailResponse.OTP); + } + } catch {} + }; - )} + const handleOTPSubmit = async (e: FormEvent) => { + try { + const otpResponse = await verifyOtpApi(email, Number(code)); + if (otpResponse.message == "OTP verified successfully") { + setResetToken(otpResponse.resetToken); + setStep(3); + } else { + alert(otpResponse.message); + } + } catch {} + }; - {step === 2 && ( - <> - setStep(3)} - resendCode={resendCode} - /> - Login - + const handlePasswordSubmit = async (e: FormEvent) => { + try { + const passwordResponse = await changePasswordApi( + resetToken, + newPassword, + confirmPassword + ); + if (passwordResponse.message === "Password reset successfull!!") { + setStep(4); + } + } catch {} + }; - )} - - - {step === 3 && ( - <> - setStep(4)} - /> - Login - - - )} - - - {step === 4 && } - - -
+ return ( +
+
+
+
- ); + + {step === 1 && ( + <> + + + Login + + + )} + + {step === 2 && ( + <> + + + Login + + + )} + + {step === 3 && ( + <> + + + Login + + + )} + + {step === 4 && } +
+
+ ); }; export default ForgotPassword; diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 8c45b77..06352a0 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -34,7 +34,7 @@ const UserAuth: React.FC = () => { useEffect(() => { initializeFingerprint(); - }, []) + }, []); const { userId, organization } = getUserData(); @@ -47,7 +47,6 @@ const UserAuth: React.FC = () => { setError(""); setOrganization(organization); setUserName(res.message.name); - // console.log(' res.userId: ', res.message.userId); localStorage.setItem("userId", res.message.userId); localStorage.setItem("email", res.message.email); localStorage.setItem("userName", res.message.name); @@ -55,33 +54,46 @@ const UserAuth: React.FC = () => { localStorage.setItem("refreshToken", res.message.refreshToken); try { - const projects = await recentlyViewed(organization, res.message.userId); + const projects = await recentlyViewed( + organization, + res.message.userId + ); if (res.message.isShare) { if (Object.values(projects.RecentlyViewed).length > 0) { - const recent_opend_projectID = (Object.values(projects?.RecentlyViewed || {})[0] as any)?._id; - if (Object.values(projects?.RecentlyViewed).filter((val: any) => val._id == recent_opend_projectID)) { - setLoadingProgress(1) - navigate(`/projects/${recent_opend_projectID}`) + const recent_opend_projectID = ( + Object.values(projects?.RecentlyViewed || {})[0] as any + )?._id; + if ( + Object.values(projects?.RecentlyViewed).filter( + (val: any) => val._id == recent_opend_projectID + ) + ) { + setLoadingProgress(1); + navigate(`/projects/${recent_opend_projectID}`); } else { - navigate("/Dashboard") + navigate("/Dashboard"); } } else { setLoadingProgress(1); navigate("/Dashboard"); } } - } catch (error) { console.error("Error fetching recent projects:", error); } } else if (res.message === "User Not Found!!! Kindly signup...") { setError("Account not found"); - } else if (res.message === "Email & Password is invalid...Check the credentials") { - setError(res.message) - } else if (res.message === "Already LoggedIn on another browser....Please logout!!!") { + } else if ( + res.message === "Email & Password is invalid...Check the credentials" + ) { + setError(res.message); + } else if ( + res.message === + "Already LoggedIn on another browser....Please logout!!!" + ) { setError("Already logged in on another browser. Please logout first."); navigate("/"); - setError("") + setError(""); // setError(""); // setOrganization(organization); // setUserName(res.ForceLogoutData.userName); @@ -179,6 +191,7 @@ const UserAuth: React.FC = () => { name="email" value={email} placeholder="Email" + autoComplete="email" onChange={(e) => setEmail(e.target.value)} required /> @@ -188,6 +201,7 @@ const UserAuth: React.FC = () => { type={showPassword ? "text" : "password"} value={password} placeholder="Password" + autoComplete="current-password" onChange={(e) => setPassword(e.target.value)} required /> @@ -201,7 +215,11 @@ const UserAuth: React.FC = () => {
- {isSignIn && Forgot password ?} + {isSignIn && ( + + Forgot password ? + + )} {!isSignIn && (
diff --git a/app/src/services/factoryBuilder/signInSignUp/changePasswordApi.ts b/app/src/services/factoryBuilder/signInSignUp/changePasswordApi.ts new file mode 100644 index 0000000..bc42635 --- /dev/null +++ b/app/src/services/factoryBuilder/signInSignUp/changePasswordApi.ts @@ -0,0 +1,29 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const changePasswordApi = async ( + resetToken: string, + newPassword: string, + confirmPassword: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/V1/Auth/reset-password/${resetToken}`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ newPassword, confirmPassword }), + } + ); + + const result = await response.json(); + + return result; + } catch (error) { + echo.error("Failed to create password"); + if (error instanceof Error) { + return { error: error.message }; + } else { + return { error: "An unknown error occurred" }; + } + } +}; diff --git a/app/src/services/factoryBuilder/signInSignUp/checkEmailApi.ts b/app/src/services/factoryBuilder/signInSignUp/checkEmailApi.ts new file mode 100644 index 0000000..6d8138a --- /dev/null +++ b/app/src/services/factoryBuilder/signInSignUp/checkEmailApi.ts @@ -0,0 +1,25 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const checkEmailApi = async (Email: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/V1/Auth/forgetPassword`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ Email }), + } + ); + + const result = await response.json(); + + return result; + } catch (error) { + echo.error("Failed to create password"); + if (error instanceof Error) { + return { error: error.message }; + } else { + return { error: "An unknown error occurred" }; + } + } +}; diff --git a/app/src/services/factoryBuilder/signInSignUp/verifyOtpApi.ts b/app/src/services/factoryBuilder/signInSignUp/verifyOtpApi.ts new file mode 100644 index 0000000..9b289e5 --- /dev/null +++ b/app/src/services/factoryBuilder/signInSignUp/verifyOtpApi.ts @@ -0,0 +1,28 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const verifyOtpApi = async (Email: string, Otp: number) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/V1/Auth/validate-otp`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + Email, + otp: Number(Otp), + }), + } + ); + + const result = await response.json(); + + return result; + } catch (error) { + echo.error("Failed to create password"); + if (error instanceof Error) { + return { error: error.message }; + } else { + return { error: "An unknown error occurred" }; + } + } +}; From e3bd30743d636eb2a6f8274c965f0701f017ff27 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 23 Aug 2025 15:27:17 +0530 Subject: [PATCH 06/11] 2d undo redo bug fix --- app/src/modules/builder/line/line.tsx | 24 ++++--- app/src/modules/builder/point/point.tsx | 66 ++++++++++++++++++- .../calculateAssetTransformationOnWall.ts | 46 +++++++++++++ .../wallAssetInstance.tsx | 0 .../Instances/wallAssetInstances.tsx | 2 +- .../builder/wallAsset/wallAssetCreator.tsx | 2 +- .../selection2D/moveControls2D.tsx | 21 +++--- app/src/store/builder/useWallStore.ts | 16 ++++- 8 files changed, 153 insertions(+), 24 deletions(-) create mode 100644 app/src/modules/builder/wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall.ts rename app/src/modules/builder/wallAsset/Instances/{Instances => Instance}/wallAssetInstance.tsx (100%) diff --git a/app/src/modules/builder/line/line.tsx b/app/src/modules/builder/line/line.tsx index 474eb9e..fd52915 100644 --- a/app/src/modules/builder/line/line.tsx +++ b/app/src/modules/builder/line/line.tsx @@ -32,7 +32,7 @@ function Line({ points }: Readonly) { const { toolMode } = useToolMode(); const { wallStore, floorStore, zoneStore, undoRedo2DStore } = useSceneContext(); const { push2D } = undoRedo2DStore(); - const { removeWallByPoints, setPosition: setWallPosition, getWallsByPointId } = wallStore(); + const { removeWallByPoints, setPosition: setWallPosition, getWallByPoints, getConnectedWallsByWallId } = wallStore(); const { removeFloorByPoints, setPosition: setFloorPosition, getFloorsByPointId, getFloorsByPoints } = floorStore(); const { removeZoneByPoints, setPosition: setZonePosition, getZonesByPointId, getZonesByPoints } = zoneStore(); const { userId, organization } = getUserData(); @@ -361,27 +361,31 @@ function Line({ points }: Readonly) { const offset = new THREE.Vector3().subVectors(midPoint, hit); setDragOffset(offset); - if (points[0].pointType === 'Wall') { - const walls = getWallsByPointId(points[0].pointUuid); - setInitialPositions({ walls }); - } else if (points[0].pointType === 'Floor') { + if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') { + const wall = getWallByPoints(points); + if (wall) { + const walls = getConnectedWallsByWallId(wall.wallUuid, false); + setInitialPositions({ walls }); + } + } else if (points[0].pointType === 'Floor' && points[0].pointType === 'Floor') { const floors = getFloorsByPointId(points[0].pointUuid); setInitialPositions({ floors }); - } else if (points[0].pointType === 'Zone') { + } else if (points[0].pointType === 'Zone' && points[0].pointType === 'Zone') { const zones = getZonesByPointId(points[0].pointUuid); setInitialPositions({ zones }); } } }; - const handleDragEnd = (points: [Point, Point]) => { + const handleDragEnd = (points: [Point, Point]) => { if (toolMode !== 'move' || !dragOffset) return; handleCanvasCursors('default'); setDragOffset(null); + if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') { - const updatedWalls1 = getWallsByPointId(points[0].pointUuid); - const updatedWalls2 = getWallsByPointId(points[1].pointUuid); - const updatedWalls = [...updatedWalls1, ...updatedWalls2].filter((wall, index, self) => index === self.findIndex((w) => w.wallUuid === wall.wallUuid)); + const wall = getWallByPoints(points); + if (!wall) return; + const updatedWalls = getConnectedWallsByWallId(wall.wallUuid, false); if (updatedWalls.length > 0 && projectId) { updatedWalls.forEach(updatedWall => { diff --git a/app/src/modules/builder/point/point.tsx b/app/src/modules/builder/point/point.tsx index cf44c26..ca11e91 100644 --- a/app/src/modules/builder/point/point.tsx +++ b/app/src/modules/builder/point/point.tsx @@ -19,9 +19,12 @@ import { useSceneContext } from '../../scene/sceneContext'; // import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi'; // import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi'; // import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi'; +// import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi'; +// import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi'; import { getUserData } from '../../../functions/getUserData'; import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors'; +import { calculateAssetTransformationOnWall } from '../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall'; function Point({ point }: { readonly point: Point }) { const materialRef = useRef(null); @@ -32,12 +35,13 @@ function Point({ point }: { readonly point: Point }) { const [dragOffset, setDragOffset] = useState(null); const { socket } = useSocketStore(); const { toolMode } = useToolMode(); - const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore } = useSceneContext(); + const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore } = useSceneContext(); const { push2D } = undoRedo2DStore(); const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore(); const { setPosition: setWallPosition, removePoint: removeWallPoint, getWallsByPointId } = wallStore(); const { setPosition: setFloorPosition, removePoint: removeFloorPoint, getFloorsByPointId } = floorStore(); const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore(); + const { getWallAssetsByWall, updateWallAsset, removeWallAsset } = wallAssetStore(); const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position }); const { hoveredPoint, hoveredLine, setHoveredPoint } = useBuilderStore(); const { selectedPoints } = useSelectedPoints(); @@ -226,6 +230,39 @@ function Point({ point }: { readonly point: Point }) { if (updatedWalls && updatedWalls.length > 0 && projectId) { updatedWalls.forEach((updatedWall) => { + const initialWall = initialPositions.walls?.find(w => w.wallUuid === updatedWall.wallUuid); + + if (initialWall) { + const assetsOnWall = getWallAssetsByWall(updatedWall.wallUuid); + + assetsOnWall.forEach(asset => { + const { position, rotation } = calculateAssetTransformationOnWall(asset, initialWall, updatedWall); + + const updatedWallAsset = updateWallAsset(asset.modelUuid, { + position: [position[0], asset.position[1], position[2]], + rotation: rotation + }); + + if (projectId && updatedWallAsset) { + // API + + // upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset); + + // SOCKET + + const data = { + wallAssetData: updatedWallAsset, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:wall-asset:add', data); + } + }); + } + // API // upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall); @@ -393,6 +430,33 @@ function Point({ point }: { readonly point: Point }) { if (removedWalls.length > 0) { setHoveredPoint(null); removedWalls.forEach(wall => { + const assetsOnWall = getWallAssetsByWall(wall.wallUuid); + + assetsOnWall.forEach((asset) => { + if (projectId && asset) { + + removeWallAsset(asset.modelUuid); + + // API + + // deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid); + + // SOCKET + + const data = { + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization, + modelUuid: asset.modelUuid, + wallUuid: asset.wallUuid + } + + socket.emit('v1:wall-asset:delete', data); + + } + }) + if (projectId) { // API diff --git a/app/src/modules/builder/wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall.ts b/app/src/modules/builder/wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall.ts new file mode 100644 index 0000000..aa881c8 --- /dev/null +++ b/app/src/modules/builder/wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall.ts @@ -0,0 +1,46 @@ +import * as THREE from 'three'; + +const calculateAssetTransformationOnWall = ( + asset: WallAsset, + initialWall: Wall, + newWall: Wall +): { position: [number, number, number], rotation: [number, number, number] } => { + const [initialStartPoint, initialEndPoint] = initialWall.points; + const [newStartPoint, newEndPoint] = newWall.points; + + const initialWallVector = new THREE.Vector3(initialEndPoint.position[0] - initialStartPoint.position[0], 0, initialEndPoint.position[2] - initialStartPoint.position[2]); + + const assetVector = new THREE.Vector3(asset.position[0] - initialStartPoint.position[0], 0, asset.position[2] - initialStartPoint.position[2]); + + const initialWallLength = initialWallVector.length(); + const initialWallNormalized = initialWallVector.normalize(); + const dotProduct = assetVector.dot(initialWallNormalized); + + const projection = initialWallNormalized.clone().multiplyScalar(dotProduct); + const perpendicular = new THREE.Vector3().subVectors(assetVector, projection); + const distanceFromWall = perpendicular.length(); + + const crossProduct = new THREE.Vector3().crossVectors(initialWallNormalized, perpendicular).y; + const signedDistance = distanceFromWall * (crossProduct >= 0 ? 1 : -1); + + const percentage = Math.max(0, Math.min(1, dotProduct / initialWallLength)); + + const newWallVector = new THREE.Vector3(newEndPoint.position[0] - newStartPoint.position[0], 0, newEndPoint.position[2] - newStartPoint.position[2]); + + const x = newStartPoint.position[0] + (newEndPoint.position[0] - newStartPoint.position[0]) * percentage; + const z = newStartPoint.position[2] + (newEndPoint.position[2] - newStartPoint.position[2]) * percentage; + + const newWallNormal = new THREE.Vector3(-newWallVector.z, 0, newWallVector.x).normalize(); + + const offsetX = newWallNormal.x * signedDistance; + const offsetZ = newWallNormal.z * signedDistance; + + const wallAngle = Math.atan2(newWallVector.z, newWallVector.x); + + return { + position: [x + offsetX, asset.position[1], z + offsetZ], + rotation: [0, -wallAngle, 0] + }; +}; + +export { calculateAssetTransformationOnWall }; \ No newline at end of file diff --git a/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx b/app/src/modules/builder/wallAsset/Instances/Instance/wallAssetInstance.tsx similarity index 100% rename from app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx rename to app/src/modules/builder/wallAsset/Instances/Instance/wallAssetInstance.tsx diff --git a/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx b/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx index 581dfe7..d47c263 100644 --- a/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx +++ b/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { useSceneContext } from '../../../scene/sceneContext' import { useToggleView } from '../../../../store/builder/store'; -import WallAssetInstance from './Instances/wallAssetInstance'; +import WallAssetInstance from './Instance/wallAssetInstance'; function WallAssetInstances() { const { wallAssetStore } = useSceneContext(); diff --git a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx index 5001e28..fb95236 100644 --- a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx +++ b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx @@ -9,7 +9,7 @@ import { useVersionContext } from '../version/versionContext'; import { getUserData } from '../../../functions/getUserData'; import closestPointOnLineSegment from '../line/helpers/getClosestPointOnLineSegment'; -import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi'; +// import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi'; function WallAssetCreator() { const { socket } = useSocketStore(); diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx index 2555a13..d71f785 100644 --- a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx @@ -66,7 +66,7 @@ function MoveControls2D({ const onPointerUp = (event: PointerEvent) => { if (!isMoving && movedObjects.length > 0 && event.button === 0) { event.preventDefault(); - placeMovedAssets(); + placeMovedPoints(); } if (!isMoving && movedObjects.length > 0 && event.button === 2) { event.preventDefault(); @@ -180,6 +180,7 @@ function MoveControls2D({ const positions: Record = {}; selectedPoints.forEach((point: THREE.Object3D) => { positions[point.uuid] = new THREE.Vector3().copy(point.position); }); + console.log('positions: ', positions); setInitialPositions(positions); raycaster.setFromCamera(pointer, camera); @@ -221,7 +222,7 @@ function MoveControls2D({ }, 0) }; - const placeMovedAssets = () => { + const placeMovedPoints = () => { if (movedObjects.length === 0) return; const undoPoints: UndoRedo2DDataTypeSchema[] = []; @@ -262,11 +263,11 @@ function MoveControls2D({ lineData: { ...updatedAisle, points: [ - updatedAisle.points[0].pointUuid === point.pointUuid - ? { ...updatedAisle.points[0], position: [old.position.x, old.position.y, old.position.z] } + initialStates[updatedAisle.points[0].pointUuid] ? + { ...updatedAisle.points[0], position: initialStates[updatedAisle.points[0].pointUuid].position } : updatedAisle.points[0], - updatedAisle.points[1].pointUuid === point.pointUuid - ? { ...updatedAisle.points[1], position: [old.position.x, old.position.y, old.position.z] } + initialStates[updatedAisle.points[1].pointUuid] ? + { ...updatedAisle.points[1], position: initialStates[updatedAisle.points[1].pointUuid].position } : updatedAisle.points[1] ] as [Point, Point], }, @@ -302,11 +303,11 @@ function MoveControls2D({ lineData: { ...updatedWall, points: [ - updatedWall.points[0].pointUuid === point.pointUuid - ? { ...updatedWall.points[0], position: [old.position.x, old.position.y, old.position.z] } + initialStates[updatedWall.points[0].pointUuid] ? + { ...updatedWall.points[0], position: initialStates[updatedWall.points[0].pointUuid].position } : updatedWall.points[0], - updatedWall.points[1].pointUuid === point.pointUuid - ? { ...updatedWall.points[1], position: [old.position.x, old.position.y, old.position.z] } + initialStates[updatedWall.points[1].pointUuid] ? + { ...updatedWall.points[1], position: initialStates[updatedWall.points[1].pointUuid].position } : updatedWall.points[1] ] as [Point, Point], }, diff --git a/app/src/store/builder/useWallStore.ts b/app/src/store/builder/useWallStore.ts index 11f7130..db40269 100644 --- a/app/src/store/builder/useWallStore.ts +++ b/app/src/store/builder/useWallStore.ts @@ -25,6 +25,7 @@ interface WallStore { getWallByPoints: (points: Point[]) => Wall | undefined; getWallPointById: (uuid: string) => Point | undefined; getConnectedPoints: (uuid: string) => Point[]; + getConnectedWallsByWallId: (wallUuid: string, skipSelf: boolean) => Wall[]; } export const createWallStore = () => { @@ -178,7 +179,7 @@ export const createWallStore = () => { getWallsByPointId: (uuid) => { return get().walls.filter((a) => { - return a.points.some((p) => p.pointUuid === uuid); + return JSON.parse(JSON.stringify(a.points.some((p) => p.pointUuid === uuid))); }) }, @@ -211,6 +212,19 @@ export const createWallStore = () => { } return connected; }, + + getConnectedWallsByWallId: (wallUuid, skipSelf) => { + const wall = get().walls.find(w => w.wallUuid === wallUuid); + if (!wall) return []; + + const pointUuids = wall.points.map(p => p.pointUuid); + + return get().walls.filter(w => { + if (skipSelf && w.wallUuid === wallUuid) return false; + return w.points.some(p => pointUuids.includes(p.pointUuid)); + }); + }, + })) ) } From 760344b783c9ca0cc10c2f4a684e150540dd97f6 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 23 Aug 2025 15:31:11 +0530 Subject: [PATCH 07/11] bug fix --- .../controls/selectionControls/selection2D/moveControls2D.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx index d71f785..83853e9 100644 --- a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx @@ -180,7 +180,6 @@ function MoveControls2D({ const positions: Record = {}; selectedPoints.forEach((point: THREE.Object3D) => { positions[point.uuid] = new THREE.Vector3().copy(point.position); }); - console.log('positions: ', positions); setInitialPositions(positions); raycaster.setFromCamera(pointer, camera); From e2c5b43c2e05734fe55311bc52eaf58dd589ed9b Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 23 Aug 2025 15:43:19 +0530 Subject: [PATCH 08/11] Refactor SideBarRight component for improved readability and functionality; add DecalProperties component; remove DecalTransformation; update AssetProperties animations rendering; enhance InputRange and RegularDropDown components; adjust styles for better layout; fix state management in decal store. --- app/src/components/Dashboard/SidePannel.tsx | 1 - .../components/forgotPassword/OTPInput.tsx | 68 --- .../components/icons/ExportCommonIcons.tsx | 36 +- .../components/layout/sidebarLeft/Assets.tsx | 519 ++++++++-------- .../layout/sidebarRight/SideBarRight.tsx | 578 ++++++++++-------- .../sidebarRight/customInput/Vector3Input.tsx | 8 +- .../decals/DecalTransformation.tsx | 59 -- .../properties/AssetProperties.tsx | 52 +- .../properties/DecalProperties.tsx | 53 ++ app/src/components/ui/inputs/InputRange.tsx | 56 +- .../components/ui/inputs/RegularDropDown.tsx | 14 +- app/src/components/ui/log/LogList.tsx | 5 +- app/src/store/builder/store.ts | 8 +- .../components/simulation/simulation.scss | 3 +- app/src/styles/layout/sidebar.scss | 20 +- 15 files changed, 741 insertions(+), 739 deletions(-) delete mode 100644 app/src/components/layout/sidebarRight/decals/DecalTransformation.tsx create mode 100644 app/src/components/layout/sidebarRight/properties/DecalProperties.tsx diff --git a/app/src/components/Dashboard/SidePannel.tsx b/app/src/components/Dashboard/SidePannel.tsx index 6e6e461..db7d203 100644 --- a/app/src/components/Dashboard/SidePannel.tsx +++ b/app/src/components/Dashboard/SidePannel.tsx @@ -14,7 +14,6 @@ import lightThemeImage from "../../assets/image/lightThemeProject.png"; import { SettingsIcon, TrashIcon } from "../icons/ExportCommonIcons"; import { getUserData } from "../../functions/getUserData"; import { useLoadingProgress, useSocketStore } from "../../store/builder/store"; -import { createProject } from "../../services/dashboard/createProject"; interface SidePannelProps { setActiveTab: React.Dispatch>; diff --git a/app/src/components/forgotPassword/OTPInput.tsx b/app/src/components/forgotPassword/OTPInput.tsx index 3c6fef8..09d4537 100644 --- a/app/src/components/forgotPassword/OTPInput.tsx +++ b/app/src/components/forgotPassword/OTPInput.tsx @@ -1,71 +1,3 @@ -// import React, { useState, useRef, useEffect } from "react"; - -// const OTPInput: React.FC<{ -// length?: number; -// onComplete: (otp: string) => void; -// code: string; -// }> = ({ length = 4, onComplete, code }) => { -// const [otpValues, setOtpValues] = useState(Array(length).fill("")); -// const inputsRef = useRef<(HTMLInputElement | null)[]>([]); -// useEffect(() => { -// if (code) { -// console.log("code: ", code); - -// const codeString = String(code); // convert number → string -// setOtpValues(codeString.split("")); -// onComplete(codeString); -// } -// }, [code, length]); -// // Auto focus first input on mount -// useEffect(() => { -// inputsRef.current[0]?.focus(); -// }, []); - -// const handleChange = (value: string, index: number) => { -// if (/^[0-9]?$/.test(value)) { -// const newOtp = [...otpValues]; -// newOtp[index] = value; -// setOtpValues(newOtp); - -// if (value && index < length - 1) { -// inputsRef.current[index + 1]?.focus(); -// } - -// if (newOtp.every((digit) => digit !== "")) { -// console.log('newOtp.join(""): ', newOtp.join("")); -// onComplete(newOtp.join("")); -// } -// } -// }; - -// const handleKeyDown = ( -// e: React.KeyboardEvent, -// index: number -// ) => { -// if (e.key === "Backspace" && !otpValues[index] && index > 0) { -// inputsRef.current[index - 1]?.focus(); -// } -// }; - -// return ( -//
-// {otpValues.map((value, index) => ( -// handleChange(e.target.value, index)} -// onKeyDown={(e) => handleKeyDown(e, index)} -// ref={(el) => (inputsRef.current[index] = el)} -// /> -// ))} -//
-// ); -// }; - -// export default OTPInput; import React, { useState, useRef, useEffect } from "react"; const OTPInput: React.FC<{ diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index 00f7f22..72f9ca0 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -1394,7 +1394,7 @@ export const AlertIcon = () => { @@ -1402,7 +1402,7 @@ export const AlertIcon = () => { d="M10.0015 12.1777C10.0679 12.1791 10.1324 12.1997 10.187 12.2373C10.2417 12.275 10.2842 12.328 10.3091 12.3896C10.3339 12.4515 10.3402 12.5197 10.3267 12.585C10.3131 12.6501 10.2802 12.7099 10.2329 12.7568C10.1857 12.8035 10.1254 12.8357 10.0601 12.8486C9.99488 12.8615 9.92713 12.8544 9.86572 12.8291C9.83506 12.8165 9.80623 12.8 9.78076 12.7793L9.71436 12.7061L9.67139 12.6172C9.66175 12.5864 9.65628 12.5541 9.65576 12.5215C9.65579 12.4763 9.66481 12.4314 9.68213 12.3896C9.69961 12.3477 9.72603 12.3093 9.7583 12.2773C9.79045 12.2455 9.82857 12.2203 9.87061 12.2031C9.91219 12.1862 9.95664 12.1776 10.0015 12.1777ZM9.85596 10.998L9.77783 8.09961V8.08887L9.77686 8.07812V8.03125C9.77846 8.01596 9.78187 8.00098 9.78662 7.98633C9.7962 7.95676 9.81179 7.92933 9.83252 7.90625C9.84285 7.89476 9.85427 7.88407 9.8667 7.875L9.90674 7.85156C9.93523 7.83888 9.96642 7.83203 9.99756 7.83203C10.013 7.83203 10.0284 7.83375 10.0435 7.83691L10.0884 7.85156C10.1166 7.86421 10.1418 7.88315 10.1626 7.90625C10.1834 7.92943 10.199 7.95689 10.2085 7.98633C10.2181 8.01596 10.2215 8.04735 10.2183 8.07812L10.2173 8.08887V8.10059L10.145 10.999V11.0059C10.145 11.0441 10.1291 11.0804 10.1021 11.1074C10.0749 11.1345 10.0386 11.1504 10.0005 11.1504C9.96219 11.1504 9.92502 11.1345 9.89795 11.1074C9.87115 11.0804 9.85598 11.0439 9.85596 11.0059V10.998Z" fill="black" stroke="var(--text-color)" - stroke-width="0.555304" + strokeWidth="0.555304" /> ); @@ -1419,17 +1419,17 @@ export const NavigationIcon = () => { ); @@ -1447,8 +1447,8 @@ export const HangTagIcon = () => { @@ -1471,20 +1471,20 @@ export const DecalInfoIcon = () => { ); @@ -1505,13 +1505,13 @@ export const LayeringBottomIcon = () => { width="10.9233" height="9.75071" stroke="var(--text-color)" - stroke-width="0.714277" + strokeWidth="0.714277" /> { width="10.9233" height="9.75071" stroke="var(--text-color)" - stroke-width="0.714277" + strokeWidth="0.714277" /> { @@ -1689,7 +1689,7 @@ export const TargetIcon = () => { diff --git a/app/src/components/layout/sidebarLeft/Assets.tsx b/app/src/components/layout/sidebarLeft/Assets.tsx index bc3a445..c08ef78 100644 --- a/app/src/components/layout/sidebarLeft/Assets.tsx +++ b/app/src/components/layout/sidebarLeft/Assets.tsx @@ -15,270 +15,293 @@ import safety from "../../../assets/image/categories/safety.png"; import feneration from "../../../assets/image/categories/feneration.png"; import decal from "../../../assets/image/categories/decal.png"; import SkeletonUI from "../../templates/SkeletonUI"; -import { AlertIcon, DecalInfoIcon, HangTagIcon, NavigationIcon } from "../../icons/ExportCommonIcons"; +import { + AlertIcon, + DecalInfoIcon, + HangTagIcon, + NavigationIcon, +} from "../../icons/ExportCommonIcons"; // ------------------------------------- interface AssetProp { - filename: string; - thumbnail?: string; - category: string; - description?: string; - tags: string; - url?: string; - uploadDate?: number; - isArchieve?: boolean; - animated?: boolean; - price?: number; - CreatedBy?: string; + filename: string; + thumbnail?: string; + category: string; + description?: string; + tags: string; + url?: string; + uploadDate?: number; + isArchieve?: boolean; + animated?: boolean; + price?: number; + CreatedBy?: string; } interface CategoryListProp { - assetImage?: string; - assetName?: string; - categoryImage: string; - category: string; + assetImage?: string; + assetName?: string; + categoryImage: string; + category: string; } const Assets: React.FC = () => { - const { setSelectedItem } = useSelectedItem(); - const [searchValue, setSearchValue] = useState(""); - const [selectedCategory, setSelectedCategory] = useState(null); - const [categoryAssets, setCategoryAssets] = useState([]); - const [filtereredAssets, setFiltereredAssets] = useState([]); - const [categoryList, setCategoryList] = useState([]); - const [isLoading, setisLoading] = useState(false); // Loading state for assets + const { setSelectedItem } = useSelectedItem(); + const [searchValue, setSearchValue] = useState(""); + const [selectedCategory, setSelectedCategory] = useState(null); + const [categoryAssets, setCategoryAssets] = useState([]); + const [filtereredAssets, setFiltereredAssets] = useState([]); + const [categoryList, setCategoryList] = useState([]); + const [isLoading, setisLoading] = useState(false); // Loading state for assets - const handleSearchChange = (value: string) => { - const searchTerm = value.toLowerCase(); - setSearchValue(value); - if (searchTerm.trim() === "" && !selectedCategory) { - setCategoryAssets([]); - return; - } - const filteredModels = filtereredAssets?.filter((model) => { - if (!model?.tags || !model?.filename || !model?.category) return false; - if (searchTerm.startsWith(":") && searchTerm.length > 1) { - const tagSearchTerm = searchTerm.slice(1); - return model.tags.toLowerCase().includes(tagSearchTerm); - } else if (selectedCategory) { - return ( - model.category - .toLowerCase() - .includes(selectedCategory.toLowerCase()) && - model.filename.toLowerCase().includes(searchTerm) - ); - } else { - return model.filename.toLowerCase().includes(searchTerm); - } - }); + const handleSearchChange = (value: string) => { + const searchTerm = value.toLowerCase(); + setSearchValue(value); + if (searchTerm.trim() === "" && !selectedCategory) { + setCategoryAssets([]); + return; + } + const filteredModels = filtereredAssets?.filter((model) => { + if (!model?.tags || !model?.filename || !model?.category) return false; + if (searchTerm.startsWith(":") && searchTerm.length > 1) { + const tagSearchTerm = searchTerm.slice(1); + return model.tags.toLowerCase().includes(tagSearchTerm); + } else if (selectedCategory) { + return ( + model.category + .toLowerCase() + .includes(selectedCategory.toLowerCase()) && + model.filename.toLowerCase().includes(searchTerm) + ); + } else { + return model.filename.toLowerCase().includes(searchTerm); + } + }); - setCategoryAssets(filteredModels); + setCategoryAssets(filteredModels); + }; + + useEffect(() => { + const filteredAssets = async () => { + try { + const filt = await fetchAssets(); + setFiltereredAssets(filt); + } catch { + echo.error("Filter asset not found"); + } }; + filteredAssets(); + }, [categoryAssets]); - useEffect(() => { - const filteredAssets = async () => { - try { - const filt = await fetchAssets(); - setFiltereredAssets(filt); - } catch { - echo.error("Filter asset not found"); + useEffect(() => { + setCategoryList([ + { category: "Fenestration", categoryImage: feneration }, + { category: "Decals", categoryImage: decal }, + { category: "Vehicles", categoryImage: vehicle }, + { category: "Workstation", categoryImage: workStation }, + { category: "Machines", categoryImage: machines }, + { category: "Workers", categoryImage: worker }, + { category: "Storage", categoryImage: storage }, + { category: "Safety", categoryImage: safety }, + { category: "Office", categoryImage: office }, + ]); + }, []); + + const fetchCategoryAssets = async (asset: any) => { + setisLoading(true); + setSelectedCategory(asset); + try { + const res = await getCategoryAsset(asset); + setCategoryAssets(res); + setFiltereredAssets(res); + setisLoading(false); // End loading + // eslint-disable-next-line + } catch (error) { + echo.error("failed to fetch assets"); + setisLoading(false); + } + }; + + const activeSubcategories = [ + { name: "Safety", icon: }, + { name: "Navigation", icon: }, + { name: "Branding", icon: }, + { name: "Informational", icon: }, + ]; + + const { selectedSubCategory, setSelectedSubCategory } = useDecalStore(); + return ( +
+ +
+
+ {(() => { + if (isLoading) { + return ; // Show skeleton when loading } - }; - filteredAssets(); - }, [categoryAssets]); + if (searchValue) { + return ( +
+
+
+

Results for {searchValue}

+
+
+ {categoryAssets?.map((asset: any, index: number) => ( +
+ {asset.filename} { + setSelectedItem({ + name: asset.filename, + id: asset.AssetID, + type: + asset.type === "undefined" + ? undefined + : asset.type, + }); + }} + /> - useEffect(() => { - setCategoryList([ - { category: "Fenestration", categoryImage: feneration }, - { category: "Decals", categoryImage: decal }, - { category: "Vehicles", categoryImage: vehicle }, - { category: "Workstation", categoryImage: workStation }, - { category: "Machines", categoryImage: machines }, - { category: "Workers", categoryImage: worker }, - { category: "Storage", categoryImage: storage }, - { category: "Safety", categoryImage: safety }, - { category: "Office", categoryImage: office }, - ]); - }, []); +
+ {asset.filename + .split("_") + .map( + (word: any) => + word.charAt(0).toUpperCase() + word.slice(1) + ) + .join(" ")} +
+
+ ))} +
+
+
+ ); + } - const fetchCategoryAssets = async (asset: any) => { - setisLoading(true); - setSelectedCategory(asset); - try { - const res = await getCategoryAsset(asset); - setCategoryAssets(res); - setFiltereredAssets(res); - setisLoading(false); // End loading - // eslint-disable-next-line - } catch (error) { - echo.error("failed to fetch assets"); - setisLoading(false); - } - }; + if (selectedCategory) { + return ( +
+

+ {selectedCategory} + +

+ {selectedCategory === "Decals" && ( + <> +
+ {activeSubcategories.map((cat, index) => ( +
setSelectedSubCategory(cat.name)} + > +
{cat.icon}
+
{cat.name}
+
+ ))} +
+ + )} +
+ {categoryAssets?.map((asset: any, index: number) => ( +
+ {asset.filename} { + setSelectedItem({ + name: asset.filename, + id: asset.AssetID, + type: + asset.type === "undefined" + ? undefined + : asset.type, + category: asset.category, + subType: asset.subType, + }); + }} + /> +
+ {asset.filename + .split("_") + .map( + (word: any) => + word.charAt(0).toUpperCase() + word.slice(1) + ) + .join(" ")} +
+
+ ))} + {categoryAssets.length === 0 && ( +
+ 🚧 The asset shelf is empty. We're working on filling it + up! +
+ )} +
+
+ ); + } - const activeSubcategories = [ - { name: "Safety", icon: }, - { name: "Navigation", icon: }, - { name: "Branding", icon: }, - { name: "Informational", icon: } - ] - - - const { selectedSubCategory, setSelectedSubCategory } = useDecalStore(); - return ( -
- -
-
- {(() => { - if (isLoading) { - return ; // Show skeleton when loading - } - if (searchValue) { - return ( -
-
-
-

Results for {searchValue}

-
-
- {categoryAssets?.map((asset: any, index: number) => ( -
- {asset.filename} { - setSelectedItem({ - name: asset.filename, - id: asset.AssetID, - type: asset.type === "undefined" ? undefined : asset.type - }); - }} - /> - -
- {asset.filename - .split("_") - .map( - (word: any) => - word.charAt(0).toUpperCase() + word.slice(1) - ) - .join(" ")} -
-
- ))} -
-
-
- ); - } - - if (selectedCategory) { - return ( -
-

- {selectedCategory} - -

- - {selectedCategory === "Decals" && - <> -
- {activeSubcategories.map((cat, index) => ( -
setSelectedSubCategory(cat.name)}> -
{cat.icon}
-
{cat.name}
-
- ))} -
- - } -
- {categoryAssets?.map((asset: any, index: number) => ( -
- {asset.filename} { - setSelectedItem({ - name: asset.filename, - id: asset.AssetID, - type: asset.type === "undefined" ? undefined : asset.type, - category: asset.category, - subType: asset.subType - }); - }} - /> -
- {asset.filename.split("_").map((word: any) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ")} -
-
- ))} - {categoryAssets.length === 0 && ( -
- 🚧 The asset shelf is empty. We're working on filling it up! -
- )} -
-
- ); - } - - return ( -
-

Categories

-
- {Array.from( - new Set(categoryList.map((asset) => asset.category)) - ).map((category, index) => { - const categoryInfo = categoryList.find( - (asset) => asset.category === category - ); - return ( -
fetchCategoryAssets(category)} - > - {category} -
{category}
-
- ); - })} -
-
- ); - })()} -
-
-
- ); + return ( +
+

Categories

+
+ {Array.from( + new Set(categoryList.map((asset) => asset.category)) + ).map((category, index) => { + const categoryInfo = categoryList.find( + (asset) => asset.category === category + ); + return ( +
fetchCategoryAssets(category)} + > + {category} +
{category}
+
+ ); + })} +
+
+ ); + })()} +
+
+
+ ); }; export default Assets; diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index bb4e137..0041aaf 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -1,26 +1,28 @@ import React, { useEffect, useState } from "react"; import Header from "./Header"; -import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore"; +import useModuleStore, { + useSubModuleStore, +} from "../../../store/useModuleStore"; import { - AnalysisIcon, - FilePackageIcon, - MechanicsIcon, - PropertiesIcon, - SimulationIcon, + AnalysisIcon, + FilePackageIcon, + MechanicsIcon, + PropertiesIcon, + SimulationIcon, } from "../../icons/SimulationIcons"; import { useToggleStore } from "../../../store/useUIToggleStore"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; import useVersionHistoryVisibleStore, { - useDecalStore, - useSaveVersion, - useSelectedFloorItem, - useToolMode, + useDecalStore, + useSaveVersion, + useSelectedFloorItem, + useToolMode, } from "../../../store/builder/store"; import { - useSelectedEventData, - useSelectedEventSphere, + useSelectedEventData, + useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import GlobalProperties from "./properties/GlobalProperties"; @@ -33,277 +35,319 @@ import WallProperties from "./properties/WallProperties"; import FloorProperties from "./properties/FloorProperties"; import SelectedWallProperties from "./properties/SelectedWallProperties"; import SelectedFloorProperties from "./properties/SelectedFloorProperties"; -import DecalTransformation from "./decals/DecalTransformation"; import ResourceManagement from "./resourceManagement/ResourceManagement"; +import DecalProperties from "./properties/DecalProperties"; type DisplayComponent = - | "versionHistory" - | "globalProperties" - | "aisleProperties" - | "wallProperties" - | "floorProperties" - | "assetProperties" - | "selectedWallProperties" - | "selectedFloorProperties" - | "zoneProperties" - | "simulations" - | "mechanics" - | "analysis" - | "visualization" - | "decals" - | "resourceManagement" - | "none"; + | "versionHistory" + | "globalProperties" + | "aisleProperties" + | "wallProperties" + | "floorProperties" + | "assetProperties" + | "selectedWallProperties" + | "selectedFloorProperties" + | "zoneProperties" + | "simulations" + | "mechanics" + | "analysis" + | "visualization" + | "selectedDecalProperties" + | "resourceManagement" + | "none"; const SideBarRight: React.FC = () => { - const { activeModule } = useModuleStore(); - const { toggleUIRight } = useToggleStore(); - const { toolMode } = useToolMode(); - const { subModule, setSubModule } = useSubModuleStore(); - const { selectedFloorItem } = useSelectedFloorItem(); - const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); - const { selectedEventData } = useSelectedEventData(); - const { selectedEventSphere } = useSelectedEventSphere(); - const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore(); - const { isVersionSaved } = useSaveVersion(); - const { selectedSubCategory } = useDecalStore(); + const { activeModule } = useModuleStore(); + const { toggleUIRight } = useToggleStore(); + const { toolMode } = useToolMode(); + const { subModule, setSubModule } = useSubModuleStore(); + const { selectedFloorItem } = useSelectedFloorItem(); + const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); + const { selectedEventData } = useSelectedEventData(); + const { selectedEventSphere } = useSelectedEventSphere(); + const { viewVersionHistory, setVersionHistoryVisible } = + useVersionHistoryVisibleStore(); + const { isVersionSaved } = useSaveVersion(); + const { selectedSubCategory } = useDecalStore(); - const [displayComponent, setDisplayComponent] = useState("none"); + const [displayComponent, setDisplayComponent] = + useState("none"); - useEffect(() => { - if (activeModule !== "simulation") setSubModule("properties"); - if (activeModule === "simulation") setSubModule("simulations"); - }, [activeModule, setSubModule]); + useEffect(() => { + if (activeModule !== "simulation") setSubModule("properties"); + if (activeModule === "simulation") setSubModule("simulations"); + }, [activeModule, setSubModule]); - useEffect(() => { - if (activeModule !== "mechanics" && selectedEventData && selectedEventSphere) { - setSubModule("mechanics"); - } else if (!selectedEventData && !selectedEventSphere) { - if (activeModule === "simulation") { - setSubModule("simulations"); - } + useEffect(() => { + if ( + activeModule !== "mechanics" && + selectedEventData && + selectedEventSphere + ) { + setSubModule("mechanics"); + } else if (!selectedEventData && !selectedEventSphere) { + if (activeModule === "simulation") { + setSubModule("simulations"); + } + } + if (activeModule !== "simulation") { + setSubModule("properties"); + } + }, [activeModule, selectedEventData, selectedEventSphere, setSubModule]); + + useEffect(() => { + if (activeModule === "visualization") { + setDisplayComponent("visualization"); + return; + } + + if (!isVersionSaved && activeModule === "simulation") { + if (subModule === "simulations") { + setDisplayComponent("simulations"); + return; + } + if (subModule === "mechanics") { + setDisplayComponent("mechanics"); + return; + } + if (subModule === "analysis") { + setDisplayComponent("analysis"); + return; + } + if (subModule === "resourceManagement") { + setDisplayComponent("resourceManagement"); + return; + } + } + + if (activeModule === "simulation" || activeModule === "builder") { + if (subModule === "resourceManagement") { + setDisplayComponent("resourceManagement"); + return; + } + } + + if (subModule === "properties" && activeModule !== "visualization") { + if (selectedFloorItem) { + setDisplayComponent("assetProperties"); + return; + } + if ( + !selectedFloorItem && + !selectedFloor && + !selectedAisle && + selectedWall + ) { + setDisplayComponent("selectedWallProperties"); + return; + } + if ( + !selectedFloorItem && + !selectedWall && + !selectedAisle && + selectedFloor + ) { + setDisplayComponent("selectedFloorProperties"); + return; + } + if (viewVersionHistory) { + setDisplayComponent("versionHistory"); + return; + } + if (selectedSubCategory) { + setDisplayComponent("selectedDecalProperties"); + return; + } + if ( + !selectedFloorItem && + !selectedFloor && + !selectedWall && + !selectedSubCategory + ) { + if (toolMode === "Aisle") { + setDisplayComponent("aisleProperties"); + return; } - if (activeModule !== "simulation") { - setSubModule("properties"); + if (toolMode === "Wall") { + setDisplayComponent("wallProperties"); + return; } - }, [activeModule, selectedEventData, selectedEventSphere, setSubModule]); - - useEffect(() => { - - if (activeModule === "visualization") { - setDisplayComponent("visualization"); - return; + if (toolMode === "Floor") { + setDisplayComponent("floorProperties"); + return; } + setDisplayComponent("globalProperties"); + return; + } + } - if (!isVersionSaved && activeModule === "simulation") { - if (subModule === "simulations") { - setDisplayComponent("simulations"); - return; - } - if (subModule === "mechanics") { - setDisplayComponent("mechanics"); - return; - } - if (subModule === "analysis") { - setDisplayComponent("analysis"); - return; - } - if (subModule === "resourceManagement") { - setDisplayComponent("resourceManagement"); - return; - } - } + if ( + subModule === "zoneProperties" && + (activeModule === "builder" || activeModule === "simulation") + ) { + setDisplayComponent("zoneProperties"); + return; + } + setDisplayComponent("none"); + }, [ + viewVersionHistory, + activeModule, + subModule, + isVersionSaved, + selectedFloorItem, + selectedWall, + selectedFloor, + selectedAisle, + toolMode, + selectedSubCategory, + ]); + const renderComponent = () => { + switch (displayComponent) { + case "versionHistory": + return ; + case "globalProperties": + return ; + case "aisleProperties": + return ; + case "wallProperties": + return ; + case "floorProperties": + return ; + case "assetProperties": + return ; + case "selectedWallProperties": + return ; + case "selectedFloorProperties": + return ; + case "zoneProperties": + return ; + case "simulations": + return ; + case "mechanics": + return ; + case "analysis": + return ; + case "visualization": + return ; + case "selectedDecalProperties": + return ; + case "resourceManagement": + return ; + default: + return null; + } + }; - if (activeModule === "simulation" || activeModule === "builder") { - if (subModule === "resourceManagement") { - setDisplayComponent("resourceManagement"); - return; - } - } - - if (subModule === "properties" && activeModule !== "visualization") { - if (selectedFloorItem) { - setDisplayComponent("assetProperties"); - return; - } - if (!selectedFloorItem && !selectedFloor && !selectedAisle && selectedWall) { - setDisplayComponent("selectedWallProperties"); - return; - } - if (!selectedFloorItem && !selectedWall && !selectedAisle && selectedFloor) { - setDisplayComponent("selectedFloorProperties"); - return; - } - if (viewVersionHistory) { - setDisplayComponent("versionHistory"); - return; - } - if (selectedSubCategory) { - setDisplayComponent("decals"); - return; - } - if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedSubCategory) { - - - if (toolMode === "Aisle") { - setDisplayComponent("aisleProperties"); - return; - } - if (toolMode === "Wall") { - setDisplayComponent("wallProperties"); - return; - } - if (toolMode === "Floor") { - setDisplayComponent("floorProperties"); - return; - } - setDisplayComponent("globalProperties"); - return; - } - - } - - if (subModule === "zoneProperties" && (activeModule === "builder" || activeModule === "simulation")) { - setDisplayComponent("zoneProperties"); - return; - } - - setDisplayComponent("none"); - }, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorItem, selectedWall, selectedFloor, selectedAisle, toolMode, selectedSubCategory]); - - const renderComponent = () => { - - switch (displayComponent) { - case "versionHistory": - return ; - case "globalProperties": - return ; - case "aisleProperties": - return ; - case "wallProperties": - return ; - case "floorProperties": - return ; - case "assetProperties": - return ; - case "selectedWallProperties": - return ; - case "selectedFloorProperties": - return ; - case "zoneProperties": - return ; - case "simulations": - return ; - case "mechanics": - return ; - case "analysis": - return ; - case "visualization": - return ; - case "decals": - return ; - case "resourceManagement": - return ; - default: - return null; - } - }; - - return ( -
-
- {toggleUIRight && ( + return ( +
+
+ {toggleUIRight && ( + <> + {(!isVersionSaved || activeModule !== "simulation") && ( +
+ {activeModule !== "simulation" && ( <> - {(!isVersionSaved || activeModule !== "simulation") && ( -
- - {activeModule !== "simulation" && ( - <> - - - )} - - {activeModule === "simulation" && ( - <> - - - - - )} - - {(activeModule === "builder" || activeModule === "simulation") && ( - - )} - -
- )} - - {displayComponent !== "none" && ( -
-
- {renderComponent()} - {/* */} -
-
- )} + - )} -
- ); + )} + + {activeModule === "simulation" && ( + <> + + + + + )} + + {(activeModule === "builder" || + activeModule === "simulation") && ( + + )} +
+ )} + + {displayComponent !== "none" && ( +
+
+ {renderComponent()} + {/* */} +
+
+ )} + + )} +
+ ); }; -export default SideBarRight; \ No newline at end of file +export default SideBarRight; diff --git a/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx b/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx index 05fee8c..cc473c2 100644 --- a/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx +++ b/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx @@ -1,6 +1,4 @@ import React from "react"; -import { EyeDroperIcon } from "../../../icons/ExportCommonIcons"; -// import { useThree } from "@react-three/fiber"; interface PositionInputProps { onChange: (value: [number, number, number]) => void; // Callback for value change @@ -24,7 +22,7 @@ const Vector3Input: React.FC = ({ if (!value) return; const updatedValue = [...value] as [number, number, number]; updatedValue[index] = parseFloat(newValue) || 0; - // console.log('updatedValue: ', updatedValue); + console.log('updatedValue: ', updatedValue); onChange(updatedValue); }; @@ -42,8 +40,8 @@ const Vector3Input: React.FC = ({ handleChange(i, e.target.value)} + value={value?.[i] !== undefined ? value[i].toFixed(1) : ""} + onChange={(e) => handleChange(i, e.target.value)} placeholder={placeholder} disabled={disabled} /> diff --git a/app/src/components/layout/sidebarRight/decals/DecalTransformation.tsx b/app/src/components/layout/sidebarRight/decals/DecalTransformation.tsx deleted file mode 100644 index 39a30d7..0000000 --- a/app/src/components/layout/sidebarRight/decals/DecalTransformation.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { useState } from 'react'; -import RotationInput from '../customInput/RotationInput'; -import PositionInput from '../customInput/PositionInputs'; -import { LockIcon } from '../../../icons/RealTimeVisulationIcons'; -import { LayeringBottomIcon, LayeringTopIcon, ValueUpdateIcon } from '../../../icons/ExportCommonIcons'; -import decalImage from "../../../../assets/image/sampleDecal.png" -const DecalTransformation = () => { - - - - return ( -
- {["position", "rotation", "scale"].map((transformation) => ( -
-
{transformation}
-
- -
- -
- -
-
-
-
- ))} - -
-
opacity
-
- -
- -
-
- -
-
Layering
- -
-
- -
-
- -
-
-
- -
- -
replace
-
-
- ); -}; - -export default DecalTransformation; - diff --git a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx index 7d50298..4f76584 100644 --- a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx @@ -103,32 +103,32 @@ const AssetProperties: React.FC = () => {
Animations
- {assets.map((asset) => ( - <> - {asset.modelUuid === selectedFloorItem.uuid && - asset.animations && - asset.animations.length > 0 && - asset.animations.map((animation, index) => ( -
-
handleAnimationClick(animation)} - onMouseEnter={() => setHoveredIndex(index)} - onMouseLeave={() => setHoveredIndex(null)} - className="animations-list" - style={{ - background: - hoveredIndex === index - ? "#7b4cd3" - : "var(--background-color)", - }} - > - {animation.charAt(0).toUpperCase() + - animation.slice(1).toLowerCase()} -
-
- ))} - - ))} + {assets.map((asset) => { + if (asset.modelUuid !== selectedFloorItem.uuid || !asset.animations) + return null; + + return asset.animations.map((animation, index) => ( +
+
handleAnimationClick(animation)} + onMouseEnter={() => setHoveredIndex(index)} + onMouseLeave={() => setHoveredIndex(null)} + className="animations-list" + style={{ + background: + hoveredIndex === index + ? "var(--background-color-button)" + : "var(--background-color)", + color: + hoveredIndex === index ? "var(--text-button-color)" : "", + }} + > + {animation.charAt(0).toUpperCase() + + animation.slice(1).toLowerCase()} +
+
+ )); + })}
); diff --git a/app/src/components/layout/sidebarRight/properties/DecalProperties.tsx b/app/src/components/layout/sidebarRight/properties/DecalProperties.tsx new file mode 100644 index 0000000..4163ea5 --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/DecalProperties.tsx @@ -0,0 +1,53 @@ +import { + LayeringBottomIcon, + LayeringTopIcon, +} from "../../../icons/ExportCommonIcons"; +import InputRange from "../../../ui/inputs/InputRange"; +import RotationInput from "../customInput/RotationInput"; +import Vector3Input from "../customInput/Vector3Input"; + +const DecalProperties = () => { + return ( +
+
Decal Propertis
+
+ {}} + value={10} + /> + console.log(value)} + header="Scale" + value={[0, 0, 0] as [number, number, number]} + /> +
+ +
+ console.log(value)} + key={"6"} + /> + +
+
Layering
+ +
+ + +
+
+
+
+ ); +}; + +export default DecalProperties; diff --git a/app/src/components/ui/inputs/InputRange.tsx b/app/src/components/ui/inputs/InputRange.tsx index 1a2f6f5..372edaf 100644 --- a/app/src/components/ui/inputs/InputRange.tsx +++ b/app/src/components/ui/inputs/InputRange.tsx @@ -1,11 +1,12 @@ import React, { useEffect, useState } from "react"; -import * as CONSTANTS from "../../../types/world/worldConstants"; + interface InputToggleProps { - label: string; // Represents the toggle state (on/off) + label: string; min?: number; max?: number; - onClick?: () => void; // Function to handle toggle clicks - onChange?: (value: number) => void; // Function to handle toggle clicks + step?: number; // Added step prop + onClick?: () => void; + onChange?: (value: number) => void; disabled?: boolean; value?: number; onPointerUp?: (value: number) => void; @@ -17,54 +18,46 @@ const InputRange: React.FC = ({ onChange, min, max, + step = 1, // default step disabled, value, onPointerUp, }) => { - const [rangeValue, setRangeValue] = useState(value ? value : 5); + const [rangeValue, setRangeValue] = useState(value ?? 5); function handleChange(e: React.ChangeEvent) { - const newValue = parseInt(e.target.value); // Parse the value to an integer + const newValue = parseFloat(e.target.value); + setRangeValue(newValue); - setRangeValue(newValue); // Update the local state - - if (onChange) { - onChange(newValue); // Call the onChange function if it exists - } + if (onChange) onChange(newValue); } + useEffect(() => { - value && setRangeValue(value); + if (value !== undefined) setRangeValue(value); }, [value]); + function handlePointerUp(e: React.PointerEvent) { - const newValue = parseInt(e.currentTarget.value, 10); // Parse value correctly - - if (onPointerUp) { - onPointerUp(newValue); // Call the callback function if it exists - } + const newValue = parseFloat(e.currentTarget.value); + if (onPointerUp) onPointerUp(newValue); } - function handlekey(e: React.KeyboardEvent) { - const newValue = parseInt(e.currentTarget.value, 10); // Parse value correctly - if (onPointerUp) { - onPointerUp(newValue); // Call the callback function if it exists - } + function handleKey(e: React.KeyboardEvent) { + const newValue = parseFloat(e.currentTarget.value); + if (onPointerUp) onPointerUp(newValue); } return (
-