Refactor simulation product handling and state management

- Replaced `useComparisonProduct` with `useSimulationState` in multiple components to streamline state management.
- Updated `SyncCam` to use `comparisonScene` instead of `comparisonProduct`.
- Modified `Products` component to utilize `mainScene` and `comparisonScene` for product selection.
- Adjusted various simulation functions to accept `ProductsSchema` instead of `productsSchema`.
- Enhanced `Simulator` component to fetch simulation data using the updated state structure.
- Refined Zustand store to manage `mainScene` and `comparisonScene` states, including their respective setters and clearers.
- Updated type definitions for products to ensure consistency across the application.
- Cleaned up shortcut key handling to reflect changes in state management.
This commit is contained in:
2025-09-08 11:40:27 +05:30
parent c8e9633050
commit 80a672adf0
20 changed files with 637 additions and 640 deletions

View File

@@ -1,5 +1,5 @@
import { useCompareProductDataStore, useLoadingProgress, useIsComparing } from "../../../store/builder/store"; import { useCompareProductDataStore, useLoadingProgress, useIsComparing } from "../../../store/builder/store";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useSceneContext } from "../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../modules/scene/sceneContext";
@@ -9,12 +9,14 @@ import ComparisonResult from "../../ui/compareVersion/ComparisonResult";
import RegularDropDown from "../../ui/inputs/RegularDropDown"; import RegularDropDown from "../../ui/inputs/RegularDropDown";
import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
type AssetData = { type AssetData = {
activeTime: number; activeTime: number;
idleTime: number; idleTime: number;
type: string; type: string;
assetId: string; assetId: string;
}; };
export interface CompareProduct { export interface CompareProduct {
productUuid: string; productUuid: string;
productName: string; productName: string;
@@ -48,6 +50,7 @@ export interface CompareProduct {
efficiencyScore?: number; efficiencyScore?: number;
}; };
} }
const calculateSimulationData = (assets: AssetData[]) => { const calculateSimulationData = (assets: AssetData[]) => {
let totalActiveTime = 0; let totalActiveTime = 0;
let totalIdleTime = 0; let totalIdleTime = 0;
@@ -111,6 +114,7 @@ export const createCompareProduct = (productUuid: string, productName: string, a
productName, productName,
simulationData: calculateSimulationData(assets), simulationData: calculateSimulationData(assets),
}); });
function ComparisonScene() { function ComparisonScene() {
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { productStore, versionStore } = useSceneContext(); const { productStore, versionStore } = useSceneContext();
@@ -118,13 +122,11 @@ function ComparisonScene() {
const { products, selectedProduct } = productStore(); const { products, selectedProduct } = productStore();
const { isComparing } = useIsComparing(); const { isComparing } = useIsComparing();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { mainScene, comparisonScene, setComparisonState } = useSimulationState();
const { mainProduct } = useMainProduct();
const { loadingProgress } = useLoadingProgress(); const { loadingProgress } = useLoadingProgress();
const { projectId } = useParams(); const { projectId } = useParams();
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); const { setCompareProductsData } = useCompareProductDataStore();
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false); const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
console.log("shouldShowComparisonResult: ", shouldShowComparisonResult);
const handleSelectVersion = (option: string) => { const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option); const version = versionHistory.find((version) => version.versionName === option);
@@ -135,8 +137,14 @@ function ComparisonScene() {
const handleSelectProduct = (option: string) => { const handleSelectProduct = (option: string) => {
const product = products.find((product) => product.productName === option); const product = products.find((product) => product.productName === option);
if (product) { if (product && selectedVersion) {
setComparisonProduct(product.productUuid, product.productName); const data = {
productUuid: product.productUuid,
productName: product.productName,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setComparisonState(data);
} }
}; };
@@ -156,16 +164,15 @@ function ComparisonScene() {
useEffect(() => { useEffect(() => {
// const selectedProductData = getProductById(selectedProduct.productUuid); // const selectedProductData = getProductById(selectedProduct.productUuid);
if (mainProduct && comparisonProduct && selectedVersion) { if (mainScene && comparisonScene && selectedVersion) {
const product1 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, mainProduct.productUuid); const product1 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, mainScene.product.productUuid);
const product2 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, comparisonProduct.productUuid); const product2 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, comparisonScene.product.productUuid);
const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainProduct.productName, product1?.simulateData || []); const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainScene.product.productName, product1?.simulateData || []);
const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonProduct.productName, product2?.simulateData || []); const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonScene.product.productName, product2?.simulateData || []);
const comparedArray = [compareProduct1, compareProduct2]; const comparedArray = [compareProduct1, compareProduct2];
console.log("comparedArray: ", comparedArray);
if (product1 === undefined || product2 === undefined) { if (product1 === undefined || product2 === undefined) {
setShouldShowComparisonResult(false); setShouldShowComparisonResult(false);
@@ -176,7 +183,7 @@ function ComparisonScene() {
} else { } else {
setShouldShowComparisonResult(false); setShouldShowComparisonResult(false);
} }
}, [mainProduct, comparisonProduct, selectedVersion, projectId, setCompareProductsData]); }, [mainScene, comparisonScene, selectedVersion, projectId, setCompareProductsData]);
return ( return (
<> <>

View File

@@ -7,7 +7,7 @@ import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore"
import { useFloatingWidget } from "../../../store/visualization/useDroppedObjectsStore"; import { useFloatingWidget } from "../../../store/visualization/useDroppedObjectsStore";
import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore"; import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore";
import { createHandleDrop } from "../../../modules/visualization/functions/handleUiDrop"; import { createHandleDrop } from "../../../modules/visualization/functions/handleUiDrop";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import { useSceneContext } from "../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../modules/scene/sceneContext";
import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import useRestStates from "../../../hooks/useResetStates"; import useRestStates from "../../../hooks/useResetStates";
@@ -35,7 +35,7 @@ import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi"; import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
function MainScene() { function MainScene() {
const { setMainProduct } = useMainProduct(); const { setMainState, clearComparisonState } = useSimulationState();
const { isComparing, setIsComparing } = useIsComparing(); const { isComparing, setIsComparing } = useIsComparing();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore(); const { selectedUser } = useSelectedUserStore();
@@ -46,7 +46,6 @@ function MainScene() {
const { visualizationSocket } = useSocketStore(); const { visualizationSocket } = useSocketStore();
const { selectedZone } = useSelectedZoneStore(); const { selectedZone } = useSelectedZoneStore();
const { setFloatingWidget } = useFloatingWidget(); const { setFloatingWidget } = useFloatingWidget();
const { clearComparisonProduct } = useComparisonProduct();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore(); const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { assetStore, productStore, versionStore } = useSceneContext(); const { assetStore, productStore, versionStore } = useSceneContext();
const { products, selectedProduct } = productStore(); const { products, selectedProduct } = productStore();
@@ -62,14 +61,15 @@ function MainScene() {
return () => { return () => {
resetStates(); resetStates();
}; };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
useEffect(() => { useEffect(() => {
if (activeModule !== "simulation") { if (activeModule !== "simulation") {
clearComparisonProduct(); clearComparisonState();
setIsComparing(false); setIsComparing(false);
} }
}, [activeModule, clearComparisonProduct, setIsComparing]); }, [activeModule, clearComparisonState, setIsComparing]);
useEffect(() => { useEffect(() => {
if (!projectId) return; if (!projectId) return;
@@ -120,8 +120,14 @@ function MainScene() {
const handleSelectProduct = (option: string) => { const handleSelectProduct = (option: string) => {
const product = products.find((product) => product.productName === option); const product = products.find((product) => product.productName === option);
if (product) { if (product && selectedVersion) {
setMainProduct(product.productUuid, product.productName); const data = {
productUuid: product.productUuid,
productName: product.productName,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setMainState(data);
} }
}; };

View File

@@ -1,4 +1,5 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
interface SimulationData { interface SimulationData {
key: string; key: string;
data?: object | any; data?: object | any;
@@ -28,6 +29,7 @@ interface ProjectSimulation {
projectId: string | undefined; projectId: string | undefined;
versions: VersionSimulation[]; versions: VersionSimulation[];
} }
export const saveSimulationData = async (data: any) => { export const saveSimulationData = async (data: any) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/SimulatedUpsert`, { const response = await fetch(`${url_Backend_dwinzo}/api/V1/SimulatedUpsert`, {
@@ -59,8 +61,9 @@ export const saveSimulationData = async (data: any) => {
} }
} }
}; };
export const updateSimulateData = async (data: any) => { export const updateSimulateData = async (data: any) => {
console.log("data: update", data); // console.log("data: update", data);
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/ValidateSimulated`, { const response = await fetch(`${url_Backend_dwinzo}/api/V1/ValidateSimulated`, {
method: "POST", method: "POST",
@@ -91,18 +94,25 @@ export const updateSimulateData = async (data: any) => {
} }
} }
}; };
export const getSimulationData = async (projectId: string, versionId: string, productUuid: string) => { export const getSimulationData = async (
console.log("called"); projectId: string,
versionId: string,
productUuid: string
) => {
// console.log("called");
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/V1/SimulatedDatas/${projectId}/${versionId}?productUuid=${productUuid}`, { const response = await fetch(
method: "GET", `${url_Backend_dwinzo}/api/V1/SimulatedDatas/${projectId}/${versionId}?productUuid=${productUuid}`,
headers: { {
Authorization: "Bearer <access_token>", method: "GET",
"Content-Type": "application/json", headers: {
token: localStorage.getItem("token") || "", Authorization: "Bearer <access_token>",
refresh_token: localStorage.getItem("refreshToken") || "", "Content-Type": "application/json",
}, token: localStorage.getItem("token") || "",
}); refresh_token: localStorage.getItem("refreshToken") || "",
},
}
);
console.log("response: ", response); console.log("response: ", response);

View File

@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons"; import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
import RenameInput from "../../../ui/inputs/RenameInput"; import RenameInput from "../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../functions/handleResizePannel"; import { handleResize } from "../../../../functions/handleResizePannel";
import { useMainProduct, useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; import { useSimulationState, useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
import { generateUUID } from "three/src/math/MathUtils"; import { generateUUID } from "three/src/math/MathUtils";
import RenderOverlay from "../../../templates/Overlay"; import RenderOverlay from "../../../templates/Overlay";
import EditWidgetOption from "../../../ui/menu/EditWidgetOption"; import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
@@ -17,8 +17,7 @@ import { useCompareStore, useIsComparing, useSimulateId } from "../../../../stor
import { useToggleStore } from "../../../../store/ui/useUIToggleStore"; import { useToggleStore } from "../../../../store/ui/useUIToggleStore";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { getSimulationData, updateSimulateData } from "../../scenes/functions/simulationStorage"; import { updateSimulateData } from "../../scenes/functions/simulationStorage";
import { get } from "http";
interface Event { interface Event {
modelName: string; modelName: string;
@@ -35,7 +34,7 @@ const Simulations: React.FC = () => {
const [processes, setProcesses] = useState<Event[][]>(); const [processes, setProcesses] = useState<Event[][]>();
const { setToggleUI } = useToggleStore(); const { setToggleUI } = useToggleStore();
const { projectId } = useParams(); const { projectId } = useParams();
const { setMainProduct } = useMainProduct(); const { setMainState, clearMainState } = useSimulationState();
const { selectedVersion } = versionStore(); const { selectedVersion } = versionStore();
const { comparePopUp, setComparePopUp } = useCompareStore(); const { comparePopUp, setComparePopUp } = useCompareStore();
const { setIsComparing } = useIsComparing(); const { setIsComparing } = useIsComparing();
@@ -51,7 +50,6 @@ const Simulations: React.FC = () => {
productUuid: selectedProduct?.productUuid || "", productUuid: selectedProduct?.productUuid || "",
simulatedId: simulateId, simulatedId: simulateId,
}; };
console.log("singleData: ", singleData);
const getData = await updateSimulateData(singleData); const getData = await updateSimulateData(singleData);
echo.log(getData.message); echo.log(getData.message);
}; };
@@ -74,17 +72,23 @@ const Simulations: React.FC = () => {
const updatedProducts = products.filter((p) => p.productUuid !== productUuid); const updatedProducts = products.filter((p) => p.productUuid !== productUuid);
if (isSelected) { if (isSelected && selectedVersion) {
if (updatedProducts.length > 0) { if (updatedProducts.length > 0) {
let newSelectedIndex = currentIndex; let newSelectedIndex = currentIndex;
if (currentIndex >= updatedProducts.length) { if (currentIndex >= updatedProducts.length) {
newSelectedIndex = updatedProducts.length - 1; newSelectedIndex = updatedProducts.length - 1;
} }
setSelectedProduct(updatedProducts[newSelectedIndex].productUuid, updatedProducts[newSelectedIndex].productName); setSelectedProduct(updatedProducts[newSelectedIndex].productUuid, updatedProducts[newSelectedIndex].productName);
setMainProduct(updatedProducts[newSelectedIndex].productUuid, updatedProducts[newSelectedIndex].productName); const data = {
productUuid: updatedProducts[newSelectedIndex].productUuid,
productName: updatedProducts[newSelectedIndex].productName,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setMainState(data);
} else { } else {
setSelectedProduct("", ""); setSelectedProduct("", "");
setMainProduct("", ""); clearMainState();
} }
} }
@@ -99,9 +103,15 @@ const Simulations: React.FC = () => {
const handleRenameProduct = (productUuid: string, newName: string) => { const handleRenameProduct = (productUuid: string, newName: string) => {
renameProduct(productUuid, newName); renameProduct(productUuid, newName);
renameProductApi({ productName: newName, productUuid, projectId: projectId || "", versionId: selectedVersion?.versionId || "" }); renameProductApi({ productName: newName, productUuid, projectId: projectId || "", versionId: selectedVersion?.versionId || "" });
if (selectedProduct.productUuid === productUuid) { if (selectedProduct.productUuid === productUuid && selectedVersion) {
setSelectedProduct(productUuid, newName); setSelectedProduct(productUuid, newName);
setMainProduct(productUuid, newName); const data = {
productUuid: productUuid,
productName: newName,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setMainState(data);
} }
}; };
@@ -136,7 +146,7 @@ const Simulations: React.FC = () => {
}); });
} }
}, [selectedProduct.productUuid, products]); }, [selectedProduct.productUuid, products]);
//call when comparePopup is true
useEffect(() => { useEffect(() => {
if (comparePopUp || selectedProduct.productUuid) { if (comparePopUp || selectedProduct.productUuid) {
} }
@@ -173,8 +183,16 @@ const Simulations: React.FC = () => {
<div <div
className="value" className="value"
onClick={() => { onClick={() => {
setSelectedProduct(product.productUuid, product.productName); if (selectedVersion) {
setMainProduct(product.productUuid, product.productName); setSelectedProduct(product.productUuid, product.productName);
const data = {
productUuid: product.productUuid,
productName: product.productName,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setMainState(data);
}
}} }}
> >
<input type="radio" name="products" checked={selectedProduct.productUuid === product.productUuid} readOnly /> <input type="radio" name="products" checked={selectedProduct.productUuid === product.productUuid} readOnly />

View File

@@ -4,79 +4,75 @@ import { LogoIconLarge } from "../icons/Logo";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useProjectName } from "../../store/builder/store"; import { useProjectName } from "../../store/builder/store";
import { getAllProjects } from "../../services/dashboard/getAllProjects"; import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { useComparisonProduct } from "../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../store/simulation/useSimulationStore";
import { getUserData } from "../../functions/getUserData"; import { getUserData } from "../../functions/getUserData";
import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject"; import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject";
interface LoadingPageProps { interface LoadingPageProps {
progress: number; // Expect progress as a percentage (0-100) progress: number; // Expect progress as a percentage (0-100)
} }
const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => { const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
const { projectName, setProjectName } = useProjectName(); const { projectName, setProjectName } = useProjectName();
const { projectId } = useParams(); const { projectId } = useParams();
const { comparisonProduct } = useComparisonProduct(); const { comparisonScene } = useSimulationState();
const { userId, organization } = getUserData(); const { userId, organization } = getUserData();
const validatedProgress = Math.min(100, Math.max(0, progress)); const validatedProgress = Math.min(100, Math.max(0, progress));
useEffect(() => {
if (!userId) {
console.error("User data not found in localStorage");
return;
}
const fetchProjects = async () => { useEffect(() => {
try { if (!userId) {
const projects = await getAllProjects(userId, organization); console.error("User data not found in localStorage");
const shared = await sharedWithMeProjects(); return;
const allProjects = [...(projects?.Projects || []), ...(shared || [])];
const matchedProject = allProjects.find(
(val: any) => val.projectUuid === projectId || val._id === projectId
);
if (matchedProject) {
setProjectName(matchedProject.projectName);
} else {
console.warn("Project not found with given ID:", projectId);
} }
} catch (error) {
console.error("Error fetching projects:", error);
}
};
fetchProjects(); const fetchProjects = async () => {
}, []); try {
const projects = await getAllProjects(userId, organization);
const shared = await sharedWithMeProjects();
return ( const allProjects = [...(projects?.Projects || []), ...(shared || [])];
<RenderOverlay>
<div const matchedProject = allProjects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
className={`loading-wrapper ${comparisonProduct != null ? "comparisionLoading" : ""
}`} if (matchedProject) {
> setProjectName(matchedProject.projectName);
<div className="loading-container"> } else {
<div className="project-name">{projectName}</div> console.warn("Project not found with given ID:", projectId);
<div className="loading-hero-container"> }
<div className="logo"> } catch (error) {
<LogoIconLarge /> console.error("Error fetching projects:", error);
}
};
fetchProjects();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<RenderOverlay>
<div className={`loading-wrapper ${comparisonScene != null ? "comparisionLoading" : ""}`}>
<div className="loading-container">
<div className="project-name">{projectName}</div>
<div className="loading-hero-container">
<div className="logo">
<LogoIconLarge />
</div>
<div className="content">Entering A New World with your Aalai</div>
</div>
<div className="progress-container">
<div className="progress-value">{validatedProgress}%</div>
<div className="progress-indicator-container">
<div
className="progress-bar"
style={{ width: `${validatedProgress}%` }} // Dynamic width
></div>
</div>
</div>
</div>
</div> </div>
<div className="content">Entering A New World with your Aalai</div> </RenderOverlay>
</div> );
<div className="progress-container">
<div className="progress-value">{validatedProgress}%</div>
<div className="progress-indicator-container">
<div
className="progress-bar"
style={{ width: `${validatedProgress}%` }} // Dynamic width
></div>
</div>
</div>
</div>
</div>
</RenderOverlay>
);
}; };
export default LoadingPage; export default LoadingPage;

View File

@@ -2,7 +2,7 @@ import { useParams } from "react-router-dom";
import React, { useState, useRef, useEffect, Suspense } from "react"; import React, { useState, useRef, useEffect, Suspense } from "react";
import { CompareLayoutIcon, LayoutIcon, ResizerIcon } from "../../icons/SimulationIcons"; import { CompareLayoutIcon, LayoutIcon, ResizerIcon } from "../../icons/SimulationIcons";
import { useLoadingProgress, useIsComparing } from "../../../store/builder/store"; import { useLoadingProgress, useIsComparing } from "../../../store/builder/store";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../modules/scene/sceneContext";
import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi"; import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
@@ -14,7 +14,7 @@ import useRestStates from "../../../hooks/useResetStates";
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi"; import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
const CompareLayOut = () => { const CompareLayOut = () => {
const { clearComparisonProduct, comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { clearComparisonState, comparisonScene, setComparisonState } = useSimulationState();
const { versionStore } = useSceneContext(); const { versionStore } = useSceneContext();
const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion, setVersions } = versionStore(); const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion, setVersions } = versionStore();
const { setLoadingProgress } = useLoadingProgress(); const { setLoadingProgress } = useLoadingProgress();
@@ -32,11 +32,10 @@ const CompareLayOut = () => {
useEffect(() => { useEffect(() => {
return () => { return () => {
if (selectedVersion?.versionId) { resetStates();
resetStates();
}
}; };
}, [selectedVersion?.versionId]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => { useEffect(() => {
if (!projectId) return; if (!projectId) return;
@@ -63,10 +62,10 @@ const CompareLayOut = () => {
}, [projectId]); }, [projectId]);
useEffect(() => { useEffect(() => {
if (!comparisonProduct) { if (!comparisonScene) {
clearSelectedVersion(); clearSelectedVersion();
} }
}, [comparisonProduct]); }, [comparisonScene]);
OuterClick({ OuterClick({
contextClassName: ["displayLayouts-container", "selectLayout"], contextClassName: ["displayLayouts-container", "selectLayout"],
@@ -108,7 +107,7 @@ const CompareLayOut = () => {
if (finalWidthVw <= 10) { if (finalWidthVw <= 10) {
setWidth("0px"); setWidth("0px");
setIsComparing(false); setIsComparing(false);
clearComparisonProduct(); clearComparisonState();
setIsPlaying(false); setIsPlaying(false);
} else { } else {
setWidth(`${finalWidthVw}vw`); setWidth(`${finalWidthVw}vw`);
@@ -154,7 +153,13 @@ const CompareLayOut = () => {
getAllProductsApi(projectId || "", version.versionId || "").then((data) => { getAllProductsApi(projectId || "", version.versionId || "").then((data) => {
if (data && data.length > 0) { if (data && data.length > 0) {
setSelectedVersion(version); setSelectedVersion(version);
setComparisonProduct(data[0].productUuid, data[0].productName); const comparisonData = {
productUuid: data[0].productUuid,
productName: data[0].productName,
versionUuid: version.versionId,
versionName: version.versionName,
};
setComparisonState(comparisonData);
setLoadingProgress(1); setLoadingProgress(1);
} }
}); });

View File

@@ -1,10 +1,9 @@
import React, { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import PerformanceResult from "./result-card/PerformanceResult"; import PerformanceResult from "./result-card/PerformanceResult";
import EnergyUsage from "./result-card/EnergyUsage"; import { Bar, Pie } from "react-chartjs-2";
import { Bar, Line, Pie } from "react-chartjs-2";
import { useCompareProductDataStore } from "../../../store/builder/store"; import { useCompareProductDataStore } from "../../../store/builder/store";
// import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
export interface CompareProduct { export interface CompareProduct {
productUuid: string; productUuid: string;
productName: string; productName: string;
@@ -21,16 +20,16 @@ export interface CompareProduct {
efficiencyScore?: number; efficiencyScore?: number;
}; };
} }
const ComparisonResult = () => { const ComparisonResult = () => {
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore(); const { compareProductsData } = useCompareProductDataStore();
const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { comparisonScene, mainScene } = useSimulationState();
const { mainProduct } = useMainProduct();
const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>([]); const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>([]);
useEffect(() => { useEffect(() => {
if (compareProductsData.length > 0 && mainProduct && comparisonProduct) { if (compareProductsData.length > 0 && comparisonScene && mainScene) {
const mainProductData = compareProductsData.find((product) => product.productUuid === mainProduct.productUuid); const mainProductData = compareProductsData.find((product) => product.productUuid === mainScene.product.productUuid);
const comparisonProductData = compareProductsData.find((product) => product.productUuid === comparisonProduct.productUuid); const comparisonProductData = compareProductsData.find((product) => product.productUuid === comparisonScene.product.productUuid);
if (mainProductData && comparisonProductData) { if (mainProductData && comparisonProductData) {
setComparedProducts([mainProductData, comparisonProductData]); setComparedProducts([mainProductData, comparisonProductData]);
@@ -40,7 +39,7 @@ const ComparisonResult = () => {
} else { } else {
setComparedProducts([]); setComparedProducts([]);
} }
}, [compareProductsData, mainProduct, comparisonProduct]); }, [compareProductsData, comparisonScene, mainScene]);
useEffect(() => { useEffect(() => {
if (comparedProducts.length === 2) { if (comparedProducts.length === 2) {

View File

@@ -1,464 +1,391 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons"; import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
import { import { comparsionMaterialData, useActiveTool, useProcessBar, useViewSceneStore } from "../../../store/builder/store";
comparsionMaterialData, import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
useActiveTool, import { DailyProductionIcon, EndIcon, ExpandIcon, EyeCloseIcon, HourlySimulationIcon, InfoIcon, MonthlyROI, SpeedIcon, StartIcon } from "../../icons/ExportCommonIcons";
useProcessBar,
useViewSceneStore,
} from "../../../store/builder/store";
import {
useAnimationPlaySpeed,
usePauseButtonStore,
usePlayButtonStore,
useResetButtonStore,
} from "../../../store/ui/usePlayButtonStore";
import {
DailyProductionIcon,
EndIcon,
ExpandIcon,
EyeCloseIcon,
HourlySimulationIcon,
InfoIcon,
MonthlyROI,
SpeedIcon,
StartIcon,
} from "../../icons/ExportCommonIcons";
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor"; import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
import useModuleStore, { import useModuleStore, { useSubModuleStore } from "../../../store/ui/useModuleStore";
useSubModuleStore,
} from "../../../store/ui/useModuleStore";
import ProductionCapacity from "../analysis/ThroughputSummary"; import ProductionCapacity from "../analysis/ThroughputSummary";
import ThroughputSummary from "../analysis/ProductionCapacity"; import ThroughputSummary from "../analysis/ProductionCapacity";
import ROISummary from "../analysis/ROISummary"; import ROISummary from "../analysis/ROISummary";
import { usePlayerStore } from "../../../store/ui/useUIToggleStore"; import { usePlayerStore } from "../../../store/ui/useUIToggleStore";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import InputToggle from "../inputs/InputToggle"; import InputToggle from "../inputs/InputToggle";
import { saveSimulationData } from "../../layout/scenes/functions/simulationStorage";
import { useSceneContext } from "../../../modules/scene/sceneContext";
const SimulationPlayer: React.FC = () => { const SimulationPlayer: React.FC = () => {
const MAX_SPEED = 8; // Maximum speed const MAX_SPEED = 8; // Maximum speed
const isDragging = useRef(false); const isDragging = useRef(false);
const sliderRef = useRef<HTMLDivElement>(null); const sliderRef = useRef<HTMLDivElement>(null);
const [expand, setExpand] = useState(true); const [expand, setExpand] = useState(true);
const { hidePlayer, setHidePlayer } = usePlayerStore(); const { hidePlayer, setHidePlayer } = usePlayerStore();
const { speed, setSpeed } = useAnimationPlaySpeed(); const { speed, setSpeed } = useAnimationPlaySpeed();
const { setIsPlaying } = usePlayButtonStore(); const { setIsPlaying } = usePlayButtonStore();
const { setActiveTool } = useActiveTool(); const { setActiveTool } = useActiveTool();
const { isPaused, setIsPaused } = usePauseButtonStore(); const { isPaused, setIsPaused } = usePauseButtonStore();
const { isReset, setReset } = useResetButtonStore(); const { isReset, setReset } = useResetButtonStore();
const { subModule } = useSubModuleStore(); const { subModule } = useSubModuleStore();
const { clearComparisonProduct } = useComparisonProduct(); const { clearComparisonState } = useSimulationState();
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore(); const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
const { materialData, setMaterialData } = comparsionMaterialData() const { materialData } = comparsionMaterialData();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { productStore } = useSceneContext();
const { selectedProduct, setSelectedProduct } = productStore();
useEffect(() => {
if (isReset) {
setTimeout(() => {
setReset(false);
}, 0);
}
}, [isReset, setReset]);
useEffect(() => { useEffect(() => {
if (materialData.length === 0) return; if (isReset) {
console.log('materialData: ', materialData); setTimeout(() => {
// saveSimulationData({ key: selectedProduct.productUuid, data: materialData }); setReset(false);
}, [materialData]) }, 0);
}
}, [isReset, setReset]);
// Button functions useEffect(() => {
const handleReset = () => { if (materialData.length === 0) return;
setReset(true); // console.log("materialData: ", materialData);
setIsPaused(false); // saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
setSpeed(1); }, [materialData]);
echo.info("Simulation RESET.....");
};
const handlePlayStop = () => {
setIsPaused(!isPaused);
if (isPaused) {
setIsPlaying(true);
}
echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
};
const handleExit = () => {
setIsPlaying(false);
setIsPaused(false);
clearComparisonProduct();
setActiveTool("cursor");
echo.info("Exit Simulation");
};
// Slider functions starts // Button functions
const handleSpeedChange = (event: React.ChangeEvent<HTMLInputElement>) => { const handleReset = () => {
setSpeed(parseFloat(event.target.value)); setReset(true);
}; setIsPaused(false);
setSpeed(1);
const calculateHandlePosition = () => { echo.info("Simulation RESET.....");
return ((speed - 0.5) / (MAX_SPEED - 0.5)) * 100;
};
const handleMouseDown = () => {
isDragging.current = true;
};
const handleMouseMove = (e: MouseEvent) => {
if (!isDragging.current || !sliderRef.current) return;
const sliderRect = sliderRef.current.getBoundingClientRect();
const offsetX = e.clientX - sliderRect.left;
const percentage = Math.min(Math.max(offsetX / sliderRect.width, 0), 1);
const newValue = 0.5 + percentage * (50 - 0.5);
setSpeed(parseFloat(newValue.toFixed(1)));
};
const handleMouseUp = () => {
isDragging.current = false;
};
const handleVisibility = () => {
if (document.visibilityState !== 'visible' && isPlaying) {
setIsPaused(!isPaused);
if (isPaused) {
setIsPlaying(true);
}
echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
}
}
useEffect(() => {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
document.addEventListener('visibilitychange', handleVisibility);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
document.removeEventListener('visibilitychange', handleVisibility);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Slider function ends
// UI-Part
const hourlySimulation = 25;
const dailyProduction = 75;
const monthlyROI = 10;
const { processBar } = useProcessBar();
useEffect(() => { }, [processBar]);
const intervals = [50, 20, 30, 40, 50, 60]; // in minutes
const totalSegments = intervals.length;
const progress = 20; // percent (example)
const processPlayerRef = useRef<HTMLDivElement>(null);
const processWrapperRef = useRef<HTMLDivElement>(null);
const [playerPosition, setPlayerPosition] = useState(20); // initial position
const handleProcessMouseDown = (e: React.MouseEvent) => {
if (!processWrapperRef.current) return;
const rect = processWrapperRef.current.getBoundingClientRect();
let x = e.clientX - rect.left;
x = Math.max(0, Math.min(x, rect.width));
setPlayerPosition(x);
const onMouseMove = (e: MouseEvent) => {
if (!processWrapperRef.current) return;
const newRect = processWrapperRef.current.getBoundingClientRect();
let newX = e.clientX - newRect.left;
newX = Math.max(0, Math.min(newX, newRect.width));
setPlayerPosition(newX);
const progressPercent = (newX / newRect.width) * 100;
console.log(`Dragging at progress: ${progressPercent.toFixed(1)}%`);
}; };
const onMouseUp = () => { const handlePlayStop = () => {
document.removeEventListener("mousemove", onMouseMove); setIsPaused(!isPaused);
document.removeEventListener("mouseup", onMouseUp); if (isPaused) {
setIsPlaying(true);
}
echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
}; };
document.addEventListener("mousemove", onMouseMove); const handleExit = () => {
document.addEventListener("mouseup", onMouseUp); setIsPlaying(false);
}; setIsPaused(false);
clearComparisonState();
setActiveTool("cursor");
echo.info("Exit Simulation");
};
return ( // Slider functions starts
<> const handleSpeedChange = (event: React.ChangeEvent<HTMLInputElement>) => {
{isPlaying && activeModule === "simulation" && ( setSpeed(parseFloat(event.target.value));
<div className="label-toogler "> {/* bottom */} };
<InputToggle
value={viewSceneLabels} const calculateHandlePosition = () => {
inputKey="1" return ((speed - 0.5) / (MAX_SPEED - 0.5)) * 100;
label="Enable View Labels" };
onClick={() => setViewSceneLabels(!viewSceneLabels)}
/> const handleMouseDown = () => {
</div> isDragging.current = true;
)} };
<div className={`simulation-player-wrapper${hidePlayer ? " hide" : ""}`}>
<div className={`simulation-player-container ${expand ? "open" : ""}`}> const handleMouseMove = (e: MouseEvent) => {
<div className="controls-container"> if (!isDragging.current || !sliderRef.current) return;
{!hidePlayer && subModule === "analysis" && (
<div className="production-details"> const sliderRect = sliderRef.current.getBoundingClientRect();
{/* hourlySimulation */} const offsetX = e.clientX - sliderRect.left;
<div className="hourly-wrapper production-wrapper"> const percentage = Math.min(Math.max(offsetX / sliderRect.width, 0), 1);
<div className="header"> const newValue = 0.5 + percentage * (50 - 0.5);
<div className="icon"> setSpeed(parseFloat(newValue.toFixed(1)));
<HourlySimulationIcon /> };
</div>
<h4 className="label">ThroughPut</h4> const handleMouseUp = () => {
</div> isDragging.current = false;
<div className="progress-wrapper"> };
<div
className="progress" const handleVisibility = () => {
style={{ width: hourlySimulation }} if (document.visibilityState !== "visible" && isPlaying) {
></div> setIsPaused(!isPaused);
</div> if (isPaused) {
setIsPlaying(true);
}
echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
}
};
useEffect(() => {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
document.addEventListener("visibilitychange", handleVisibility);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
document.removeEventListener("visibilitychange", handleVisibility);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Slider function ends
// UI-Part
const hourlySimulation = 25;
const dailyProduction = 75;
const monthlyROI = 10;
const { processBar } = useProcessBar();
useEffect(() => {}, [processBar]);
const intervals = [50, 20, 30, 40, 50, 60]; // in minutes
const totalSegments = intervals.length;
const progress = 20; // percent (example)
const processPlayerRef = useRef<HTMLDivElement>(null);
const processWrapperRef = useRef<HTMLDivElement>(null);
const [playerPosition, setPlayerPosition] = useState(20); // initial position
const handleProcessMouseDown = (e: React.MouseEvent) => {
if (!processWrapperRef.current) return;
const rect = processWrapperRef.current.getBoundingClientRect();
let x = e.clientX - rect.left;
x = Math.max(0, Math.min(x, rect.width));
setPlayerPosition(x);
const onMouseMove = (e: MouseEvent) => {
if (!processWrapperRef.current) return;
const newRect = processWrapperRef.current.getBoundingClientRect();
let newX = e.clientX - newRect.left;
newX = Math.max(0, Math.min(newX, newRect.width));
setPlayerPosition(newX);
const progressPercent = (newX / newRect.width) * 100;
console.log(`Dragging at progress: ${progressPercent.toFixed(1)}%`);
};
const onMouseUp = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
};
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
};
return (
<>
{isPlaying && activeModule === "simulation" && (
<div className="label-toogler ">
{" "}
{/* bottom */}
<InputToggle value={viewSceneLabels} inputKey="1" label="Enable View Labels" onClick={() => setViewSceneLabels(!viewSceneLabels)} />
</div> </div>
{/* dailyProduction */}
<div className="dailyProduction-wrapper production-wrapper">
<div className="header">
<div className="icon">
<DailyProductionIcon />
</div>
<div className="label">Production Capacity</div>
</div>
<div className="progress-wrapper">
<div
className="progress"
style={{ width: dailyProduction }}
></div>
</div>
</div>
{/* monthlyROI */}
<div className="monthlyROI-wrapper production-wrapper">
<div className="header">
<div className="icon">
<MonthlyROI />
</div>
<div className="label">ROI</div>
</div>
<div className="progress-wrapper">
<div
className="progress"
style={{ width: `${monthlyROI}%` }}
></div>
</div>{" "}
</div>
</div>
)} )}
{!hidePlayer && subModule !== "analysis" && ( <div className={`simulation-player-wrapper${hidePlayer ? " hide" : ""}`}>
<div className="header"> <div className={`simulation-player-container ${expand ? "open" : ""}`}>
<InfoIcon /> <div className="controls-container">
{isPaused ? "Paused - system idle." : "Running simulation..."} {!hidePlayer && subModule === "analysis" && (
</div> <div className="production-details">
)} {/* hourlySimulation */}
<div className="controls-wrapper"> <div className="hourly-wrapper production-wrapper">
{!hidePlayer && ( <div className="header">
<button <div className="icon">
id="simulation-reset-button" <HourlySimulationIcon />
className="simulation-button-container" </div>
onClick={() => { <h4 className="label">ThroughPut</h4>
handleReset(); </div>
}} <div className="progress-wrapper">
> <div className="progress" style={{ width: hourlySimulation }}></div>
<ResetIcon /> </div>
Reset </div>
</button> {/* dailyProduction */}
)} <div className="dailyProduction-wrapper production-wrapper">
{!hidePlayer && ( <div className="header">
<button <div className="icon">
id="simulation-play-button" <DailyProductionIcon />
className="simulation-button-container" </div>
onClick={() => { <div className="label">Production Capacity</div>
handlePlayStop(); </div>
}} <div className="progress-wrapper">
> <div className="progress" style={{ width: dailyProduction }}></div>
<PlayStopIcon /> </div>
{isPaused ? "Play" : "Stop"} </div>
</button> {/* monthlyROI */}
)} <div className="monthlyROI-wrapper production-wrapper">
<button <div className="header">
id="simulation-reset-button" <div className="icon">
className="simulation-button-container" <MonthlyROI />
onClick={() => { </div>
handleExit(); <div className="label">ROI</div>
}} </div>
> <div className="progress-wrapper">
<ExitIcon /> <div className="progress" style={{ width: `${monthlyROI}%` }}></div>
{!hidePlayer && "Exit"} </div>{" "}
</button> </div>
<button </div>
id="simulation-reset-button" )}
className="simulation-button-container" {!hidePlayer && subModule !== "analysis" && (
onClick={() => { <div className="header">
setHidePlayer(!hidePlayer); <InfoIcon />
}} {isPaused ? "Paused - system idle." : "Running simulation..."}
> </div>
<EyeCloseIcon /> )}
{!hidePlayer && "Hide"} <div className="controls-wrapper">
</button> {!hidePlayer && (
{subModule === "analysis" && ( <button
<button id="simulation-reset-button"
id="simulation-expand-button" className="simulation-button-container"
className="expand-icon-container" onClick={() => {
onClick={() => setExpand(!expand)} handleReset();
> }}
<ExpandIcon isActive={!expand} /> >
</button> <ResetIcon />
)} Reset
</div> </button>
</div> )}
{!hidePlayer && ( {!hidePlayer && (
<div className="progresser-wrapper"> <button
<div className="time-displayer"> id="simulation-play-button"
<div className="start-time-wrappper"> className="simulation-button-container"
<div className="icon"> onClick={() => {
<StartIcon /> handlePlayStop();
</div> }}
<div className="time-wrapper"> >
<div className="date">23 April ,25</div> <PlayStopIcon />
<div className="time">04:41 PM</div> {isPaused ? "Play" : "Stop"}
</div> </button>
</div> )}
<div className="time-progresser"> <button
<div className="timeline"> id="simulation-reset-button"
{intervals.map((label, index) => { className="simulation-button-container"
const segmentProgress = (index / totalSegments) * 100; onClick={() => {
const isFilled = progress >= segmentProgress; handleExit();
return ( }}
<React.Fragment key={`${index}-${label}`}> >
<div className="label-dot-wrapper"> <ExitIcon />
<div className="label">{label} mins</div> {!hidePlayer && "Exit"}
<div </button>
className={`dot ${isFilled ? "filled" : ""}`} <button
></div> id="simulation-reset-button"
</div> className="simulation-button-container"
{index < intervals.length - 1 && ( onClick={() => {
<div setHidePlayer(!hidePlayer);
className={`line ${progress >= ((index + 1) / totalSegments) * 100 }}
? "filled" >
: "" <EyeCloseIcon />
}`} {!hidePlayer && "Hide"}
></div> </button>
)} {subModule === "analysis" && (
</React.Fragment> <button id="simulation-expand-button" className="expand-icon-container" onClick={() => setExpand(!expand)}>
); <ExpandIcon isActive={!expand} />
})} </button>
</div> )}
</div> </div>
<div className="end-time-wrappper">
<div className="time-wrapper">
<div className="time">00:10:20</div>
</div>
<div className="icon">
<EndIcon />
</div>
</div>
</div>
<div className="speed-control-container">
<div className="min-value">
<div className="icon">
<SpeedIcon />
</div>
Speed
</div>
<div className="slider-container" ref={sliderRef}>
<div className="speed-label mix-value">0.5X</div>
<div className="marker marker-10"></div>
<div className="marker marker-20"></div>
<div className="marker marker-30"></div>
<div className="marker marker-40"></div>
<div className="marker marker-50"></div>
<div className="marker marker-60"></div>
<div className="marker marker-70"></div>
<div className="marker marker-80"></div>
<div className="marker marker-90"></div>
<div className="custom-slider-wrapper">
<div className="custom-slider">
<button
id="slider-handle"
className={`slider-handle ${isDragging ? "dragging" : ""
}`}
style={{ left: `${calculateHandlePosition()}%` }}
onMouseDown={handleMouseDown}
>
{speed.toFixed(1)}x
</button>
<input
type="range"
min="0.5"
max={MAX_SPEED}
step="0.1"
value={speed}
onChange={handleSpeedChange}
className="slider-input"
/>
</div> </div>
<div className="speed-label max-value">{MAX_SPEED}x</div> {!hidePlayer && (
</div> <div className="progresser-wrapper">
<div className="time-displayer">
<div className="start-time-wrappper">
<div className="icon">
<StartIcon />
</div>
<div className="time-wrapper">
<div className="date">23 April ,25</div>
<div className="time">04:41 PM</div>
</div>
</div>
<div className="time-progresser">
<div className="timeline">
{intervals.map((label, index) => {
const segmentProgress = (index / totalSegments) * 100;
const isFilled = progress >= segmentProgress;
return (
<React.Fragment key={`${index}-${label}`}>
<div className="label-dot-wrapper">
<div className="label">{label} mins</div>
<div className={`dot ${isFilled ? "filled" : ""}`}></div>
</div>
{index < intervals.length - 1 && <div className={`line ${progress >= ((index + 1) / totalSegments) * 100 ? "filled" : ""}`}></div>}
</React.Fragment>
);
})}
</div>
</div>
<div className="end-time-wrappper">
<div className="time-wrapper">
<div className="time">00:10:20</div>
</div>
<div className="icon">
<EndIcon />
</div>
</div>
</div>
<div className="speed-control-container">
<div className="min-value">
<div className="icon">
<SpeedIcon />
</div>
Speed
</div>
<div className="slider-container" ref={sliderRef}>
<div className="speed-label mix-value">0.5X</div>
<div className="marker marker-10"></div>
<div className="marker marker-20"></div>
<div className="marker marker-30"></div>
<div className="marker marker-40"></div>
<div className="marker marker-50"></div>
<div className="marker marker-60"></div>
<div className="marker marker-70"></div>
<div className="marker marker-80"></div>
<div className="marker marker-90"></div>
<div className="custom-slider-wrapper">
<div className="custom-slider">
<button id="slider-handle" className={`slider-handle ${isDragging ? "dragging" : ""}`} style={{ left: `${calculateHandlePosition()}%` }} onMouseDown={handleMouseDown}>
{speed.toFixed(1)}x
</button>
<input type="range" min="0.5" max={MAX_SPEED} step="0.1" value={speed} onChange={handleSpeedChange} className="slider-input" />
</div>
<div className="speed-label max-value">{MAX_SPEED}x</div>
</div>
</div>
</div>
</div>
)}
{!hidePlayer && subModule === "analysis" && (
<div className="processDisplayer">
<div className="start-displayer timmer">00:00</div>
<div className="end-displayer timmer">24:00</div>
<div className="process-wrapper" style={{ padding: expand ? "0px" : "5px 35px" }}>
{/* eslint-disable-next-line */}
<div className="process-container" ref={processWrapperRef} onMouseDown={handleProcessMouseDown}>
{processBar?.length > 0 ? (
processBar.map((item: any, index: any) => (
<div
key={`${index}-${item.name}`}
className="process"
style={{
width: `${item.completed}%`,
backgroundColor: getAvatarColor(index),
}}
>
<div className="process-player" ref={processPlayerRef} style={{ left: playerPosition, position: "absolute" }}></div>
</div>
))
) : (
<div>No process data available</div>
)}
</div>
</div>
</div>
)}
</div> </div>
</div>
</div> </div>
)} {/* {subModule === "analysis" && ( */}
{!hidePlayer && subModule === "analysis" && ( {subModule === "analysis" && (
<div className="processDisplayer"> <div className="analysis">
<div className="start-displayer timmer">00:00</div> <div className="analysis-wrapper">
<div className="end-displayer timmer">24:00</div> <ProductionCapacity />
<div <ThroughputSummary />
className="process-wrapper" </div>
style={{ padding: expand ? "0px" : "5px 35px" }} <ROISummary />
>
{/* eslint-disable-next-line */}
<div
className="process-container"
ref={processWrapperRef}
onMouseDown={handleProcessMouseDown}
>
{processBar?.length > 0 ? (
processBar.map((item: any, index: any) => (
<div
key={`${index}-${item.name}`}
className="process"
style={{
width: `${item.completed}%`,
backgroundColor: getAvatarColor(index),
}}
>
<div
className="process-player"
ref={processPlayerRef}
style={{ left: playerPosition, position: "absolute" }}
></div>
</div>
))
) : (
<div>No process data available</div>
)}
</div> </div>
</div> )}
</div> {/* )} */}
)} </>
</div> );
</div>
{/* {subModule === "analysis" && ( */}
{subModule === "analysis" && (
<div className="analysis">
<div className="analysis-wrapper">
<ProductionCapacity />
<ThroughputSummary />
</div>
<ROISummary />
</div>
)}
{/* )} */}
</>
);
}; };
export default SimulationPlayer; export default SimulationPlayer;

View File

@@ -4,7 +4,7 @@ import { CameraControls } from "@react-three/drei";
import { useSceneContext } from "../sceneContext"; import { useSceneContext } from "../sceneContext";
import { useIsComparing } from "../../../store/builder/store"; import { useIsComparing } from "../../../store/builder/store";
import { useSceneStore } from "../../../store/scene/useSceneStore"; import { useSceneStore } from "../../../store/scene/useSceneStore";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import useModuleStore from "../../../store/ui/useModuleStore"; import useModuleStore from "../../../store/ui/useModuleStore";
import * as CONSTANTS from "../../../types/world/worldConstants"; import * as CONSTANTS from "../../../types/world/worldConstants";
@@ -14,7 +14,7 @@ function SyncCam() {
const { controls } = useThree(); const { controls } = useThree();
const { isComparing } = useIsComparing(); const { isComparing } = useIsComparing();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { comparisonProduct } = useComparisonProduct(); const { comparisonScene } = useSimulationState();
const { setCamera, camState } = useSceneStore(); const { setCamera, camState } = useSceneStore();
useFrame(() => { useFrame(() => {
@@ -25,7 +25,7 @@ function SyncCam() {
(controls as any).mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse; (controls as any).mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse;
(controls as CameraControls).setLookAt(camState.position.x, camState.position.y, camState.position.z, camState.target.x, camState.target.y, camState.target.z, true); (controls as CameraControls).setLookAt(camState.position.x, camState.position.y, camState.position.z, camState.target.x, camState.target.y, camState.target.z, true);
} }
if (layout === "Main Layout" && controls && isComparing && activeModule === "simulation" && comparisonProduct) { if (layout === "Main Layout" && controls && isComparing && activeModule === "simulation" && comparisonScene) {
const position = (controls as CameraControls).getPosition(new Vector3()); const position = (controls as CameraControls).getPosition(new Vector3());
const target = (controls as CameraControls).getTarget(new Vector3()); const target = (controls as CameraControls).getTarget(new Vector3());
setCamera(position, target); setCamera(position, target);

View File

@@ -4,13 +4,12 @@ import { upsertProductOrEventApi } from "../../../services/simulation/products/U
import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi"; import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore"; import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../scene/sceneContext"; import { useSceneContext } from "../../scene/sceneContext";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../../store/simulation/useSimulationStore";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
function Products() { function Products() {
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, layout, productStore, versionStore } = useSceneContext(); const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, layout, productStore, versionStore } = useSceneContext();
const { products, getProductById, addProduct, setProducts, selectedProduct, setSelectedProduct } = productStore(); const { products, getProductById, addProduct, setProducts, selectedProduct, setSelectedProduct } = productStore();
const { setMainProduct } = useMainProduct();
const { addVehicle, clearVehicles } = vehicleStore(); const { addVehicle, clearVehicles } = vehicleStore();
const { addArmBot, clearArmBots } = armBotStore(); const { addArmBot, clearArmBots } = armBotStore();
const { addMachine, clearMachines } = machineStore(); const { addMachine, clearMachines } = machineStore();
@@ -20,26 +19,25 @@ function Products() {
const { addCrane, addCurrentAction: addCurrentActionCrane, clearCranes } = craneStore(); const { addCrane, addCurrentAction: addCurrentActionCrane, clearCranes } = craneStore();
const { isReset } = useResetButtonStore(); const { isReset } = useResetButtonStore();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { mainProduct } = useMainProduct(); const { setMainState, mainScene, comparisonScene } = useSimulationState();
const { comparisonProduct } = useComparisonProduct();
const { selectedVersion } = versionStore(); const { selectedVersion } = versionStore();
const { projectId } = useParams(); const { projectId } = useParams();
useEffect(() => { useEffect(() => {
if (layout === "Main Layout" && mainProduct) { if (layout === "Main Layout" && mainScene) {
setSelectedProduct(mainProduct.productUuid, mainProduct.productName); setSelectedProduct(mainScene.product.productUuid, mainScene.product.productName);
} }
}, [mainProduct]); }, [mainScene, layout]);
useEffect(() => { useEffect(() => {
if (layout === "Comparison Layout" && comparisonProduct) { if (layout === "Comparison Layout" && comparisonScene) {
setSelectedProduct(comparisonProduct.productUuid, comparisonProduct.productName); setSelectedProduct(comparisonScene.product.productUuid, comparisonScene.product.productName);
} }
}, [comparisonProduct]); }, [comparisonScene, layout]);
useEffect(() => { useEffect(() => {
if (!selectedVersion) return; if (!selectedVersion) return;
getAllProductsApi(projectId || "", selectedVersion?.versionId || "") getAllProductsApi(projectId || "", selectedVersion.versionId)
.then((data) => { .then((data) => {
if (data && data.length === 0) { if (data && data.length === 0) {
const id = THREE.MathUtils.generateUUID(); const id = THREE.MathUtils.generateUUID();
@@ -49,17 +47,29 @@ function Products() {
productName: name, productName: name,
productUuid: id, productUuid: id,
projectId: projectId || "", projectId: projectId || "",
versionId: selectedVersion?.versionId || "", versionId: selectedVersion.versionId,
}); });
if (layout === "Main Layout") { if (layout === "Main Layout" && selectedVersion) {
setSelectedProduct(id, name); setSelectedProduct(id, name);
setMainProduct(id, name); const mainData = {
productUuid: id,
productName: name,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setMainState(mainData);
} }
} else { } else {
setProducts(data); setProducts(data);
if (layout === "Main Layout") { if (layout === "Main Layout") {
setSelectedProduct(data[0].productUuid, data[0].productName); setSelectedProduct(data[0].productUuid, data[0].productName);
setMainProduct(data[0].productUuid, data[0].productName); const mainData = {
productUuid: data[0].productUuid,
productName: data[0].productName,
versionUuid: selectedVersion.versionId,
versionName: selectedVersion.versionName,
};
setMainState(mainData);
} }
} }
}) })

View File

@@ -108,7 +108,7 @@ export function useCheckActiveRoboticArmsInSubsequence() {
} }
// Helper function to get machine sequences (simplified from your example) // Helper function to get machine sequences (simplified from your example)
function determineExecutionMachineSequences(products: productsSchema): EventsSchema[][] { function determineExecutionMachineSequences(products: ProductsSchema): EventsSchema[][] {
const pointToEventMap = new Map<string, EventsSchema>(); const pointToEventMap = new Map<string, EventsSchema>();
const allPoints: PointsScheme[] = []; const allPoints: PointsScheme[] = [];

View File

@@ -1,6 +1,6 @@
import { extractTriggersFromPoint } from "./extractTriggersFromPoint"; import { extractTriggersFromPoint } from "./extractTriggersFromPoint";
export async function determineExecutionMachineSequences(products: productsSchema): Promise<EventsSchema[][]> { export async function determineExecutionMachineSequences(products: ProductsSchema): Promise<EventsSchema[][]> {
const pointToEventMap = new Map<string, EventsSchema>(); const pointToEventMap = new Map<string, EventsSchema>();
const allPoints: PointsScheme[] = []; const allPoints: PointsScheme[] = [];

View File

@@ -1,6 +1,6 @@
import { extractTriggersFromPoint } from "./extractTriggersFromPoint"; import { extractTriggersFromPoint } from "./extractTriggersFromPoint";
export function determineExecutionOrder(products: productsSchema): Action[] { export function determineExecutionOrder(products: ProductsSchema): Action[] {
// Create maps for all events and points // Create maps for all events and points
const pointMap = new Map<string, PointsScheme>(); const pointMap = new Map<string, PointsScheme>();
const allPoints: PointsScheme[] = []; const allPoints: PointsScheme[] = [];

View File

@@ -1,6 +1,6 @@
import { extractTriggersFromPoint } from "./extractTriggersFromPoint"; import { extractTriggersFromPoint } from "./extractTriggersFromPoint";
export async function determineExecutionSequences(products: productsSchema): Promise<PointsScheme[][]> { export async function determineExecutionSequences(products: ProductsSchema): Promise<PointsScheme[][]> {
// Create maps for all points // Create maps for all points
const pointMap = new Map<string, PointsScheme>(); const pointMap = new Map<string, PointsScheme>();
const allPoints: PointsScheme[] = []; const allPoints: PointsScheme[] = [];

View File

@@ -75,7 +75,7 @@ export function findConveyorSubsequence(
} }
// Helper function to get machine sequences (simplified from your example) // Helper function to get machine sequences (simplified from your example)
function determineExecutionMachineSequences(products: productsSchema): EventsSchema[][] { function determineExecutionMachineSequences(products: ProductsSchema): EventsSchema[][] {
const pointToEventMap = new Map<string, EventsSchema>(); const pointToEventMap = new Map<string, EventsSchema>();
const allPoints: PointsScheme[] = []; const allPoints: PointsScheme[] = [];

View File

@@ -5,7 +5,10 @@ import { determineExecutionOrder } from "./functions/determineExecutionOrder";
import { useSceneContext } from "../../scene/sceneContext"; import { useSceneContext } from "../../scene/sceneContext";
import SimulationHandler from "./SimulationHandler"; import SimulationHandler from "./SimulationHandler";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { getSimulationData, saveSimulationData } from "../../../components/layout/scenes/functions/simulationStorage"; import {
getSimulationData,
saveSimulationData,
} from "../../../components/layout/scenes/functions/simulationStorage";
import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore";
import { useSimulateId } from "../../../store/builder/store"; import { useSimulateId } from "../../../store/builder/store";
@@ -32,18 +35,23 @@ function Simulator() {
handleAction(action); handleAction(action);
}); });
}, [products, isPlaying, isReset, selectedProduct]); }, [products, isPlaying, isReset, selectedProduct]);
useEffect(() => { useEffect(() => {
if (!projectId || !selectedVersion || !selectedProduct?.productUuid) return; if (!projectId || !selectedVersion || !selectedProduct?.productUuid) return;
const fetchSimulateData = async () => { const fetchSimulateData = async () => {
const getData = await getSimulationData(projectId, selectedVersion.versionId, selectedProduct?.productUuid); const getData = await getSimulationData(
projectId,
selectedVersion.versionId,
selectedProduct?.productUuid
);
const product = getProductById(selectedProduct.productUuid); const product = getProductById(selectedProduct.productUuid);
if (!product) return; if (!product) return;
const products: productsSchema = [product]; const products: ProductsSchema = [product];
const getSimulate = getData?.data; const getSimulate = getData?.data;
console.log("getSimulate: ", getSimulate); // console.log("getSimulate: ", getSimulate);
if (getData && getSimulate && getSimulate.productTimestamp === products[0]?.timestamp) { if (getData && getSimulate && getSimulate.productTimestamp === products[0]?.timestamp) {
setSimulateId(getSimulate._id); setSimulateId(getSimulate._id);
console.log(" getSimulate.data: ", getSimulate.data); // console.log(" getSimulate.data: ", getSimulate.data);
addSimulationRecords( addSimulationRecords(
projectId, projectId,
selectedVersion?.versionId || "", selectedVersion?.versionId || "",
@@ -58,15 +66,22 @@ function Simulator() {
projectId: projectId, projectId: projectId,
versionId: selectedVersion.versionId, versionId: selectedVersion.versionId,
productUuid: selectedProduct.productUuid, productUuid: selectedProduct.productUuid,
simulateData: useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, selectedProduct.productUuid)?.simulateData, simulateData: useSimulationManager
.getState()
.getProductById(
projectId,
selectedVersion?.versionId,
selectedProduct.productUuid
)?.simulateData,
}; };
const simulations = await saveSimulationData(data); const simulations = await saveSimulationData(data);
console.log("simulations: ", simulations); // console.log("simulations: ", simulations);
echo.log("Simulation data saved successfully"); echo.log("Simulation data saved successfully");
} }
}; };
fetchSimulateData(); fetchSimulateData();
}, []); }, []);
return ( return (
<> <>
{/* <simulationHandler/> */} {/* <simulationHandler/> */}

View File

@@ -2,7 +2,7 @@ import { create } from "zustand";
import { immer } from "zustand/middleware/immer"; import { immer } from "zustand/middleware/immer";
type ProductsStore = { type ProductsStore = {
products: productsSchema; products: ProductsSchema;
selectedProduct: { productUuid: string; productName: string }; selectedProduct: { productUuid: string; productName: string };
setSelectedProduct: (productUuid: string, productName: string) => void; setSelectedProduct: (productUuid: string, productName: string) => void;
@@ -10,7 +10,7 @@ type ProductsStore = {
// Product-level actions // Product-level actions
addProduct: (productName: string, productUuid: string) => void; addProduct: (productName: string, productUuid: string) => void;
setProducts: (products: productsSchema) => void; setProducts: (products: ProductsSchema) => void;
clearProducts: () => void; clearProducts: () => void;
removeProduct: (productUuid: string) => void; removeProduct: (productUuid: string) => void;
updateProduct: (productUuid: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void; updateProduct: (productUuid: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;

View File

@@ -1,6 +1,6 @@
import { create } from 'zustand'; import { create } from "zustand";
import { immer } from 'zustand/middleware/immer'; import { immer } from "zustand/middleware/immer";
import * as THREE from 'three'; import * as THREE from "three";
interface SelectedEventSphereState { interface SelectedEventSphereState {
selectedEventSphere: THREE.Mesh | null; selectedEventSphere: THREE.Mesh | null;
@@ -120,15 +120,9 @@ interface SelectedAnimationState {
animationName: string; animationName: string;
animationType: "behaviour" | "animatedTravel"; animationType: "behaviour" | "animatedTravel";
animation: string | null; animation: string | null;
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; } travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null };
} | null; } | null;
setSelectedAnimation: (animation: { setSelectedAnimation: (animation: { animationUuid: string; animationName: string; animationType: "behaviour" | "animatedTravel"; animation: string | null; travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null } }) => void;
animationUuid: string;
animationName: string;
animationType: "behaviour" | "animatedTravel";
animation: string | null;
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
}) => void;
clearSelectedAnimation: () => void; clearSelectedAnimation: () => void;
} }
@@ -180,45 +174,55 @@ export const useIsRotating = create<IsRotatingState>()(
})) }))
); );
interface MainProductState { interface SimulationState {
mainProduct: { productUuid: string; productName: string } | null; mainScene: {
setMainProduct: (productUuid: string, productName: string) => void; product: { productUuid: string; productName: string };
clearMainProduct: () => void; version: { versionUuid: string; versionName: string };
};
comparisonScene: {
product: { productUuid: string; productName: string };
version: { versionUuid: string; versionName: string };
} | null;
setMainState: (mainScene: { productUuid: string; productName: string; versionUuid: string; versionName: string }) => void;
setComparisonState: (comparisonScene: { productUuid: string; productName: string; versionUuid: string; versionName: string } | null) => void;
clearMainState: () => void;
clearComparisonState: () => void;
} }
export const useMainProduct = create<MainProductState>()( export const useSimulationState = create<SimulationState>()(
immer((set) => ({ immer((set) => ({
mainProduct: null, mainScene: {
setMainProduct: (productUuid: string, productName: string) => { product: { productUuid: "", productName: "" },
version: { versionUuid: "", versionName: "" },
},
comparisonScene: null,
setMainState: (mainScene) => {
set((state) => { set((state) => {
state.mainProduct = { productUuid, productName }; state.mainScene.product = { productUuid: mainScene.productUuid, productName: mainScene.productName };
state.mainScene.version = { versionUuid: mainScene.versionUuid, versionName: mainScene.versionName };
}); });
}, },
clearMainProduct: () => { setComparisonState: (comparisonScene) => {
set((state) => { set((state) => {
state.mainProduct = null; if (comparisonScene) {
state.comparisonScene = {
product: { productUuid: comparisonScene.productUuid, productName: comparisonScene.productName },
version: { versionUuid: comparisonScene.versionUuid, versionName: comparisonScene.versionName },
};
} else {
state.comparisonScene = null;
}
}); });
}, },
})) clearMainState: () => {
);
interface ComparisonProductState {
comparisonProduct: { productUuid: string; productName: string } | null;
setComparisonProduct: (productUuid: string, productName: string) => void;
clearComparisonProduct: () => void;
}
export const useComparisonProduct = create<ComparisonProductState>()(
immer((set) => ({
comparisonProduct: null,
setComparisonProduct: (productUuid: string, productName: string) => {
set((state) => { set((state) => {
state.comparisonProduct = { productUuid, productName }; state.mainScene.product = { productUuid: "", productName: "" };
state.mainScene.version = { versionUuid: "", versionName: "" };
}); });
}, },
clearComparisonProduct: () => { clearComparisonState: () => {
set((state) => { set((state) => {
state.comparisonProduct = null; state.comparisonScene = null;
}); });
}, },
})) }))
@@ -242,14 +246,14 @@ export const useSelectedPoints = create<SelectedPointsState>()(
}, },
addSelectedPoint: (point) => { addSelectedPoint: (point) => {
set((state) => { set((state) => {
if (!state.selectedPoints.find(p => p.uuid === point.uuid)) { if (!state.selectedPoints.find((p) => p.uuid === point.uuid)) {
state.selectedPoints.push(point); state.selectedPoints.push(point);
} }
}); });
}, },
removeSelectedPoint: (uuid) => { removeSelectedPoint: (uuid) => {
set((state) => { set((state) => {
state.selectedPoints = state.selectedPoints.filter(p => p.uuid !== uuid); state.selectedPoints = state.selectedPoints.filter((p) => p.uuid !== uuid);
}); });
}, },
clearSelectedPoints: () => { clearSelectedPoints: () => {
@@ -258,4 +262,4 @@ export const useSelectedPoints = create<SelectedPointsState>()(
}); });
}, },
})) }))
); );

View File

@@ -400,7 +400,7 @@ type MaterialsSchema = MaterialSchema[];
// Products // Products
type productsSchema = { type ProductsSchema = {
productName: string; productName: string;
productUuid: string; productUuid: string;
eventDatas: EventsSchema[]; eventDatas: EventsSchema[];

View File

@@ -6,12 +6,12 @@ import useCameraModeStore, { usePlayButtonStore } from "../../store/ui/usePlayBu
import { detectModifierKeys } from "./detectModifierKeys"; import { detectModifierKeys } from "./detectModifierKeys";
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore"; import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
import { useLogger } from "../../components/ui/log/LoggerContext"; import { useLogger } from "../../components/ui/log/LoggerContext";
import { useComparisonProduct } from "../../store/simulation/useSimulationStore"; import { useSimulationState } from "../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../store/builder/useBuilderStore";
import { useSceneContext } from "../../modules/scene/sceneContext"; import { useSceneContext } from "../../modules/scene/sceneContext";
const KeyPressListener: React.FC = () => { const KeyPressListener: React.FC = () => {
const { comparisonProduct, clearComparisonProduct } = useComparisonProduct(); const { comparisonScene, clearComparisonState } = useSimulationState();
const { activeModule, setActiveModule } = useModuleStore(); const { activeModule, setActiveModule } = useModuleStore();
const { assetStore, versionStore } = useSceneContext(); const { assetStore, versionStore } = useSceneContext();
const { selectedAssets } = assetStore(); const { selectedAssets } = assetStore();
@@ -178,7 +178,7 @@ const KeyPressListener: React.FC = () => {
clearSelectedZone(); clearSelectedZone();
setShowShortcuts(false); setShowShortcuts(false);
setIsComparing(false); setIsComparing(false);
clearComparisonProduct(); clearComparisonState();
setIsLogListVisible(false); setIsLogListVisible(false);
setIsRenameMode(false); setIsRenameMode(false);
setDfxUploaded([]); setDfxUploaded([]);
@@ -203,7 +203,7 @@ const KeyPressListener: React.FC = () => {
handleBuilderShortcuts(keyCombination); handleBuilderShortcuts(keyCombination);
// Shortcut to enter play mode // Shortcut to enter play mode
if (keyCombination === "Ctrl+P" && !toggleView && !comparisonProduct) { if (keyCombination === "Ctrl+P" && !toggleView && !comparisonScene) {
setIsPlaying(true); setIsPlaying(true);
} }