From bfcb67c3c8ea9e7fa0877bdffe9a1b05a00d2437 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B <jerald@hexrfactory.com> Date: Fri, 25 Apr 2025 11:19:40 +0530 Subject: [PATCH] feat: Enhance EventProperties and mechanics components with new mechanics; refactor action handling and improve state management for various actions --- .../eventProperties/EventProperties.tsx | 122 +------------ .../eventProperties/actions/DelayAction.tsx | 20 ++- .../eventProperties/actions/ProcessAction.tsx | 58 +++++-- .../eventProperties/actions/SpawnAction.tsx | 93 +++++++--- .../eventProperties/actions/SwapAction.tsx | 27 ++- .../eventProperties/actions/TravelAction.tsx | 100 +++++++---- .../mechanics/conveyorMechanics.tsx | 162 ++++++++++++++++-- .../mechanics/machineMechanics.tsx | 116 ++++++++++++- .../mechanics/storageMechanics.tsx | 51 +++++- .../mechanics/vehicleMechanics.tsx | 151 ++++++++++++++-- .../ui/inputs/PreviewSelectionWithUpload.tsx | 6 - .../IntialLoad/loadInitialFloorItems.ts | 2 +- 12 files changed, 663 insertions(+), 245 deletions(-) diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx index 887aaaa..21781f0 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx @@ -25,6 +25,8 @@ import { useProductStore } from "../../../../../store/simulation/useProductStore import ConveyorMechanics from "./mechanics/conveyorMechanics"; import VehicleMechanics from "./mechanics/vehicleMechanics"; import RoboticArmMechanics from "./mechanics/roboticArmMechanics"; +import MachineMechanics from "./mechanics/machineMechanics"; +import StorageMechanics from "./mechanics/storageMechanics"; const EventProperties: React.FC = () => { const actionsContainerRef = useRef<HTMLDivElement>(null); @@ -170,17 +172,6 @@ const EventProperties: React.FC = () => { return "0.5"; }; - const handleActionToggle = (actionUuid: string) => { - const selected = actions.find(action => action.uuid === actionUuid); - if (selected) { - setSelectedItem({ item: selected }); - } - }; - - const handleDeleteAction = (actionUuid: string) => { - // Implementation for delete action - }; - return ( <> <div className="event-proprties-wrapper"> @@ -189,112 +180,11 @@ const EventProperties: React.FC = () => { <div className="header"> <div className="header-value">{selectedEventData?.data.modelName}</div> </div> - <div className="global-props"> - <div className="property-list-container"> - <div className="property-item"> - <InputWithDropDown - label="Speed" - value="0.5" - min={0} - step={0.1} - defaultValue={speed} - max={10} - activeOption="s" - onClick={() => { }} - onChange={(value) => console.log(value)} - /> - </div> - - <div className="property-item"> - <InputWithDropDown - label="Delay" - value="0.5" - min={0} - step={0.1} - defaultValue="0.5" - max={10} - activeOption="s" - onClick={() => { }} - onChange={(value) => console.log(value)} - /> - </div> - </div> - </div> - {assetType === 'roboticArm' && - <div className="actions-list-container"> - <div className="actions"> - <div className="header"> - <div className="header-value">Actions</div> - <div className="add-button" onClick={() => { }}> - <AddIcon /> Add - </div> - </div> - <div - className="lists-main-container" - ref={actionsContainerRef} - style={{ height: "120px" }} - > - <div className="list-container"> - {actions.map((action) => ( - <div - key={action.uuid} - className={`list-item ${selectedItem.item?.uuid === action.uuid ? "active" : ""}`} - > - <div - className="value" - onClick={() => handleActionToggle(action.uuid)} - > - <RenameInput value={action.name} /> - </div> - {actions.length > 1 && ( - <div - className="remove-button" - onClick={() => handleDeleteAction(action.uuid)} - > - <RemoveIcon /> - </div> - )} - </div> - ))} - </div> - <div - className="resize-icon" - id="action-resize" - onMouseDown={(e) => handleResize(e, actionsContainerRef)} - > - <ResizeHeightIcon /> - </div> - </div> - </div> - </div> - } - <div className="selected-actions-details"> - <div className="selected-actions-header"> - <RenameInput value="Action Name" /> - </div> - <div className="selected-actions-list"> - <LabledDropdown - defaultOption={availableActions.defaultOption} - options={availableActions.options} - onSelect={(option) => setActiveOption(option)} - /> - {activeOption === "default" && <DefaultAction />} - {activeOption === "spawn" && <SpawnAction />} - {activeOption === "swap" && <SwapAction />} - {activeOption === "despawn" && <DespawnAction />} - {activeOption === "travel" && <TravelAction />} - {activeOption === "pickAndPlace" && <PickAndPlaceAction />} - {activeOption === "process" && <ProcessAction />} - {activeOption === "store" && <StorageAction />} - </div> - </div> - <div className="tirgger"> - <Trigger /> - </div> - - {/* {assetType === 'conveyor' && <ConveyorMechanics />} + {assetType === 'conveyor' && <ConveyorMechanics />} {assetType === 'vehicle' && <VehicleMechanics />} - {assetType === 'roboticArm' && <RoboticArmMechanics />} */} + {assetType === 'roboticArm' && <RoboticArmMechanics />} + {assetType === 'machine' && <MachineMechanics />} + {assetType === 'storageUnit' && <StorageMechanics />} </> } </div> diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/DelayAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/DelayAction.tsx index e4bceb9..2bb63d4 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/DelayAction.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/DelayAction.tsx @@ -1,19 +1,27 @@ import React from "react"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; -const DelayAction: React.FC = () => { +interface DelayActionProps { + value: string; + defaultValue: string; + min: number; + max: number; + onChange: (value: string) => void; +} + +const DelayAction: React.FC<DelayActionProps> = ({ value, defaultValue, min, max, onChange }) => { return ( <> <InputWithDropDown label="Delay" - value="0.5" - min={0} + value={value} + min={min} step={0.1} - defaultValue="0.5" - max={10} + defaultValue={defaultValue} + max={max} activeOption="s" onClick={() => { }} - onChange={(value) => console.log(value)} + onChange={onChange} /> </> ); diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/ProcessAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/ProcessAction.tsx index a27894e..331cf1b 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/ProcessAction.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/ProcessAction.tsx @@ -2,23 +2,47 @@ import React from "react"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; import SwapAction from "./SwapAction"; -const ProcessAction: React.FC = () => { - return ( - <> - <InputWithDropDown - label="Process Time" - value="6" - min={0} - step={1} - max={10} - defaultValue="0" - activeOption="s" - onClick={() => {}} - onChange={(value) => console.log(value)} - /> - <SwapAction /> - </> - ); +interface ProcessActionProps { + value: string; + min: number; + max: number; + defaultValue: string; + onChange: (value: string) => void; + swapOptions: string[]; + swapDefaultOption: string; + onSwapSelect: (value: string) => void; +} + +const ProcessAction: React.FC<ProcessActionProps> = ({ + value, + min, + max, + defaultValue, + onChange, + swapOptions, + swapDefaultOption, + onSwapSelect, +}) => { + return ( + <> + <InputWithDropDown + label="Process Time" + value={value} + min={min} + step={1} + max={max} + defaultValue={defaultValue} + activeOption="s" + onClick={() => { }} + onChange={onChange} + /> + <SwapAction + options={swapOptions} + defaultOption={swapDefaultOption} + onSelect={onSwapSelect} + /> + </> + ); }; export default ProcessAction; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SpawnAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SpawnAction.tsx index 0c37cdb..7d8002e 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SpawnAction.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SpawnAction.tsx @@ -1,35 +1,72 @@ import React from "react"; import PreviewSelectionWithUpload from "../../../../../ui/inputs/PreviewSelectionWithUpload"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; +import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; -const SpawnAction: React.FC = () => { - return ( - <> - <InputWithDropDown - label="Spawn interval" - value="0" - min={0} - step={1} - defaultValue="0" - max={10} - activeOption="s" - onClick={() => {}} - onChange={(value) => console.log(value)} - /> - <InputWithDropDown - label="Spawn count" - value="0" - min={0} - step={1} - defaultValue="0" - max={10} - activeOption="s" - onClick={() => {}} - onChange={(value) => console.log(value)} - /> - <PreviewSelectionWithUpload /> - </> - ); +interface SpawnActionProps { + onChangeInterval: (value: string) => void; + onChangeCount: (value: string) => void; + defaultOption: string; + options: string[]; + onSelect: (option: string) => void; + intervalValue: string; + countValue: string; + intervalMin: number; + intervalMax: number; + intervalDefaultValue: string; + countMin: number; + countMax: number; + countDefaultValue: string; +} + +const SpawnAction: React.FC<SpawnActionProps> = ({ + onChangeInterval, + onChangeCount, + defaultOption, + options, + onSelect, + intervalValue, + countValue, + intervalMin, + intervalMax, + intervalDefaultValue, + countMin, + countMax, + countDefaultValue, +}) => { + return ( + <> + <InputWithDropDown + label="Spawn interval" + value={intervalValue} + min={intervalMin} + step={1} + defaultValue={intervalDefaultValue} + max={intervalMax} + activeOption="s" + onClick={() => { }} + onChange={onChangeInterval} + /> + <InputWithDropDown + label="Spawn count" + value={countValue} + min={countMin} + step={1} + defaultValue={countDefaultValue} + max={countMax} + activeOption="s" + onClick={() => { }} + onChange={onChangeCount} + /> + {/* <PreviewSelectionWithUpload /> */} + <LabledDropdown + label="Presets" + defaultOption={defaultOption} + options={options} + onSelect={onSelect} + /> + </> + ); }; export default SpawnAction; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SwapAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SwapAction.tsx index 2e18d80..23b203f 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SwapAction.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/SwapAction.tsx @@ -1,12 +1,27 @@ import React from "react"; import PreviewSelectionWithUpload from "../../../../../ui/inputs/PreviewSelectionWithUpload"; +import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; -const SwapAction: React.FC = () => { - return ( - <> - <PreviewSelectionWithUpload /> - </> - ); +interface SwapActionProps { + onSelect: (option: string) => void; + defaultOption: string; + options: string[]; +} + +const SwapAction: React.FC<SwapActionProps> = ({ onSelect, defaultOption, options }) => { + + return ( + <> + {/* <PreviewSelectionWithUpload /> */} + + <LabledDropdown + label="Presets" + defaultOption={defaultOption} + options={options} + onSelect={onSelect} + /> + </> + ); }; export default SwapAction; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/TravelAction.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/TravelAction.tsx index ee4bda0..49eb683 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/actions/TravelAction.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/actions/TravelAction.tsx @@ -2,35 +2,77 @@ import React from "react"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; import EyeDropInput from "../../../../../ui/inputs/EyeDropInput"; -const TravelAction: React.FC = () => { - return ( - <> - <InputWithDropDown - label="Load Capacity" - value="" - min={0} - step={0.1} - max={10} - defaultValue="0" - activeOption="s" - onClick={() => {}} - onChange={(value) => console.log(value)} - /> - <InputWithDropDown - label="Unload Duration" - value="" - min={0} - step={0.1} - max={10} - defaultValue="0" - activeOption="s" - onClick={() => {}} - onChange={(value) => console.log(value)} - /> - <EyeDropInput label="Pick Point" value="na" onChange={() => {}} /> - <EyeDropInput label="Unload Point" value="na" onChange={() => {}} /> - </> - ); +interface TravelActionProps { + loadCapacity: { + value: string; + min: number; + max: number; + defaultValue: string; + onChange: (value: string) => void; + }; + unloadDuration: { + value: string; + min: number; + max: number; + defaultValue: string; + onChange: (value: string) => void; + }; + pickPoint?: { + value: string; + onChange: (value: string) => void; + }; + unloadPoint?: { + value: string; + onChange: (value: string) => void; + }; +} + +const TravelAction: React.FC<TravelActionProps> = ({ + loadCapacity, + unloadDuration, + pickPoint, + unloadPoint, +}) => { + return ( + <> + <InputWithDropDown + label="Load Capacity" + value={loadCapacity.value} + min={loadCapacity.min} + max={loadCapacity.max} + defaultValue={loadCapacity.defaultValue} + step={0.1} + activeOption="s" + onClick={() => { }} + onChange={loadCapacity.onChange} + /> + <InputWithDropDown + label="Unload Duration" + value={unloadDuration.value} + min={unloadDuration.min} + max={unloadDuration.max} + defaultValue={unloadDuration.defaultValue} + step={0.1} + activeOption="s" + onClick={() => { }} + onChange={unloadDuration.onChange} + /> + {pickPoint && ( + <EyeDropInput + label="Pick Point" + value={pickPoint.value} + onChange={pickPoint.onChange} + /> + )} + {unloadPoint && ( + <EyeDropInput + label="Unload Point" + value={unloadPoint.value} + onChange={unloadPoint.onChange} + /> + )} + </> + ); }; export default TravelAction; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx index 4f3122b..c13bd75 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx @@ -12,27 +12,116 @@ import { useSelectedEventData, useSelectedProduct } from "../../../../../../stor import { useProductStore } from "../../../../../../store/simulation/useProductStore"; function ConveyorMechanics() { - const [activeOption, setActiveOption] = useState("default"); - const [selectedPointData, setSelectedPointData] = useState<PointsScheme | undefined>(); + const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default"); + const [selectedPointData, setSelectedPointData] = useState<ConveyorPointSchema | undefined>(); const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid } = useProductStore(); + const { getPointByUuid, updateEvent, updateAction } = useProductStore(); const { selectedProduct } = useSelectedProduct(); useEffect(() => { if (selectedEventData) { - const point = getPointByUuid(selectedProduct.productId, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint); + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData?.data.modelUuid, + selectedEventData?.selectedPoint + ) as ConveyorPointSchema | undefined; if (point && 'action' in point) { - setSelectedPointData(point as PointsScheme & { action: { actionType: string } }); - setActiveOption((point as PointsScheme & { action: { actionType: string } }).action.actionType); + setSelectedPointData(point); + setActiveOption(point.action.actionType as "default" | "spawn" | "swap" | "delay" | "despawn"); } } }, [selectedProduct, selectedEventData]) + const handleSpeedChange = (value: string) => { + if (!selectedEventData) return; + updateEvent( + selectedProduct.productId, + selectedEventData.data.modelUuid, + { speed: parseFloat(value) } + ); + }; + + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as "default" | "spawn" | "swap" | "delay" | "despawn"; + setActiveOption(validOption); + + updateAction( + selectedPointData.action.actionUuid, + { actionType: validOption } + ); + }; + + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { actionName: newName } + ); + }; + + const handleSpawnCountChange = (value: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { spawnCount: value === "inherit" ? "inherit" : parseFloat(value) } + ); + }; + + const handleSpawnIntervalChange = (value: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { spawnInterval: value === "inherit" ? "inherit" : parseFloat(value) } + ); + }; + + const handleMaterialSelect = (material: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { material } + ); + }; + + const handleDelayChange = (value: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { delay: value === "inherit" ? "inherit" : parseFloat(value) } + ); + }; + const availableActions = { defaultOption: "default", options: ["default", "spawn", "swap", "delay", "despawn"], }; + // Get current values from store + const currentSpeed = selectedEventData?.data.type === "transfer" + ? selectedEventData.data.speed.toString() + : "0.5"; + + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; + + const currentMaterial = selectedPointData + ? selectedPointData.action.material + : "Default material"; + + const currentSpawnCount = selectedPointData + ? selectedPointData.action.spawnCount?.toString() || "1" + : "1"; + + const currentSpawnInterval = selectedPointData + ? selectedPointData.action.spawnInterval?.toString() || "1" + : "1"; + + const currentDelay = selectedPointData + ? selectedPointData.action.delay?.toString() || "0" + : "0"; + return ( <> {selectedEventData && @@ -42,14 +131,14 @@ function ConveyorMechanics() { <div className="property-item"> <InputWithDropDown label="Speed" - value="0.5" + value={currentSpeed} min={0} step={0.1} defaultValue={"0.5"} max={10} - activeOption="s" + activeOption="m/s" onClick={() => { }} - onChange={(value) => console.log(value)} + onChange={handleSpeedChange} /> </div> </div> @@ -57,21 +146,58 @@ function ConveyorMechanics() { <div className="selected-actions-details"> <div className="selected-actions-header"> - <RenameInput value="Action Name" /> + <RenameInput + value={currentActionName} + onRename={handleRenameAction} + /> </div> <div className="selected-actions-list"> <LabledDropdown - defaultOption={selectedPointData && 'action' in selectedPointData - ? (selectedPointData as PointsScheme & { action: { actionType: string } }).action.actionType + defaultOption={selectedPointData + ? selectedPointData.action.actionType : "default"} options={availableActions.options} - onSelect={(option) => setActiveOption(option)} + onSelect={handleActionTypeChange} /> - {activeOption === "default" && <DefaultAction />} - {activeOption === "spawn" && <SpawnAction />} - {activeOption === "swap" && <SwapAction />} - {activeOption === "despawn" && <DespawnAction />} - {activeOption === "delay" && <DelayAction />} + {activeOption === "default" && + <DefaultAction /> + } + {activeOption === "spawn" && + <SpawnAction + onChangeCount={handleSpawnCountChange} + options={["Default material", "Material 1", "Material 2"]} + defaultOption={currentMaterial} + onSelect={handleMaterialSelect} + onChangeInterval={handleSpawnIntervalChange} + intervalValue={currentSpawnInterval} + countValue={currentSpawnCount} + intervalMin={1} + intervalMax={60} + intervalDefaultValue="1" + countMin={1} + countMax={100} + countDefaultValue="1" + /> + } + {activeOption === "swap" && + <SwapAction + options={["Default material", "Material 1", "Material 2"]} + defaultOption={currentMaterial} + onSelect={handleMaterialSelect} + /> + } + {activeOption === "despawn" && + <DespawnAction /> + } + {activeOption === "delay" && + <DelayAction + value={currentDelay} + defaultValue="0" + min={0} + max={60} + onChange={handleDelayChange} + /> + } </div> </div> <div className="tirgger"> diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx index b6e4fb9..138ed7c 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx @@ -1,8 +1,122 @@ -import React from 'react' +import { useEffect, useState } from 'react' +import RenameInput from '../../../../../ui/inputs/RenameInput' +import LabledDropdown from '../../../../../ui/inputs/LabledDropdown' +import Trigger from '../trigger/Trigger' +import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; +import { useProductStore } from "../../../../../../store/simulation/useProductStore"; +import ProcessAction from '../actions/ProcessAction' function MachineMechanics() { + const [activeOption, setActiveOption] = useState<"default" | "process">("default"); + const [selectedPointData, setSelectedPointData] = useState<MachinePointSchema | undefined>(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid, updateAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData?.data.modelUuid, + selectedEventData?.selectedPoint + ) as MachinePointSchema | undefined; + if (point && 'action' in point) { + setSelectedPointData(point); + setActiveOption(point.action.actionType as "process"); + } + } + }, [selectedProduct, selectedEventData]) + + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as "process"; + setActiveOption(validOption); + + updateAction( + selectedPointData.action.actionUuid, + { actionType: validOption } + ); + }; + + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { actionName: newName } + ); + }; + + const handleProcessTimeChange = (value: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { processTime: parseFloat(value) } + ); + }; + + const handleMaterialSelect = (material: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { swapMaterial: material } + ); + }; + + // Get current values from store + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; + + const currentProcessTime = selectedPointData + ? selectedPointData.action.processTime.toString() + : "1"; + + const currentMaterial = selectedPointData + ? selectedPointData.action.swapMaterial + : "Default material"; + + const availableActions = { + defaultOption: "process", + options: ["process"], + }; + return ( <> + {selectedEventData && + <> + <div className="selected-actions-details"> + <div className="selected-actions-header"> + <RenameInput + value={currentActionName} + onRename={handleRenameAction} + /> + </div> + <div className="selected-actions-list"> + <LabledDropdown + defaultOption="process" + options={availableActions.options} + onSelect={handleActionTypeChange} + disabled={true} + /> + {activeOption === "process" && + <ProcessAction + value={currentProcessTime} + min={0.1} + max={60} + defaultValue="1" + onChange={handleProcessTimeChange} + swapOptions={["Default material", "Material 1", "Material 2"]} + swapDefaultOption={currentMaterial} + onSwapSelect={handleMaterialSelect} + /> + } + </div> + </div> + <div className="tirgger"> + <Trigger /> + </div> + </> + } </> ) } diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx index 0cda40e..d513768 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx @@ -1,8 +1,57 @@ -import React from 'react' +import { useEffect, useState } from 'react' +import RenameInput from '../../../../../ui/inputs/RenameInput' +import LabledDropdown from '../../../../../ui/inputs/LabledDropdown' +import Trigger from '../trigger/Trigger' +import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; +import { useProductStore } from "../../../../../../store/simulation/useProductStore"; +import StorageAction from '../actions/StorageAction'; function StorageMechanics() { + const [activeOption, setActiveOption] = useState("default"); + const [selectedPointData, setSelectedPointData] = useState<PointsScheme | undefined>(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid(selectedProduct.productId, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint); + if (point && 'action' in point) { + setSelectedPointData(point as PointsScheme & { action: { actionType: string } }); + setActiveOption((point as PointsScheme & { action: { actionType: string } }).action.actionType); + } + } + }, [selectedProduct, selectedEventData]) + + const availableActions = { + defaultOption: "store", + options: ["store", "spawn"], + }; + return ( <> + {selectedEventData && + <> + <div className="selected-actions-details"> + <div className="selected-actions-header"> + <RenameInput value="Action Name" /> + </div> + <div className="selected-actions-list"> + <LabledDropdown + defaultOption={selectedPointData && 'action' in selectedPointData + ? (selectedPointData as PointsScheme & { action: { actionType: string } }).action.actionType + : "default"} + options={availableActions.options} + onSelect={(option) => setActiveOption(option)} + /> + {activeOption === "store" && <StorageAction />} + </div> + </div> + <div className="tirgger"> + <Trigger /> + </div> + </> + } </> ) } diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx index b689734..cc2bfa0 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx @@ -8,22 +8,114 @@ import { useProductStore } from "../../../../../../store/simulation/useProductSt import TravelAction from '../actions/TravelAction' function VehicleMechanics() { - const [activeOption, setActiveOption] = useState("default"); - const [selectedPointData, setSelectedPointData] = useState<PointsScheme | undefined>(); + const [activeOption, setActiveOption] = useState<"default" | "travel">("default"); + const [selectedPointData, setSelectedPointData] = useState<VehiclePointSchema | undefined>(); const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid } = useProductStore(); + const { getPointByUuid, updateEvent, updateAction } = useProductStore(); const { selectedProduct } = useSelectedProduct(); useEffect(() => { if (selectedEventData) { - const point = getPointByUuid(selectedProduct.productId, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint); - if (point && 'action' in point) { - setSelectedPointData(point as PointsScheme & { action: { actionType: string } }); - setActiveOption((point as PointsScheme & { action: { actionType: string } }).action.actionType); + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData.data.modelUuid, + selectedEventData.selectedPoint + ) as VehiclePointSchema | undefined; + + if (point) { + setSelectedPointData(point); + setActiveOption(point.action.actionType as "travel"); } } }, [selectedProduct, selectedEventData]) + const handleSpeedChange = (value: string) => { + if (!selectedEventData) return; + updateEvent( + selectedProduct.productId, + selectedEventData.data.modelUuid, + { speed: parseFloat(value) } + ); + }; + + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as "travel"; + setActiveOption(validOption); + + updateAction( + selectedPointData.action.actionUuid, + { actionType: validOption } + ); + }; + + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { actionName: newName } + ); + }; + + const handleLoadCapacityChange = (value: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { loadCapacity: parseFloat(value) } + ); + }; + + const handleUnloadDurationChange = (value: string) => { + if (!selectedPointData) return; + updateAction( + selectedPointData.action.actionUuid, + { unLoadDuration: parseFloat(value) } + ); + }; + + const handlePickPointChange = (value: string) => { + if (!selectedPointData) return; + const [x, y, z] = value.split(',').map(Number); + updateAction( + selectedPointData.action.actionUuid, + { pickUpPoint: { x, y, z } } + ); + }; + + const handleUnloadPointChange = (value: string) => { + if (!selectedPointData) return; + const [x, y, z] = value.split(',').map(Number); + updateAction( + selectedPointData.action.actionUuid, + { unLoadPoint: { x, y, z } } + ); + }; + + // Get current values from store + const currentSpeed = selectedEventData?.data.type === "vehicle" + ? selectedEventData.data.speed.toString() + : "0.5"; + + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; + + const currentLoadCapacity = selectedPointData + ? selectedPointData.action.loadCapacity.toString() + : "1"; + + const currentUnloadDuration = selectedPointData + ? selectedPointData.action.unLoadDuration.toString() + : "1"; + + const currentPickPoint = selectedPointData?.action.pickUpPoint + ? `${selectedPointData.action.pickUpPoint.x},${selectedPointData.action.pickUpPoint.y},${selectedPointData.action.pickUpPoint.z}` + : ""; + + const currentUnloadPoint = selectedPointData?.action.unLoadPoint + ? `${selectedPointData.action.unLoadPoint.x},${selectedPointData.action.unLoadPoint.y},${selectedPointData.action.unLoadPoint.z}` + : ""; + const availableActions = { defaultOption: "travel", options: ["travel"], @@ -38,14 +130,14 @@ function VehicleMechanics() { <div className="property-item"> <InputWithDropDown label="Speed" - value="0.5" + value={currentSpeed} min={0} step={0.1} defaultValue={"0.5"} max={10} - activeOption="s" + activeOption="m/s" onClick={() => { }} - onChange={(value) => console.log(value)} + onChange={handleSpeedChange} /> </div> </div> @@ -53,17 +145,44 @@ function VehicleMechanics() { <div className="selected-actions-details"> <div className="selected-actions-header"> - <RenameInput value="Action Name" /> + <RenameInput + value={currentActionName} + onRename={handleRenameAction} + /> </div> <div className="selected-actions-list"> <LabledDropdown - defaultOption={selectedPointData && 'action' in selectedPointData - ? (selectedPointData as PointsScheme & { action: { actionType: string } }).action.actionType - : "default"} + defaultOption="travel" options={availableActions.options} - onSelect={(option) => setActiveOption(option)} + onSelect={handleActionTypeChange} /> - {activeOption === "travel" && <TravelAction />} + + {activeOption === 'travel' && + <TravelAction + loadCapacity={{ + value: currentLoadCapacity, + min: 1, + max: 100, + defaultValue: "1", + onChange: handleLoadCapacityChange, + }} + unloadDuration={{ + value: currentUnloadDuration, + min: 1, + max: 60, + defaultValue: "1", + onChange: handleUnloadDurationChange, + }} + // pickPoint={{ + // value: currentPickPoint, + // onChange: handlePickPointChange, + // }} + // unloadPoint={{ + // value: currentUnloadPoint, + // onChange: handleUnloadPointChange, + // }} + /> + } </div> </div> <div className="tirgger"> diff --git a/app/src/components/ui/inputs/PreviewSelectionWithUpload.tsx b/app/src/components/ui/inputs/PreviewSelectionWithUpload.tsx index e2c2936..3e14517 100644 --- a/app/src/components/ui/inputs/PreviewSelectionWithUpload.tsx +++ b/app/src/components/ui/inputs/PreviewSelectionWithUpload.tsx @@ -35,12 +35,6 @@ const PreviewSelectionWithUpload: React.FC = () => { Upload here </label> </div> - <LabledDropdown - label="Presets" - defaultOption={"Default material"} - options={["Default material", "Product 1", "Product 2"]} - onSelect={(option) => console.log(option)} - /> </div> </div> ); diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts index 2378bf3..82b5596 100644 --- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts +++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts @@ -243,7 +243,7 @@ function processLoadedModel( rotation: [0, 0, 0], action: { actionUuid: THREE.MathUtils.generateUUID(), - actionName: `Action ${index}`, + actionName: `Action ${index + 1}`, actionType: 'default', material: 'inherit', delay: 0,