feat: Refactor product selection and comparison functionality

- Created a new store for selected products using Zustand and immer for state management.
- Introduced `useMainProduct` and `useComparisonProduct` hooks to manage main and comparison products.
- Implemented `ComparisonScene` and `ComparisonSceneProvider` components to handle product comparisons.
- Updated `MainScene` to allow selection of main products with a dropdown.
- Enhanced styles for comparison layout and product selection UI.
- Established a context for product management to streamline state access across components.
This commit is contained in:
Jerald-Golden-B 2025-05-29 12:00:16 +05:30
parent 5e58606f8f
commit d3ea36d1ba
46 changed files with 996 additions and 776 deletions

View File

@ -0,0 +1,48 @@
import { useProductContext } from '../../../modules/simulation/products/productContext'
import RegularDropDown from '../../ui/inputs/RegularDropDown';
import { useProductStore } from '../../../store/simulation/useProductStore';
import { useSaveVersion } from '../../../store/builder/store';
import useModuleStore from '../../../store/useModuleStore';
import CompareLayOut from '../../ui/compareVersion/CompareLayOut';
import ComparisonResult from '../../ui/compareVersion/ComparisonResult';
import { useComparisonProduct } from '../../../store/simulation/useSimulationStore';
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
function ComparisonScene() {
const { isPlaying } = usePlayButtonStore();
const { products } = useProductStore();
const { isVersionSaved } = useSaveVersion();
const { activeModule } = useModuleStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
const handleSelectLayout = (option: string) => {
const product = products.find((product) => product.productName === option);
if (product) {
setComparisonProduct(product.productId, product.productName);
}
};
return (
<>
{isVersionSaved && activeModule === "simulation" && selectedProduct && (
<>
{comparisonProduct && !isPlaying &&
<div className="initial-selectLayout-wrapper">
<RegularDropDown
header={selectedProduct.productName}
options={products.map((l) => l.productName)} // Pass layout names as options
onSelect={handleSelectLayout}
search={false}
/>
</div>
}
<CompareLayOut />
{false && <ComparisonResult />}
</>
)}
</>
)
}
export default ComparisonScene;

View File

@ -0,0 +1,12 @@
import { ProductProvider } from '../../../modules/simulation/products/productContext'
import ComparisonScene from './ComparisonScene';
function ComparisonSceneProvider() {
return (
<ProductProvider>
<ComparisonScene />
</ProductProvider>
)
}
export default ComparisonSceneProvider

View File

@ -0,0 +1,113 @@
import React from 'react'
import { useLoadingProgress, useSaveVersion, useSocketStore, useWidgetSubOption } from '../../../store/builder/store';
import useModuleStore, { useThreeDStore } from '../../../store/useModuleStore';
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
import { useSelectedZoneStore } from '../../../store/visualization/useZoneStore';
import { useFloatingWidget } from '../../../store/visualization/useDroppedObjectsStore';
import { useSelectedUserStore } from '../../../store/collaboration/useCollabStore';
import KeyPressListener from '../../../utils/shortcutkeys/handleShortcutKeys';
import LoadingPage from '../../templates/LoadingPage';
import ModuleToggle from '../../ui/ModuleToggle';
import SideBarLeft from '../sidebarLeft/SideBarLeft';
import SideBarRight from '../sidebarRight/SideBarRight';
import RealTimeVisulization from '../../../modules/visualization/RealTimeVisulization';
import MarketPlace from '../../../modules/market/MarketPlace';
import Tools from '../../ui/Tools';
import SimulationPlayer from '../../ui/simulation/simulationPlayer';
import ControlsPlayer from '../controls/ControlsPlayer';
import SelectFloorPlan from '../../temporary/SelectFloorPlan';
import { createHandleDrop } from '../../../modules/visualization/functions/handleUiDrop';
import Scene from '../../../modules/scene/scene';
import { useMainProduct } from '../../../store/simulation/useSimulationStore';
import { useProductContext } from '../../../modules/simulation/products/productContext';
import { useProductStore } from '../../../store/simulation/useProductStore';
import RegularDropDown from '../../ui/inputs/RegularDropDown';
function MainScene() {
const { products } = useProductStore();
const { setMainProduct } = useMainProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { isVersionSaved } = useSaveVersion();
const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore();
const { loadingProgress } = useLoadingProgress();
const { toggleThreeD } = useThreeDStore();
const { isPlaying } = usePlayButtonStore();
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
const { selectedZone } = useSelectedZoneStore();
const { setFloatingWidget } = useFloatingWidget();
const handleSelectLayout = (option: string) => {
const product = products.find((product) => product.productName === option);
if (product) {
setMainProduct(product.productId, product.productName);
}
};
return (
<>
{!selectedUser && (
<>
<KeyPressListener />
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{!isPlaying && (
<>
{toggleThreeD && <ModuleToggle />}
<SideBarLeft />
<SideBarRight />
</>
)}
<RealTimeVisulization />
{activeModule === "market" && <MarketPlace />}
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
<Tools />
)}
{isPlaying && activeModule === "simulation" && <SimulationPlayer />}
{isPlaying && activeModule !== "simulation" && <ControlsPlayer />}
{/* remove this later */}
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
</>
)}
<div
className="scene-container"
id="work-space-three-d-canvas"
style={{
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
role="application"
onDrop={(event) =>
createHandleDrop({
widgetSubOption,
visualizationSocket,
selectedZone,
setFloatingWidget,
event,
})
}
onDragOver={(event) => event.preventDefault()}
>
<Scene layout="Main Layout" />
</div>
{selectedProduct && isVersionSaved && !isPlaying && (
<div className="selectLayout-wrapper">
<RegularDropDown
header={selectedProduct.productName}
options={products.map((l) => l.productName)} // Pass layout names as options
onSelect={handleSelectLayout}
search={false}
/>
</div>
)}
</>
)
}
export default MainScene

View File

@ -0,0 +1,12 @@
import { ProductProvider } from '../../../modules/simulation/products/productContext'
import MainScene from './MainScene'
function MainSceneProvider() {
return (
<ProductProvider>
<MainScene />
</ProductProvider>
)
}
export default MainSceneProvider

View File

@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
import {
useSelectedEventData,
useSelectedEventSphere,
useSelectedProduct,
} from "../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import ConveyorMechanics from "./mechanics/conveyorMechanics";
@ -13,11 +12,13 @@ import StorageMechanics from "./mechanics/storageMechanics";
import { AddIcon } from "../../../../icons/ExportCommonIcons";
import { handleAddEventToProduct } from "../../../../../modules/simulation/events/points/functions/handleAddEventToProduct";
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
import { useProductContext } from "../../../../../modules/simulation/products/productContext";
const EventProperties: React.FC = () => {
const { selectedEventData } = useSelectedEventData();
const { getEventByModelUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(
null
);

View File

@ -8,10 +8,10 @@ import RenameInput from "../../../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../../../functions/handleResizePannel";
import {
useSelectedAction,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
interface ActionsListProps {
selectedPointData: any;
@ -33,7 +33,8 @@ const ActionsList: React.FC<ActionsListProps> = ({
// store
const { renameAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { selectedAction, setSelectedAction } = useSelectedAction();
const handleRenameAction = (newName: string) => {
@ -87,11 +88,10 @@ const ActionsList: React.FC<ActionsListProps> = ({
selectedPointData?.actions?.map((action: any) => (
<div
key={action.actionUuid}
className={`list-item ${
selectedAction.actionId === action.actionUuid
className={`list-item ${selectedAction.actionId === action.actionUuid
? "active"
: ""
}`}
}`}
>
<button
id="action-button"

View File

@ -8,17 +8,19 @@ import SwapAction from "../actions/SwapAction";
import SpawnAction from "../actions/SpawnAction";
import DefaultAction from "../actions/DefaultAction";
import Trigger from "../trigger/Trigger";
import { useSelectedAction, useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
function ConveyorMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default");
const [selectedPointData, setSelectedPointData] = useState<ConveyorPointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const email = localStorage.getItem('email')

View File

@ -2,18 +2,20 @@ import { useEffect, useState } from "react";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger";
import { useSelectedAction, useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import ProcessAction from "../actions/ProcessAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
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();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const email = localStorage.getItem('email')

View File

@ -6,13 +6,13 @@ import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger";
import {
useSelectedEventData,
useSelectedProduct,
useSelectedAction,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
function RoboticArmMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">(
@ -30,7 +30,8 @@ function RoboticArmMechanics() {
addAction,
removeAction,
} = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { selectedAction, setSelectedAction, clearSelectedAction } =
useSelectedAction();
@ -260,7 +261,7 @@ function RoboticArmMechanics() {
defaultValue={"0.5"}
max={10}
activeOption="m/s"
onClick={() => {}}
onClick={() => { }}
onChange={handleSpeedChange}
/>
</div>
@ -286,7 +287,7 @@ function RoboticArmMechanics() {
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={() => {}}
onSelect={() => { }}
disabled={true}
/>
<PickAndPlaceAction clearPoints={handleClearPoints} />

View File

@ -6,9 +6,10 @@ import StorageAction from "../actions/StorageAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import { useSelectedAction, useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
import * as THREE from 'three';
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
function StorageMechanics() {
const { storageUnitStore } = useSceneContext();
@ -16,7 +17,8 @@ function StorageMechanics() {
const [selectedPointData, setSelectedPointData] = useState<StoragePointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const { setCurrentMaterials, clearCurrentMaterials, updateCurrentLoad, getStorageUnitById } = storageUnitStore();

View File

@ -7,13 +7,13 @@ import {
useSelectedAction,
useSelectedEventData,
useSelectedEventSphere,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import TravelAction from "../actions/TravelAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
function VehicleMechanics() {
const { vehicleStore } = useSceneContext();
@ -21,7 +21,8 @@ function VehicleMechanics() {
const [selectedPointData, setSelectedPointData] = useState<VehiclePointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const { getVehicleById } = vehicleStore();

View File

@ -11,9 +11,9 @@ import { handleResize } from "../../../../../../functions/handleResizePannel";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import {
useSelectedAction,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
type TriggerProps = {
selectedPointData?: PointsScheme | undefined;
@ -22,7 +22,8 @@ type TriggerProps = {
const Trigger = ({ selectedPointData, type }: TriggerProps) => {
const [currentAction, setCurrentAction] = useState<string | undefined>();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const {
getActionByUuid,
getEventByModelUuid,
@ -60,10 +61,10 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
) {
actionUuid = (
selectedPointData as
| ConveyorPointSchema
| VehiclePointSchema
| MachinePointSchema
| StoragePointSchema
| ConveyorPointSchema
| VehiclePointSchema
| MachinePointSchema
| StoragePointSchema
).action?.actionUuid;
} else if (
type === "RoboticArm" &&
@ -153,10 +154,10 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
return [
(
model as
| VehicleEventSchema
| RoboticArmEventSchema
| MachineEventSchema
| StorageEventSchema
| VehicleEventSchema
| RoboticArmEventSchema
| MachineEventSchema
| StorageEventSchema
).point,
];
}
@ -416,11 +417,10 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
{triggers.map((trigger) => (
<div
key={trigger.triggerUuid}
className={`list-item ${
selectedTrigger?.triggerUuid === trigger.triggerUuid
className={`list-item ${selectedTrigger?.triggerUuid === trigger.triggerUuid
? "active"
: ""
}`}
}`}
onClick={() => setSelectedTrigger(trigger)}
>
<button id="trigger" className="value">

View File

@ -9,7 +9,6 @@ import RenameInput from "../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../functions/handleResizePannel";
import {
useSelectedAsset,
useSelectedProduct,
} from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { generateUUID } from "three/src/math/MathUtils";
@ -29,6 +28,7 @@ import {
} from "../../../../store/builder/store";
import CompareLayOut from "../../../ui/compareVersion/CompareLayOut";
import { useToggleStore } from "../../../../store/useUIToggleStore";
import { useProductContext } from "../../../../modules/simulation/products/productContext";
interface Event {
modelName: string;
@ -58,7 +58,8 @@ const Simulations: React.FC = () => {
removeEvent,
getProductById,
} = useProductStore();
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct, setSelectedProduct } = selectedProductStore();
const { getEventByModelUuid } = useEventsStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const email = localStorage.getItem("email");
@ -180,8 +181,8 @@ const Simulations: React.FC = () => {
<div
key={product.productId}
className={`list-item ${selectedProduct.productId === product.productId
? "active"
: ""
? "active"
: ""
}`}
>
{/* eslint-disable-next-line */}

View File

@ -4,27 +4,20 @@ import {
LayoutIcon,
ResizerIcon,
} from "../../icons/SimulationIcons";
import { useSaveVersion } from "../../../store/builder/store";
import { useLoadingProgress, useSaveVersion } from "../../../store/builder/store";
import Search from "../inputs/Search";
import OuterClick from "../../../utils/outerClick";
import RegularDropDown from "../inputs/RegularDropDown";
import { useProductStore } from "../../../store/simulation/useProductStore";
import Scene from "../../../modules/scene/scene";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
interface Layout {
id: number;
name: string;
}
interface CompareLayoutProps {
dummyLayouts: Layout[];
}
const CompareLayOut: React.FC<CompareLayoutProps> = ({ dummyLayouts }) => {
const CompareLayOut = () => {
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
const { products } = useProductStore();
const { setLoadingProgress } = useLoadingProgress();
const [width, setWidth] = useState("50vw");
const [isResizing, setIsResizing] = useState(false);
const [showLayoutDropdown, setShowLayoutDropdown] = useState(false);
const [selectedLayout, setSelectedLayout] = useState<string | null>(null); // Track selected layout
const wrapperRef = useRef<HTMLDivElement>(null);
const startWidthRef = useRef<number>(0);
const startXRef = useRef<number>(0);
@ -111,8 +104,11 @@ const CompareLayOut: React.FC<CompareLayoutProps> = ({ dummyLayouts }) => {
}, [isResizing]);
const handleSelectLayout = (option: string) => {
setSelectedLayout(option); // Set selected layout
console.log("Selected layout:", option);
const product = products.find((product) => product.productName === option);
if (product) {
setComparisonProduct(product.productId, product.productName);
setLoadingProgress(1);
}
};
return (
@ -130,16 +126,16 @@ const CompareLayOut: React.FC<CompareLayoutProps> = ({ dummyLayouts }) => {
<ResizerIcon />
</button>
<div className="chooseLayout-container">
{selectedLayout && (
{comparisonProduct && (
<div className="compare-layout-canvas-container">
<Suspense fallback={null}>
<Scene />
<Scene layout="Comparison Layout" />
</Suspense>
</div>
)}
{width !== "0px" &&
!selectedLayout && ( // Show only if no layout selected
!comparisonProduct && ( // Show only if no layout selected
<div className="chooseLayout-wrapper">
<div className="icon">
<CompareLayoutIcon />
@ -177,16 +173,6 @@ const CompareLayOut: React.FC<CompareLayoutProps> = ({ dummyLayouts }) => {
)}
{/* Always show after layout is selected */}
{width !== "0px" && selectedLayout && (
<div className="selectLayout-wrapper">
<RegularDropDown
header={selectedLayout}
options={products.map((l) => l.productName)} // Pass layout names as options
onSelect={handleSelectLayout}
search={false}
/>
</div>
)}
</div>
</div>
);

View File

@ -12,6 +12,7 @@ import useModuleStore from "../../../store/useModuleStore";
import { useThree } from "@react-three/fiber";
import { CameraControls } from "@react-three/drei";
import addAssetModel from "./functions/addAssetModel";
import { useSceneContext } from "../../scene/sceneContext";
const gltfLoaderWorker = new Worker(
new URL(
@ -20,8 +21,9 @@ const gltfLoaderWorker = new Worker(
)
);
function AssetsGroup({ floorGroup, plane }: { floorGroup: RefGroup, plane: RefMesh }) {
function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, readonly plane: RefMesh }) {
const { activeModule } = useModuleStore();
const { layout } = useSceneContext();
const { socket } = useSocketStore();
const { controls, gl, pointer, camera, raycaster } = useThree();
const { setLoadingProgress } = useLoadingProgress();

View File

@ -12,7 +12,8 @@ import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import useModuleStore, { useSubModuleStore } from '../../../../../store/useModuleStore';
import { useLeftData, useTopData } from '../../../../../store/visualization/useZone3DWidgetStore';
import { useSelectedAsset, useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useSelectedAsset } from '../../../../../store/simulation/useSimulationStore';
import { useProductContext } from '../../../../simulation/products/productContext';
function Model({ asset }: { readonly asset: Asset }) {
const { camera, controls, gl } = useThree();
@ -24,7 +25,8 @@ function Model({ asset }: { readonly asset: Asset }) {
const { setLeft } = useLeftData();
const { getIsEventInProduct } = useProductStore();
const { getEventByModelUuid } = useEventsStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
const { socket } = useSocketStore();
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
@ -250,10 +252,10 @@ function Model({ asset }: { readonly asset: Asset }) {
userData={asset}
onDoubleClick={(e) => {
e.stopPropagation();
handleDblClick(asset);
}}
onClick={(e) => {
e.stopPropagation();
handleDblClick(asset);
handleClick(asset);
}}
onPointerOver={(e) => {

View File

@ -11,11 +11,11 @@ import * as Types from "../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { snapControls } from "../../../../utils/handleSnap";
import DistanceFindingControls from "./distanceFindingControls";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { useProductContext } from "../../../simulation/products/productContext";
function MoveControls({
movedObjects,
@ -34,7 +34,8 @@ function MoveControls({
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
const email = localStorage.getItem("email");

View File

@ -6,9 +6,9 @@ import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../st
import * as Types from "../../../../types/world/worldTypes";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { useProductContext } from "../../../simulation/products/productContext";
function RotateControls({
rotatedObjects,
@ -27,7 +27,8 @@ function RotateControls({
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
const email = localStorage.getItem('email')
@ -208,7 +209,7 @@ function RotateControls({
if (obj.userData.eventData) {
const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modelUuid);
const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid);
const productData = useProductStore.getState().getEventByModelUuid(selectedProductStore.getState().selectedProduct.productId, obj.userData.modelUuid);
if (eventData) {
useEventsStore.getState().updateEvent(obj.userData.modelUuid, {
@ -217,7 +218,7 @@ function RotateControls({
})
}
if (productData) {
const event = useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
const event = useProductStore.getState().updateEvent(selectedProductStore.getState().selectedProduct.productId, obj.userData.modelUuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})

View File

@ -8,10 +8,10 @@ import { useEffect, useState } from "react";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { useProductContext } from "../../../simulation/products/productContext";
export default function TransformControl() {
const state = useThree();
@ -21,7 +21,8 @@ export default function TransformControl() {
const { setObjectRotation } = useObjectRotation();
const { activeTool } = useActiveTool();
const { socket } = useSocketStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { updateAsset, getAssetById } = useAssetsStore();
const email = localStorage.getItem('email')

View File

@ -1,5 +1,6 @@
import { useMemo } from "react";
import { Canvas } from "@react-three/fiber";
import { Color } from "three";
import { KeyboardControls } from "@react-three/drei";
import { SceneProvider } from "./sceneContext";
@ -9,7 +10,7 @@ import Setup from "./setup/setup";
import Simulation from "../simulation/simulation";
import Collaboration from "../collaboration/collaboration";
export default function Scene() {
export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Comparison Layout' }) {
const map = useMemo(() => [
{ name: "forward", keys: ["ArrowUp", "w", "W"] },
{ name: "backward", keys: ["ArrowDown", "s", "S"] },
@ -18,7 +19,7 @@ export default function Scene() {
], []);
return (
<SceneProvider>
<SceneProvider layout={layout}>
<KeyboardControls map={map}>
<Canvas
eventPrefix="client"
@ -26,6 +27,9 @@ export default function Scene() {
onContextMenu={(e) => {
e.preventDefault();
}}
onCreated={(e) => {
e.scene.background = new Color(0x19191d);
}}
>
<Setup />
<Collaboration />

View File

@ -13,11 +13,18 @@ type SceneContextValue = {
conveyorStore: ConveyorStoreType;
vehicleStore: VehicleStoreType;
storageUnitStore: StorageUnitStoreType;
layout: 'Main Layout' | 'Comparison Layout';
};
const SceneContext = createContext<SceneContextValue | null>(null);
export function SceneProvider({ children }: { readonly children: React.ReactNode }) {
export function SceneProvider({
children,
layout
}: {
readonly children: React.ReactNode;
readonly layout: 'Main Layout' | 'Comparison Layout';
}) {
const materialStore = useMemo(() => createMaterialStore(), []);
const armBotStore = useMemo(() => createArmBotStore(), []);
const machineStore = useMemo(() => createMachineStore(), []);
@ -32,9 +39,10 @@ export function SceneProvider({ children }: { readonly children: React.ReactNode
machineStore,
conveyorStore,
vehicleStore,
storageUnitStore
storageUnitStore,
layout
}
), [materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore]);
), [materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout]);
return (
<SceneContext.Provider value={contextValue}>

View File

@ -2,9 +2,9 @@ import { useCallback, useEffect, useState } from "react";
import * as THREE from 'three';
import { useFrame } from "@react-three/fiber";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { usePlayButtonStore, useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from "../../../../../store/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
interface SpawnInstance {
lastSpawnTime: number | null;
@ -30,7 +30,8 @@ export function useSpawnHandler() {
const { isPaused } = usePauseButtonStore();
const { speed } = useAnimationPlaySpeed();
const { isReset } = useResetButtonStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const [activeSpawns, setActiveSpawns] = useState<Map<string, SpawnInstance>>(new Map());

View File

@ -1,14 +1,15 @@
import { useCallback } from "react";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useProcessHandler() {
const { materialStore, machineStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { getMaterialById, setMaterial } = materialStore();
const { addCurrentAction } = machineStore();
const { getModelUuidByActionUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const processLogStatus = (materialUuid: string, status: string) => {
echo.log(`${materialUuid}, ${status}`);

View File

@ -1,14 +1,15 @@
import { useCallback } from "react";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function usePickAndPlaceHandler() {
const { materialStore, armBotStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { getMaterialById } = materialStore();
const { addCurrentAction } = armBotStore();
const { getModelUuidByActionUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const pickAndPlaceLogStatus = (materialUuid: string, status: string) => {
echo.warn(`${materialUuid}, ${status}`);

View File

@ -1,17 +1,18 @@
import { useCallback, useState, useEffect, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore, useAnimationPlaySpeed } from "../../../../../store/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useRetrieveHandler() {
const { materialStore, armBotStore, vehicleStore, storageUnitStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { addMaterial } = materialStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid } = useProductStore();
const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = storageUnitStore();
const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = vehicleStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { getArmBotById, addCurrentAction } = armBotStore();
const { isPlaying } = usePlayButtonStore();
const { speed } = useAnimationPlaySpeed();

View File

@ -1,14 +1,15 @@
import { useCallback } from "react";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useStoreHandler() {
const { materialStore, storageUnitStore } = useSceneContext();
const { getMaterialById, removeMaterial, setEndTime } = materialStore();
const { addCurrentMaterial, updateCurrentLoad } = storageUnitStore();
const { getModelUuidByActionUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const storeLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);

View File

@ -1,13 +1,14 @@
import { useCallback } from "react";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useTravelHandler() {
const { materialStore, vehicleStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { getMaterialById } = materialStore();
const { getModelUuidByActionUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { incrementVehicleLoad, addCurrentMaterial } = vehicleStore();
const travelLogStatus = (materialUuid: string, status: string) => {

View File

@ -1,12 +1,13 @@
import React, { useEffect, useState } from 'react'
import { useInputValues, useProductionCapacityData, useROISummaryData } from '../../../../store/builder/store';
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
import { useProductContext } from '../../products/productContext';
export default function ROIData() {
const { selectedProductStore } = useProductContext();
const { inputValues } = useInputValues();
const { productionCapacityData } = useProductionCapacityData()
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { isPlaying } = usePlayButtonStore();
const { setRoiSummaryData } = useROISummaryData();
useEffect(() => {

View File

@ -1,14 +1,15 @@
import { useEffect } from 'react';
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
import { useProductStore } from '../../../../store/simulation/useProductStore';
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
import { useMachineCount, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
export default function ThroughPutData() {
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore } = useSceneContext();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { products, getProductById } = useProductStore();
const { armBots } = armBotStore();
const { vehicles } = vehicleStore();

View File

@ -1,13 +1,14 @@
import { useEffect } from 'react'
import { useResetButtonStore } from '../../../../../store/usePlayButtonStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
// import { findConveyorSubsequence } from '../../../simulator/functions/getConveyorSequencesInProduct';
function ConveyorInstance({ conveyor }: { conveyor: ConveyorStatus }) {
function ConveyorInstance({ conveyor }: { readonly conveyor: ConveyorStatus }) {
const { getProductById } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { materialStore, conveyorStore } = useSceneContext();
const { getMaterialsByCurrentModelUuid, materials } = materialStore();
const { isReset } = useResetButtonStore();

View File

@ -2,7 +2,6 @@ import { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore";
import { TransformControls } from "@react-three/drei";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
@ -10,13 +9,15 @@ import { useSelectedEventSphere, useSelectedEventData, } from "../../../../../st
import { useThree } from "@react-three/fiber";
import { usePlayButtonStore } from "../../../../../store/usePlayButtonStore";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../products/productContext";
function PointsCreator() {
const { gl, raycaster, scene, pointer, camera } = useThree();
const { subModule } = useSubModuleStore();
const { selectedProductStore } = useProductContext();
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
const { getEventByModelUuid: getEventByModelUuidFromProduct, updatePoint: updatePointFromProduct, getEventByModelUuid: getEventByModelUuidFromProduct2, getPointByUuid: getPointByUuidFromProduct } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { activeModule } = useModuleStore();
const transformRef = useRef<any>(null);
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);

View File

@ -5,13 +5,13 @@ import { useSubModuleStore } from "../../../../store/useModuleStore";
import { useSelectedAction, useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { handleAddEventToProduct } from "../points/functions/handleAddEventToProduct";
import { QuadraticBezierLine } from "@react-three/drei";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { useDeleteTool } from "../../../../store/builder/store";
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
import { ArrowOnQuadraticBezier, Arrows } from "../arrows/arrows";
import { useProductContext } from "../../products/productContext";
interface ConnectionLine {
id: string;
@ -23,9 +23,10 @@ interface ConnectionLine {
function TriggerConnector() {
const { gl, raycaster, scene, pointer, camera } = useThree();
const { subModule } = useSubModuleStore();
const { selectedProductStore } = useProductContext();
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, removeTrigger, addEvent, getEventByModelUuid, getPointUuidByActionUuid, getProductById } = useProductStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
const groupRefs = useRef<Record<string, any>>({});
const [helperlineColor, setHelperLineColor] = useState<string>("red");

View File

@ -2,9 +2,9 @@ import { useEffect, useRef, useState } from 'react'
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import MachineAnimator from '../animator/machineAnimator';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
function MachineInstance({ machineDetail }: { readonly machineDetail: MachineStatus }) {
const [currentPhase, setCurrentPhase] = useState<string>('idle');
@ -17,8 +17,9 @@ function MachineInstance({ machineDetail }: { readonly machineDetail: MachineSta
const isPausedRef = useRef<boolean>(false);
const { isPlaying } = usePlayButtonStore();
const { machineStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { machines, setMachineState, setMachineActive, incrementIdleTime, incrementActiveTime, resetTime } = machineStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid } = useProductStore();
const { triggerPointActions } = useTriggerHandler();
const { speed } = useAnimationPlaySpeed();

View File

@ -1,18 +1,19 @@
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useMemo, useRef } from 'react'
import * as THREE from 'three';
import MaterialAnimator from '../animator/materialAnimator';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { MaterialModel } from '../material/materialModel';
import { useThree } from '@react-three/fiber';
import { useAnimationPlaySpeed } from '../../../../../store/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useProductContext } from '../../../products/productContext';
function MaterialInstance({ material }: { material: MaterialSchema }) {
function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
const matRef: any = useRef();
const { scene } = useThree();
const { selectedProductStore } = useProductContext();
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid, getActionByUuid, getTriggerByUuid, getActionByPointUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { speed } = useAnimationPlaySpeed();
const { triggerPointActions } = useTriggerHandler();

View File

@ -0,0 +1,37 @@
import { createContext, useContext, useMemo } from 'react';
import { createSelectedProductStore, SelectedProductType } from '../../../store/simulation/useSimulationStore';
type ProductContextValue = {
selectedProductStore: SelectedProductType,
};
const ProductContext = createContext<ProductContextValue | null>(null);
export function ProductProvider({
children,
}: {
readonly children: React.ReactNode;
}) {
const selectedProductStore = useMemo(() => createSelectedProductStore(), []);
const contextValue = useMemo(() => (
{
selectedProductStore
}
), [selectedProductStore]);
return (
<ProductContext.Provider value={contextValue}>
{children}
</ProductContext.Provider>
);
}
// Base hook to get the context
export function useProductContext() {
const context = useContext(ProductContext);
if (!context) {
throw new Error('useProductContext must be used within a ProductProvider');
}
return context;
}

View File

@ -1,16 +1,18 @@
import * as THREE from 'three';
import { useEffect } from 'react';
import { useProductStore } from '../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
import { upsertProductOrEventApi } from '../../../services/simulation/products/UpsertProductOrEventApi';
import { getAllProductsApi } from '../../../services/simulation/products/getallProductsApi';
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
import { useSceneContext } from '../../scene/sceneContext';
import { useProductContext } from './productContext';
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
function Products() {
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore } = useSceneContext();
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout } = useSceneContext();
const { products, getProductById, addProduct, setProducts } = useProductStore();
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct, setSelectedProduct } = selectedProductStore();
const { addVehicle, clearvehicles } = vehicleStore();
const { addArmBot, clearArmBots } = armBotStore();
const { addMachine, clearMachines } = machineStore();
@ -18,6 +20,24 @@ function Products() {
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
const { isReset } = useResetButtonStore();
const { isPlaying } = usePlayButtonStore();
const { mainProduct } = useMainProduct();
const { comparisonProduct } = useComparisonProduct();
useEffect(() => {
if (layout === 'Main Layout' && mainProduct) {
setSelectedProduct(mainProduct.productId, mainProduct.productName);
}
}, [mainProduct])
useEffect(() => {
if (layout === 'Comparison Layout' && comparisonProduct) {
setSelectedProduct(comparisonProduct.productId, comparisonProduct.productName);
}
}, [comparisonProduct])
useEffect(() => {
console.log(selectedProduct);
}, [selectedProduct])
useEffect(() => {
const email = localStorage.getItem('email')
@ -28,10 +48,14 @@ function Products() {
const name = 'Product 1';
addProduct(name, id);
upsertProductOrEventApi({ productName: name, productId: id, organization: organization })
setSelectedProduct(id, name);
if (layout === 'Main Layout') {
setSelectedProduct(id, name);
}
} else {
setProducts(data);
setSelectedProduct(data[0].productId, data[0].productName);
if (layout === 'Main Layout') {
setSelectedProduct(data[0].productId, data[0].productName);
}
}
})
}, [])

View File

@ -7,9 +7,9 @@ import MaterialAnimator from '../animator/materialAnimator';
import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_1.glb";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
@ -25,12 +25,13 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
const isSpeedRef = useRef<any>(null);
let startTime: number;
const { selectedProductStore } = useProductContext();
const { materialStore, armBotStore, vehicleStore, storageUnitStore } = useSceneContext();
const { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = armBotStore();
const { decrementVehicleLoad, removeLastMaterial } = vehicleStore();
const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore();
const { getMaterialById, setIsVisible, setIsPaused } = materialStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, getEventByActionUuid, getEventByModelUuid } = useProductStore();
const { triggerPointActions } = useTriggerHandler();
const { isPlaying } = usePlayButtonStore();

View File

@ -3,12 +3,13 @@ import { useProductStore } from '../../../store/simulation/useProductStore';
import { useActionHandler } from '../actions/useActionHandler';
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
import { determineExecutionOrder } from './functions/determineExecutionOrder';
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
import { useProductContext } from '../products/productContext';
function Simulator() {
const { selectedProductStore } = useProductContext();
const { products, getProductById } = useProductStore();
const { handleAction } = useActionHandler();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { isPlaying } = usePlayButtonStore();
const { isReset } = useResetButtonStore();

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { useSelectedAction, useSelectedEventSphere, useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
import { useSelectedAction, useSelectedEventSphere } from '../../../../store/simulation/useSimulationStore';
import { useGLTF } from '@react-three/drei';
import { useThree } from '@react-three/fiber';
import { useProductStore } from '../../../../store/simulation/useProductStore';
@ -11,6 +11,7 @@ import armPick from "../../../../assets/gltf-glb/ui/arm_ui_pick.glb";
import armDrop from "../../../../assets/gltf-glb/ui/arm_ui_drop.glb";
import { upsertProductOrEventApi } from '../../../../services/simulation/products/UpsertProductOrEventApi';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
type Positions = {
pick: [number, number, number];
@ -21,7 +22,8 @@ type Positions = {
const ArmBotUI = () => {
const { getEventByModelUuid, updateAction, getActionByUuid } = useProductStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { scene } = useThree();
const { selectedAction } = useSelectedAction();
const { armBotStore } = useSceneContext();

View File

@ -4,21 +4,19 @@ import { ThreeEvent, useThree } from "@react-three/fiber";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import {
useSelectedEventData,
useSelectedProduct,
} from "../../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../products/productContext";
type OnUpdateCallback = (object: THREE.Object3D) => void;
export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
const { getEventByModelUuid, updateAction, getActionByUuid } =
useProductStore();
const { getEventByModelUuid } = useProductStore();
const { selectedEventData } = useSelectedEventData();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { camera, gl, controls } = useThree();
const activeObjRef = useRef<THREE.Object3D | null>(null);
const planeRef = useRef<THREE.Plane>(
new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
);
const planeRef = useRef<THREE.Plane>(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
const offsetRef = useRef<THREE.Vector3>(new THREE.Vector3());
const initialPositionRef = useRef<THREE.Vector3>(new THREE.Vector3());

View File

@ -5,7 +5,6 @@ import { useFrame, useThree } from "@react-three/fiber";
import {
useSelectedEventSphere,
useIsDragging,
useSelectedProduct,
useIsRotating,
} from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
@ -15,6 +14,7 @@ import { DoubleSide, Group, Plane, Vector3 } from "three";
import startPoint from "../../../../assets/gltf-glb/ui/arrow_green.glb";
import startEnd from "../../../../assets/gltf-glb/ui/arrow_red.glb";
import { useSceneContext } from "../../../scene/sceneContext";
import { useProductContext } from "../../products/productContext";
const VehicleUI = () => {
const { scene: startScene } = useGLTF(startPoint) as any;
@ -23,8 +23,9 @@ const VehicleUI = () => {
const endMarker = useRef<Group>(null);
const prevMousePos = useRef({ x: 0, y: 0 });
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedProduct } = useSelectedProduct();
const { vehicleStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { vehicleStore } = useSceneContext();
const { selectedProduct } = selectedProductStore();
const { vehicles, getVehicleById } = vehicleStore();
const { updateEvent } = useProductStore();
const [startPosition, setStartPosition] = useState<[number, number, number]>([

View File

@ -1,17 +1,18 @@
import { useCallback } from 'react';
import { useActionHandler } from '../../actions/useActionHandler';
import { useProductStore } from '../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
import { useArmBotEventManager } from '../../roboticArm/eventManager/useArmBotEventManager';
import { useConveyorEventManager } from '../../conveyor/eventManager/useConveyorEventManager';
import { useVehicleEventManager } from '../../vehicle/eventManager/useVehicleEventManager';
import { useMachineEventManager } from '../../machine/eventManager/useMachineEventManager';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
export function useTriggerHandler() {
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { handleAction } = useActionHandler();
const { selectedProduct } = useSelectedProduct();
const { selectedProduct } = selectedProductStore();
const { getEventByTriggerUuid, getEventByModelUuid, getActionByUuid, getModelUuidByActionUuid } = useProductStore();
const { getArmBotById } = armBotStore();
const { getConveyorById } = conveyorStore();

View File

@ -5,10 +5,10 @@ import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import MaterialAnimator from '../animator/materialAnimator';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh();
@ -20,7 +20,8 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { getConveyorById } = conveyorStore();
const { triggerPointActions } = useTriggerHandler();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = vehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed');

View File

@ -1,61 +1,39 @@
import React, { useEffect, useState } from "react";
import ModuleToggle from "../components/ui/ModuleToggle";
import SideBarLeft from "../components/layout/sidebarLeft/SideBarLeft";
import SideBarRight from "../components/layout/sidebarRight/SideBarRight";
import useModuleStore, { useThreeDStore } from "../store/useModuleStore";
import RealTimeVisulization from "../modules/visualization/RealTimeVisulization";
import Tools from "../components/ui/Tools";
import React, { useEffect } from "react";
import useModuleStore from "../store/useModuleStore";
import {
useSocketStore,
useOrganization,
useUserName,
useWallItems,
useZones,
useLoadingProgress,
useWidgetSubOption,
useSaveVersion,
} from "../store/builder/store";
import { useNavigate } from "react-router-dom";
import { usePlayButtonStore } from "../store/usePlayButtonStore";
import MarketPlace from "../modules/market/MarketPlace";
import LoadingPage from "../components/templates/LoadingPage";
import KeyPressListener from "../utils/shortcutkeys/handleShortcutKeys";
import { useSelectedUserStore } from "../store/collaboration/useCollabStore";
import FollowPerson from "../components/templates/FollowPerson";
import Scene from "../modules/scene/scene";
import { createHandleDrop } from "../modules/visualization/functions/handleUiDrop";
import { useSelectedZoneStore } from "../store/visualization/useZoneStore";
import { useFloatingWidget } from "../store/visualization/useDroppedObjectsStore";
import { useLogger } from "../components/ui/log/LoggerContext";
import RenderOverlay from "../components/templates/Overlay";
import LogList from "../components/ui/log/LogList";
import Footer from "../components/footer/Footer";
import SelectFloorPlan from "../components/temporary/SelectFloorPlan";
import ControlsPlayer from "../components/layout/controls/ControlsPlayer";
import CompareLayOut from "../components/ui/compareVersion/CompareLayOut";
import { useToggleStore } from "../store/useUIToggleStore";
import RegularDropDown from "../components/ui/inputs/RegularDropDown";
import VersionSaved from "../components/layout/sidebarRight/versionHisory/VersionSaved";
import SimulationPlayer from "../components/ui/simulation/simulationPlayer";
import { useAssetsStore } from "../store/builder/useAssetStore";
import { useProductStore } from "../store/simulation/useProductStore";
import ThreadChat from "../components/ui/collaboration/ThreadChat";
import ComparisonResult from "../components/ui/compareVersion/ComparisonResult";
import ComparisonSceneProvider from "../components/layout/scenes/ComparisonSceneProvider";
import MainSceneProvider from "../components/layout/scenes/MainSceneProvider";
const Project: React.FC = () => {
let navigate = useNavigate();
const echo = useLogger();
const { setToggleUI } = useToggleStore();
const { activeModule, setActiveModule } = useModuleStore();
const { loadingProgress } = useLoadingProgress();
const { setAssets } = useAssetsStore();
const { setUserName } = useUserName();
const { setOrganization } = useOrganization();
const { setWallItems } = useWallItems();
const { setZones } = useZones();
const { isVersionSaved } = useSaveVersion();
const { products } = useProductStore();
const { selectedUser } = useSelectedUserStore();
const { isLogListVisible } = useLogger();
useEffect(() => {
if (!isVersionSaved) {
@ -85,84 +63,10 @@ const Project: React.FC = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// global store
const { toggleThreeD } = useThreeDStore();
// simulation store
const { isPlaying } = usePlayButtonStore();
// collaboration store
const { selectedUser } = useSelectedUserStore();
const { isLogListVisible } = useLogger();
// real-time visualization store
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
const { selectedZone } = useSelectedZoneStore();
const { setFloatingWidget } = useFloatingWidget();
const [selectedLayout, setSelectedLayout] = useState<string | null>(null); // Track selected layout
const dummyLayouts = [
{ id: 1, name: "Layout 1" },
{ id: 2, name: "Layout 2" },
{ id: 3, name: "Layout 3" },
{ id: 4, name: "Layout 4" },
];
const handleSelectLayout = (option: string) => {
setSelectedLayout(option); // Set selected layout
console.log("Selected layout:", option);
};
return (
<div className="project-main">
{!selectedUser && (
<>
<KeyPressListener />
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{!isPlaying && (
<>
{toggleThreeD && <ModuleToggle />}
<SideBarLeft />
<SideBarRight />
</>
)}
<RealTimeVisulization />
{activeModule === "market" && <MarketPlace />}
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
<Tools />
)}
{isPlaying && activeModule === "simulation" && <SimulationPlayer />}
{isPlaying && activeModule !== "simulation" && <ControlsPlayer />}
{/* remove this later */}
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
</>
)}
<div
className="scene-container"
id="work-space-three-d-canvas"
style={{
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
role="application"
onDrop={(event) =>
createHandleDrop({
widgetSubOption,
visualizationSocket,
selectedZone,
setFloatingWidget,
event,
})
}
onDragOver={(event) => event.preventDefault()}
>
<Scene />
</div>
<ComparisonSceneProvider />
<MainSceneProvider />
{selectedUser && <FollowPerson />}
{isLogListVisible && (
<RenderOverlay>
@ -170,20 +74,6 @@ const Project: React.FC = () => {
</RenderOverlay>
)}
{activeModule !== "market" && !selectedUser && <Footer />}
{isVersionSaved && activeModule === "simulation" && (
<>
<div className="initial-selectLayout-wrapper">
<RegularDropDown
header={selectedLayout ?? "Layout 1"}
options={products.map((l) => l.productName)} // Pass layout names as options
onSelect={handleSelectLayout}
search={false}
/>
</div>
<CompareLayOut dummyLayouts={dummyLayouts} />
{false && <ComparisonResult />}
</>
)}
<VersionSaved />
</div>
);

View File

@ -74,23 +74,27 @@ interface SelectedProductState {
clearSelectedProduct: () => void;
}
export const useSelectedProduct = create<SelectedProductState>()(
immer((set) => ({
selectedProduct: { productId: '', productName: '' },
setSelectedProduct: (productId, productName) => {
set((state) => {
state.selectedProduct.productId = productId;
state.selectedProduct.productName = productName;
});
},
clearSelectedProduct: () => {
set((state) => {
state.selectedProduct.productId = '';
state.selectedProduct.productName = '';
});
},
}))
);
export const createSelectedProductStore = () => {
return create<SelectedProductState>()(
immer((set) => ({
selectedProduct: { productId: '', productName: '' },
setSelectedProduct: (productId, productName) => {
set((state) => {
state.selectedProduct.productId = productId;
state.selectedProduct.productName = productName;
});
},
clearSelectedProduct: () => {
set((state) => {
state.selectedProduct.productId = '';
state.selectedProduct.productName = '';
});
},
}))
)
}
export type SelectedProductType = ReturnType<typeof createSelectedProductStore>;
interface SelectedActionState {
selectedAction: { actionId: string | null; actionName: string | null };
@ -147,3 +151,47 @@ export const useIsRotating = create<IsRotatingState>()(
},
}))
);
interface MainProductState {
mainProduct: { productId: string; productName: string } | null;
setMainProduct: (productId: string, productName: string) => void;
clearMainProduct: () => void;
}
export const useMainProduct = create<MainProductState>()(
immer((set) => ({
mainProduct: null,
setMainProduct: (productId: string, productName: string) => {
set((state) => {
state.mainProduct = { productId, productName };
});
},
clearMainProduct: () => {
set((state) => {
state.mainProduct = null;
});
},
}))
);
interface ComparisonProductState {
comparisonProduct: { productId: string; productName: string } | null;
setComparisonProduct: (productId: string, productName: string) => void;
clearComparisonProduct: () => void;
}
export const useComparisonProduct = create<ComparisonProductState>()(
immer((set) => ({
comparisonProduct: null,
setComparisonProduct: (productId: string, productName: string) => {
set((state) => {
state.comparisonProduct = { productId, productName };
});
},
clearComparisonProduct: () => {
set((state) => {
state.comparisonProduct = null;
});
},
}))
);

File diff suppressed because it is too large Load Diff