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:
@@ -1,5 +1,5 @@
|
||||
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 { useEffect, useState } from "react";
|
||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
@@ -9,12 +9,14 @@ import ComparisonResult from "../../ui/compareVersion/ComparisonResult";
|
||||
import RegularDropDown from "../../ui/inputs/RegularDropDown";
|
||||
import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
type AssetData = {
|
||||
activeTime: number;
|
||||
idleTime: number;
|
||||
type: string;
|
||||
assetId: string;
|
||||
};
|
||||
|
||||
export interface CompareProduct {
|
||||
productUuid: string;
|
||||
productName: string;
|
||||
@@ -48,6 +50,7 @@ export interface CompareProduct {
|
||||
efficiencyScore?: number;
|
||||
};
|
||||
}
|
||||
|
||||
const calculateSimulationData = (assets: AssetData[]) => {
|
||||
let totalActiveTime = 0;
|
||||
let totalIdleTime = 0;
|
||||
@@ -111,6 +114,7 @@ export const createCompareProduct = (productUuid: string, productName: string, a
|
||||
productName,
|
||||
simulationData: calculateSimulationData(assets),
|
||||
});
|
||||
|
||||
function ComparisonScene() {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { productStore, versionStore } = useSceneContext();
|
||||
@@ -118,13 +122,11 @@ function ComparisonScene() {
|
||||
const { products, selectedProduct } = productStore();
|
||||
const { isComparing } = useIsComparing();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||
const { mainProduct } = useMainProduct();
|
||||
const { mainScene, comparisonScene, setComparisonState } = useSimulationState();
|
||||
const { loadingProgress } = useLoadingProgress();
|
||||
const { projectId } = useParams();
|
||||
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||
const { setCompareProductsData } = useCompareProductDataStore();
|
||||
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
|
||||
console.log("shouldShowComparisonResult: ", shouldShowComparisonResult);
|
||||
|
||||
const handleSelectVersion = (option: string) => {
|
||||
const version = versionHistory.find((version) => version.versionName === option);
|
||||
@@ -135,8 +137,14 @@ function ComparisonScene() {
|
||||
|
||||
const handleSelectProduct = (option: string) => {
|
||||
const product = products.find((product) => product.productName === option);
|
||||
if (product) {
|
||||
setComparisonProduct(product.productUuid, product.productName);
|
||||
if (product && selectedVersion) {
|
||||
const data = {
|
||||
productUuid: product.productUuid,
|
||||
productName: product.productName,
|
||||
versionUuid: selectedVersion.versionId,
|
||||
versionName: selectedVersion.versionName,
|
||||
};
|
||||
setComparisonState(data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,16 +164,15 @@ function ComparisonScene() {
|
||||
|
||||
useEffect(() => {
|
||||
// const selectedProductData = getProductById(selectedProduct.productUuid);
|
||||
if (mainProduct && comparisonProduct && selectedVersion) {
|
||||
const product1 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, mainProduct.productUuid);
|
||||
if (mainScene && comparisonScene && selectedVersion) {
|
||||
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 compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonProduct.productName, product2?.simulateData || []);
|
||||
const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainScene.product.productName, product1?.simulateData || []);
|
||||
const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonScene.product.productName, product2?.simulateData || []);
|
||||
|
||||
const comparedArray = [compareProduct1, compareProduct2];
|
||||
console.log("comparedArray: ", comparedArray);
|
||||
|
||||
if (product1 === undefined || product2 === undefined) {
|
||||
setShouldShowComparisonResult(false);
|
||||
@@ -176,7 +183,7 @@ function ComparisonScene() {
|
||||
} else {
|
||||
setShouldShowComparisonResult(false);
|
||||
}
|
||||
}, [mainProduct, comparisonProduct, selectedVersion, projectId, setCompareProductsData]);
|
||||
}, [mainScene, comparisonScene, selectedVersion, projectId, setCompareProductsData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore"
|
||||
import { useFloatingWidget } from "../../../store/visualization/useDroppedObjectsStore";
|
||||
import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore";
|
||||
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 { useBuilderStore } from "../../../store/builder/useBuilderStore";
|
||||
import useRestStates from "../../../hooks/useResetStates";
|
||||
@@ -35,7 +35,7 @@ import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/
|
||||
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
|
||||
|
||||
function MainScene() {
|
||||
const { setMainProduct } = useMainProduct();
|
||||
const { setMainState, clearComparisonState } = useSimulationState();
|
||||
const { isComparing, setIsComparing } = useIsComparing();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { selectedUser } = useSelectedUserStore();
|
||||
@@ -46,7 +46,6 @@ function MainScene() {
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const { selectedZone } = useSelectedZoneStore();
|
||||
const { setFloatingWidget } = useFloatingWidget();
|
||||
const { clearComparisonProduct } = useComparisonProduct();
|
||||
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
|
||||
const { assetStore, productStore, versionStore } = useSceneContext();
|
||||
const { products, selectedProduct } = productStore();
|
||||
@@ -62,14 +61,15 @@ function MainScene() {
|
||||
return () => {
|
||||
resetStates();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== "simulation") {
|
||||
clearComparisonProduct();
|
||||
clearComparisonState();
|
||||
setIsComparing(false);
|
||||
}
|
||||
}, [activeModule, clearComparisonProduct, setIsComparing]);
|
||||
}, [activeModule, clearComparisonState, setIsComparing]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
@@ -120,8 +120,14 @@ function MainScene() {
|
||||
|
||||
const handleSelectProduct = (option: string) => {
|
||||
const product = products.find((product) => product.productName === option);
|
||||
if (product) {
|
||||
setMainProduct(product.productUuid, product.productName);
|
||||
if (product && selectedVersion) {
|
||||
const data = {
|
||||
productUuid: product.productUuid,
|
||||
productName: product.productName,
|
||||
versionUuid: selectedVersion.versionId,
|
||||
versionName: selectedVersion.versionName,
|
||||
};
|
||||
setMainState(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||
|
||||
interface SimulationData {
|
||||
key: string;
|
||||
data?: object | any;
|
||||
@@ -28,6 +29,7 @@ interface ProjectSimulation {
|
||||
projectId: string | undefined;
|
||||
versions: VersionSimulation[];
|
||||
}
|
||||
|
||||
export const saveSimulationData = async (data: any) => {
|
||||
try {
|
||||
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) => {
|
||||
console.log("data: update", data);
|
||||
// console.log("data: update", data);
|
||||
try {
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/V1/ValidateSimulated`, {
|
||||
method: "POST",
|
||||
@@ -91,18 +94,25 @@ export const updateSimulateData = async (data: any) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
export const getSimulationData = async (projectId: string, versionId: string, productUuid: string) => {
|
||||
console.log("called");
|
||||
export const getSimulationData = async (
|
||||
projectId: string,
|
||||
versionId: string,
|
||||
productUuid: string
|
||||
) => {
|
||||
// console.log("called");
|
||||
try {
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/V1/SimulatedDatas/${projectId}/${versionId}?productUuid=${productUuid}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: "Bearer <access_token>",
|
||||
"Content-Type": "application/json",
|
||||
token: localStorage.getItem("token") || "",
|
||||
refresh_token: localStorage.getItem("refreshToken") || "",
|
||||
},
|
||||
});
|
||||
const response = await fetch(
|
||||
`${url_Backend_dwinzo}/api/V1/SimulatedDatas/${projectId}/${versionId}?productUuid=${productUuid}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: "Bearer <access_token>",
|
||||
"Content-Type": "application/json",
|
||||
token: localStorage.getItem("token") || "",
|
||||
refresh_token: localStorage.getItem("refreshToken") || "",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
console.log("response: ", response);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||
import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
|
||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||
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 RenderOverlay from "../../../templates/Overlay";
|
||||
import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
|
||||
@@ -17,8 +17,7 @@ import { useCompareStore, useIsComparing, useSimulateId } from "../../../../stor
|
||||
import { useToggleStore } from "../../../../store/ui/useUIToggleStore";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useSceneContext } from "../../../../modules/scene/sceneContext";
|
||||
import { getSimulationData, updateSimulateData } from "../../scenes/functions/simulationStorage";
|
||||
import { get } from "http";
|
||||
import { updateSimulateData } from "../../scenes/functions/simulationStorage";
|
||||
|
||||
interface Event {
|
||||
modelName: string;
|
||||
@@ -35,7 +34,7 @@ const Simulations: React.FC = () => {
|
||||
const [processes, setProcesses] = useState<Event[][]>();
|
||||
const { setToggleUI } = useToggleStore();
|
||||
const { projectId } = useParams();
|
||||
const { setMainProduct } = useMainProduct();
|
||||
const { setMainState, clearMainState } = useSimulationState();
|
||||
const { selectedVersion } = versionStore();
|
||||
const { comparePopUp, setComparePopUp } = useCompareStore();
|
||||
const { setIsComparing } = useIsComparing();
|
||||
@@ -51,7 +50,6 @@ const Simulations: React.FC = () => {
|
||||
productUuid: selectedProduct?.productUuid || "",
|
||||
simulatedId: simulateId,
|
||||
};
|
||||
console.log("singleData: ", singleData);
|
||||
const getData = await updateSimulateData(singleData);
|
||||
echo.log(getData.message);
|
||||
};
|
||||
@@ -74,17 +72,23 @@ const Simulations: React.FC = () => {
|
||||
|
||||
const updatedProducts = products.filter((p) => p.productUuid !== productUuid);
|
||||
|
||||
if (isSelected) {
|
||||
if (isSelected && selectedVersion) {
|
||||
if (updatedProducts.length > 0) {
|
||||
let newSelectedIndex = currentIndex;
|
||||
if (currentIndex >= updatedProducts.length) {
|
||||
newSelectedIndex = updatedProducts.length - 1;
|
||||
}
|
||||
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 {
|
||||
setSelectedProduct("", "");
|
||||
setMainProduct("", "");
|
||||
clearMainState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,9 +103,15 @@ const Simulations: React.FC = () => {
|
||||
const handleRenameProduct = (productUuid: string, newName: string) => {
|
||||
renameProduct(productUuid, newName);
|
||||
renameProductApi({ productName: newName, productUuid, projectId: projectId || "", versionId: selectedVersion?.versionId || "" });
|
||||
if (selectedProduct.productUuid === productUuid) {
|
||||
if (selectedProduct.productUuid === productUuid && selectedVersion) {
|
||||
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]);
|
||||
//call when comparePopup is true
|
||||
|
||||
useEffect(() => {
|
||||
if (comparePopUp || selectedProduct.productUuid) {
|
||||
}
|
||||
@@ -173,8 +183,16 @@ const Simulations: React.FC = () => {
|
||||
<div
|
||||
className="value"
|
||||
onClick={() => {
|
||||
setSelectedProduct(product.productUuid, product.productName);
|
||||
setMainProduct(product.productUuid, product.productName);
|
||||
if (selectedVersion) {
|
||||
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 />
|
||||
|
||||
@@ -4,79 +4,75 @@ import { LogoIconLarge } from "../icons/Logo";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useProjectName } from "../../store/builder/store";
|
||||
import { getAllProjects } from "../../services/dashboard/getAllProjects";
|
||||
import { useComparisonProduct } from "../../store/simulation/useSimulationStore";
|
||||
import { useSimulationState } from "../../store/simulation/useSimulationStore";
|
||||
import { getUserData } from "../../functions/getUserData";
|
||||
import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject";
|
||||
|
||||
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 { projectName, setProjectName } = useProjectName();
|
||||
const { projectId } = useParams();
|
||||
const { comparisonProduct } = useComparisonProduct();
|
||||
const { userId, organization } = getUserData();
|
||||
const { projectName, setProjectName } = useProjectName();
|
||||
const { projectId } = useParams();
|
||||
const { comparisonScene } = useSimulationState();
|
||||
const { userId, organization } = getUserData();
|
||||
|
||||
const validatedProgress = Math.min(100, Math.max(0, progress));
|
||||
useEffect(() => {
|
||||
if (!userId) {
|
||||
console.error("User data not found in localStorage");
|
||||
return;
|
||||
}
|
||||
const validatedProgress = Math.min(100, Math.max(0, progress));
|
||||
|
||||
const fetchProjects = async () => {
|
||||
try {
|
||||
const projects = await getAllProjects(userId, organization);
|
||||
const shared = await sharedWithMeProjects();
|
||||
|
||||
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);
|
||||
useEffect(() => {
|
||||
if (!userId) {
|
||||
console.error("User data not found in localStorage");
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching projects:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchProjects();
|
||||
}, []);
|
||||
const fetchProjects = async () => {
|
||||
try {
|
||||
const projects = await getAllProjects(userId, organization);
|
||||
const shared = await sharedWithMeProjects();
|
||||
|
||||
return (
|
||||
<RenderOverlay>
|
||||
<div
|
||||
className={`loading-wrapper ${comparisonProduct != null ? "comparisionLoading" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="loading-container">
|
||||
<div className="project-name">{projectName}</div>
|
||||
<div className="loading-hero-container">
|
||||
<div className="logo">
|
||||
<LogoIconLarge />
|
||||
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();
|
||||
// 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 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>
|
||||
</RenderOverlay>
|
||||
);
|
||||
</RenderOverlay>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingPage;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useParams } from "react-router-dom";
|
||||
import React, { useState, useRef, useEffect, Suspense } from "react";
|
||||
import { CompareLayoutIcon, LayoutIcon, ResizerIcon } from "../../icons/SimulationIcons";
|
||||
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 { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
|
||||
@@ -14,7 +14,7 @@ import useRestStates from "../../../hooks/useResetStates";
|
||||
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
|
||||
|
||||
const CompareLayOut = () => {
|
||||
const { clearComparisonProduct, comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||
const { clearComparisonState, comparisonScene, setComparisonState } = useSimulationState();
|
||||
const { versionStore } = useSceneContext();
|
||||
const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion, setVersions } = versionStore();
|
||||
const { setLoadingProgress } = useLoadingProgress();
|
||||
@@ -32,11 +32,10 @@ const CompareLayOut = () => {
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (selectedVersion?.versionId) {
|
||||
resetStates();
|
||||
}
|
||||
resetStates();
|
||||
};
|
||||
}, [selectedVersion?.versionId]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
@@ -63,10 +62,10 @@ const CompareLayOut = () => {
|
||||
}, [projectId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!comparisonProduct) {
|
||||
if (!comparisonScene) {
|
||||
clearSelectedVersion();
|
||||
}
|
||||
}, [comparisonProduct]);
|
||||
}, [comparisonScene]);
|
||||
|
||||
OuterClick({
|
||||
contextClassName: ["displayLayouts-container", "selectLayout"],
|
||||
@@ -108,7 +107,7 @@ const CompareLayOut = () => {
|
||||
if (finalWidthVw <= 10) {
|
||||
setWidth("0px");
|
||||
setIsComparing(false);
|
||||
clearComparisonProduct();
|
||||
clearComparisonState();
|
||||
setIsPlaying(false);
|
||||
} else {
|
||||
setWidth(`${finalWidthVw}vw`);
|
||||
@@ -154,7 +153,13 @@ const CompareLayOut = () => {
|
||||
getAllProductsApi(projectId || "", version.versionId || "").then((data) => {
|
||||
if (data && data.length > 0) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import PerformanceResult from "./result-card/PerformanceResult";
|
||||
import EnergyUsage from "./result-card/EnergyUsage";
|
||||
import { Bar, Line, Pie } from "react-chartjs-2";
|
||||
import { Bar, Pie } from "react-chartjs-2";
|
||||
import { useCompareProductDataStore } from "../../../store/builder/store";
|
||||
// import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store";
|
||||
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
|
||||
export interface CompareProduct {
|
||||
productUuid: string;
|
||||
productName: string;
|
||||
@@ -21,16 +20,16 @@ export interface CompareProduct {
|
||||
efficiencyScore?: number;
|
||||
};
|
||||
}
|
||||
|
||||
const ComparisonResult = () => {
|
||||
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||
const { mainProduct } = useMainProduct();
|
||||
const { compareProductsData } = useCompareProductDataStore();
|
||||
const { comparisonScene, mainScene } = useSimulationState();
|
||||
const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (compareProductsData.length > 0 && mainProduct && comparisonProduct) {
|
||||
const mainProductData = compareProductsData.find((product) => product.productUuid === mainProduct.productUuid);
|
||||
const comparisonProductData = compareProductsData.find((product) => product.productUuid === comparisonProduct.productUuid);
|
||||
if (compareProductsData.length > 0 && comparisonScene && mainScene) {
|
||||
const mainProductData = compareProductsData.find((product) => product.productUuid === mainScene.product.productUuid);
|
||||
const comparisonProductData = compareProductsData.find((product) => product.productUuid === comparisonScene.product.productUuid);
|
||||
|
||||
if (mainProductData && comparisonProductData) {
|
||||
setComparedProducts([mainProductData, comparisonProductData]);
|
||||
@@ -40,7 +39,7 @@ const ComparisonResult = () => {
|
||||
} else {
|
||||
setComparedProducts([]);
|
||||
}
|
||||
}, [compareProductsData, mainProduct, comparisonProduct]);
|
||||
}, [compareProductsData, comparisonScene, mainScene]);
|
||||
|
||||
useEffect(() => {
|
||||
if (comparedProducts.length === 2) {
|
||||
|
||||
@@ -1,464 +1,391 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
||||
import {
|
||||
comparsionMaterialData,
|
||||
useActiveTool,
|
||||
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 { comparsionMaterialData, useActiveTool, 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 useModuleStore, {
|
||||
useSubModuleStore,
|
||||
} from "../../../store/ui/useModuleStore";
|
||||
import useModuleStore, { useSubModuleStore } from "../../../store/ui/useModuleStore";
|
||||
import ProductionCapacity from "../analysis/ThroughputSummary";
|
||||
import ThroughputSummary from "../analysis/ProductionCapacity";
|
||||
import ROISummary from "../analysis/ROISummary";
|
||||
import { usePlayerStore } from "../../../store/ui/useUIToggleStore";
|
||||
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
import InputToggle from "../inputs/InputToggle";
|
||||
import { saveSimulationData } from "../../layout/scenes/functions/simulationStorage";
|
||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
|
||||
const SimulationPlayer: React.FC = () => {
|
||||
const MAX_SPEED = 8; // Maximum speed
|
||||
const MAX_SPEED = 8; // Maximum speed
|
||||
|
||||
const isDragging = useRef(false);
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
const [expand, setExpand] = useState(true);
|
||||
const { hidePlayer, setHidePlayer } = usePlayerStore();
|
||||
const isDragging = useRef(false);
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
const [expand, setExpand] = useState(true);
|
||||
const { hidePlayer, setHidePlayer } = usePlayerStore();
|
||||
|
||||
const { speed, setSpeed } = useAnimationPlaySpeed();
|
||||
const { setIsPlaying } = usePlayButtonStore();
|
||||
const { setActiveTool } = useActiveTool();
|
||||
const { isPaused, setIsPaused } = usePauseButtonStore();
|
||||
const { isReset, setReset } = useResetButtonStore();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { clearComparisonProduct } = useComparisonProduct();
|
||||
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
||||
const { materialData, setMaterialData } = comparsionMaterialData()
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { productStore } = useSceneContext();
|
||||
const { selectedProduct, setSelectedProduct } = productStore();
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
setTimeout(() => {
|
||||
setReset(false);
|
||||
}, 0);
|
||||
}
|
||||
}, [isReset, setReset]);
|
||||
const { speed, setSpeed } = useAnimationPlaySpeed();
|
||||
const { setIsPlaying } = usePlayButtonStore();
|
||||
const { setActiveTool } = useActiveTool();
|
||||
const { isPaused, setIsPaused } = usePauseButtonStore();
|
||||
const { isReset, setReset } = useResetButtonStore();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { clearComparisonState } = useSimulationState();
|
||||
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
||||
const { materialData } = comparsionMaterialData();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (materialData.length === 0) return;
|
||||
console.log('materialData: ', materialData);
|
||||
// saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
|
||||
}, [materialData])
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
setTimeout(() => {
|
||||
setReset(false);
|
||||
}, 0);
|
||||
}
|
||||
}, [isReset, setReset]);
|
||||
|
||||
// Button functions
|
||||
const handleReset = () => {
|
||||
setReset(true);
|
||||
setIsPaused(false);
|
||||
setSpeed(1);
|
||||
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");
|
||||
};
|
||||
useEffect(() => {
|
||||
if (materialData.length === 0) return;
|
||||
// console.log("materialData: ", materialData);
|
||||
// saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
|
||||
}, [materialData]);
|
||||
|
||||
// Slider functions starts
|
||||
const handleSpeedChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSpeed(parseFloat(event.target.value));
|
||||
};
|
||||
|
||||
const calculateHandlePosition = () => {
|
||||
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)}%`);
|
||||
// Button functions
|
||||
const handleReset = () => {
|
||||
setReset(true);
|
||||
setIsPaused(false);
|
||||
setSpeed(1);
|
||||
echo.info("Simulation RESET.....");
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
const handlePlayStop = () => {
|
||||
setIsPaused(!isPaused);
|
||||
if (isPaused) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
|
||||
};
|
||||
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
};
|
||||
const handleExit = () => {
|
||||
setIsPlaying(false);
|
||||
setIsPaused(false);
|
||||
clearComparisonState();
|
||||
setActiveTool("cursor");
|
||||
echo.info("Exit Simulation");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{isPlaying && activeModule === "simulation" && (
|
||||
<div className="label-toogler "> {/* bottom */}
|
||||
<InputToggle
|
||||
value={viewSceneLabels}
|
||||
inputKey="1"
|
||||
label="Enable View Labels"
|
||||
onClick={() => setViewSceneLabels(!viewSceneLabels)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={`simulation-player-wrapper${hidePlayer ? " hide" : ""}`}>
|
||||
<div className={`simulation-player-container ${expand ? "open" : ""}`}>
|
||||
<div className="controls-container">
|
||||
{!hidePlayer && subModule === "analysis" && (
|
||||
<div className="production-details">
|
||||
{/* hourlySimulation */}
|
||||
<div className="hourly-wrapper production-wrapper">
|
||||
<div className="header">
|
||||
<div className="icon">
|
||||
<HourlySimulationIcon />
|
||||
</div>
|
||||
<h4 className="label">ThroughPut</h4>
|
||||
</div>
|
||||
<div className="progress-wrapper">
|
||||
<div
|
||||
className="progress"
|
||||
style={{ width: hourlySimulation }}
|
||||
></div>
|
||||
</div>
|
||||
// Slider functions starts
|
||||
const handleSpeedChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSpeed(parseFloat(event.target.value));
|
||||
};
|
||||
|
||||
const calculateHandlePosition = () => {
|
||||
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 = () => {
|
||||
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>
|
||||
{/* 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="header">
|
||||
<InfoIcon />
|
||||
{isPaused ? "Paused - system idle." : "Running simulation..."}
|
||||
</div>
|
||||
)}
|
||||
<div className="controls-wrapper">
|
||||
{!hidePlayer && (
|
||||
<button
|
||||
id="simulation-reset-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
handleReset();
|
||||
}}
|
||||
>
|
||||
<ResetIcon />
|
||||
Reset
|
||||
</button>
|
||||
)}
|
||||
{!hidePlayer && (
|
||||
<button
|
||||
id="simulation-play-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
handlePlayStop();
|
||||
}}
|
||||
>
|
||||
<PlayStopIcon />
|
||||
{isPaused ? "Play" : "Stop"}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
id="simulation-reset-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
handleExit();
|
||||
}}
|
||||
>
|
||||
<ExitIcon />
|
||||
{!hidePlayer && "Exit"}
|
||||
</button>
|
||||
<button
|
||||
id="simulation-reset-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
setHidePlayer(!hidePlayer);
|
||||
}}
|
||||
>
|
||||
<EyeCloseIcon />
|
||||
{!hidePlayer && "Hide"}
|
||||
</button>
|
||||
{subModule === "analysis" && (
|
||||
<button
|
||||
id="simulation-expand-button"
|
||||
className="expand-icon-container"
|
||||
onClick={() => setExpand(!expand)}
|
||||
>
|
||||
<ExpandIcon isActive={!expand} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{!hidePlayer && (
|
||||
<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 className={`simulation-player-wrapper${hidePlayer ? " hide" : ""}`}>
|
||||
<div className={`simulation-player-container ${expand ? "open" : ""}`}>
|
||||
<div className="controls-container">
|
||||
{!hidePlayer && subModule === "analysis" && (
|
||||
<div className="production-details">
|
||||
{/* hourlySimulation */}
|
||||
<div className="hourly-wrapper production-wrapper">
|
||||
<div className="header">
|
||||
<div className="icon">
|
||||
<HourlySimulationIcon />
|
||||
</div>
|
||||
<h4 className="label">ThroughPut</h4>
|
||||
</div>
|
||||
<div className="progress-wrapper">
|
||||
<div className="progress" style={{ width: hourlySimulation }}></div>
|
||||
</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="header">
|
||||
<InfoIcon />
|
||||
{isPaused ? "Paused - system idle." : "Running simulation..."}
|
||||
</div>
|
||||
)}
|
||||
<div className="controls-wrapper">
|
||||
{!hidePlayer && (
|
||||
<button
|
||||
id="simulation-reset-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
handleReset();
|
||||
}}
|
||||
>
|
||||
<ResetIcon />
|
||||
Reset
|
||||
</button>
|
||||
)}
|
||||
{!hidePlayer && (
|
||||
<button
|
||||
id="simulation-play-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
handlePlayStop();
|
||||
}}
|
||||
>
|
||||
<PlayStopIcon />
|
||||
{isPaused ? "Play" : "Stop"}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
id="simulation-reset-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
handleExit();
|
||||
}}
|
||||
>
|
||||
<ExitIcon />
|
||||
{!hidePlayer && "Exit"}
|
||||
</button>
|
||||
<button
|
||||
id="simulation-reset-button"
|
||||
className="simulation-button-container"
|
||||
onClick={() => {
|
||||
setHidePlayer(!hidePlayer);
|
||||
}}
|
||||
>
|
||||
<EyeCloseIcon />
|
||||
{!hidePlayer && "Hide"}
|
||||
</button>
|
||||
{subModule === "analysis" && (
|
||||
<button id="simulation-expand-button" className="expand-icon-container" onClick={() => setExpand(!expand)}>
|
||||
<ExpandIcon isActive={!expand} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="speed-label max-value">{MAX_SPEED}x</div>
|
||||
</div>
|
||||
{!hidePlayer && (
|
||||
<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>
|
||||
)}
|
||||
{!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>
|
||||
)}
|
||||
{/* {subModule === "analysis" && ( */}
|
||||
{subModule === "analysis" && (
|
||||
<div className="analysis">
|
||||
<div className="analysis-wrapper">
|
||||
<ProductionCapacity />
|
||||
<ThroughputSummary />
|
||||
</div>
|
||||
<ROISummary />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* {subModule === "analysis" && ( */}
|
||||
{subModule === "analysis" && (
|
||||
<div className="analysis">
|
||||
<div className="analysis-wrapper">
|
||||
<ProductionCapacity />
|
||||
<ThroughputSummary />
|
||||
</div>
|
||||
<ROISummary />
|
||||
</div>
|
||||
)}
|
||||
{/* )} */}
|
||||
</>
|
||||
);
|
||||
)}
|
||||
{/* )} */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SimulationPlayer;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CameraControls } from "@react-three/drei";
|
||||
import { useSceneContext } from "../sceneContext";
|
||||
import { useIsComparing } from "../../../store/builder/store";
|
||||
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 * as CONSTANTS from "../../../types/world/worldConstants";
|
||||
@@ -14,7 +14,7 @@ function SyncCam() {
|
||||
const { controls } = useThree();
|
||||
const { isComparing } = useIsComparing();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { comparisonProduct } = useComparisonProduct();
|
||||
const { comparisonScene } = useSimulationState();
|
||||
const { setCamera, camState } = useSceneStore();
|
||||
|
||||
useFrame(() => {
|
||||
@@ -25,7 +25,7 @@ function SyncCam() {
|
||||
(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);
|
||||
}
|
||||
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 target = (controls as CameraControls).getTarget(new Vector3());
|
||||
setCamera(position, target);
|
||||
|
||||
@@ -4,13 +4,12 @@ import { upsertProductOrEventApi } from "../../../services/simulation/products/U
|
||||
import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
|
||||
import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
|
||||
import { useSceneContext } from "../../scene/sceneContext";
|
||||
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
function Products() {
|
||||
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, layout, productStore, versionStore } = useSceneContext();
|
||||
const { products, getProductById, addProduct, setProducts, selectedProduct, setSelectedProduct } = productStore();
|
||||
const { setMainProduct } = useMainProduct();
|
||||
const { addVehicle, clearVehicles } = vehicleStore();
|
||||
const { addArmBot, clearArmBots } = armBotStore();
|
||||
const { addMachine, clearMachines } = machineStore();
|
||||
@@ -20,26 +19,25 @@ function Products() {
|
||||
const { addCrane, addCurrentAction: addCurrentActionCrane, clearCranes } = craneStore();
|
||||
const { isReset } = useResetButtonStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { mainProduct } = useMainProduct();
|
||||
const { comparisonProduct } = useComparisonProduct();
|
||||
const { setMainState, mainScene, comparisonScene } = useSimulationState();
|
||||
const { selectedVersion } = versionStore();
|
||||
const { projectId } = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
if (layout === "Main Layout" && mainProduct) {
|
||||
setSelectedProduct(mainProduct.productUuid, mainProduct.productName);
|
||||
if (layout === "Main Layout" && mainScene) {
|
||||
setSelectedProduct(mainScene.product.productUuid, mainScene.product.productName);
|
||||
}
|
||||
}, [mainProduct]);
|
||||
}, [mainScene, layout]);
|
||||
|
||||
useEffect(() => {
|
||||
if (layout === "Comparison Layout" && comparisonProduct) {
|
||||
setSelectedProduct(comparisonProduct.productUuid, comparisonProduct.productName);
|
||||
if (layout === "Comparison Layout" && comparisonScene) {
|
||||
setSelectedProduct(comparisonScene.product.productUuid, comparisonScene.product.productName);
|
||||
}
|
||||
}, [comparisonProduct]);
|
||||
}, [comparisonScene, layout]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedVersion) return;
|
||||
getAllProductsApi(projectId || "", selectedVersion?.versionId || "")
|
||||
getAllProductsApi(projectId || "", selectedVersion.versionId)
|
||||
.then((data) => {
|
||||
if (data && data.length === 0) {
|
||||
const id = THREE.MathUtils.generateUUID();
|
||||
@@ -49,17 +47,29 @@ function Products() {
|
||||
productName: name,
|
||||
productUuid: id,
|
||||
projectId: projectId || "",
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
versionId: selectedVersion.versionId,
|
||||
});
|
||||
if (layout === "Main Layout") {
|
||||
if (layout === "Main Layout" && selectedVersion) {
|
||||
setSelectedProduct(id, name);
|
||||
setMainProduct(id, name);
|
||||
const mainData = {
|
||||
productUuid: id,
|
||||
productName: name,
|
||||
versionUuid: selectedVersion.versionId,
|
||||
versionName: selectedVersion.versionName,
|
||||
};
|
||||
setMainState(mainData);
|
||||
}
|
||||
} else {
|
||||
setProducts(data);
|
||||
if (layout === "Main Layout") {
|
||||
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);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -108,7 +108,7 @@ export function useCheckActiveRoboticArmsInSubsequence() {
|
||||
}
|
||||
|
||||
// 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 allPoints: PointsScheme[] = [];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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 allPoints: PointsScheme[] = [];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { extractTriggersFromPoint } from "./extractTriggersFromPoint";
|
||||
|
||||
export function determineExecutionOrder(products: productsSchema): Action[] {
|
||||
export function determineExecutionOrder(products: ProductsSchema): Action[] {
|
||||
// Create maps for all events and points
|
||||
const pointMap = new Map<string, PointsScheme>();
|
||||
const allPoints: PointsScheme[] = [];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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
|
||||
const pointMap = new Map<string, PointsScheme>();
|
||||
const allPoints: PointsScheme[] = [];
|
||||
|
||||
@@ -75,7 +75,7 @@ export function findConveyorSubsequence(
|
||||
}
|
||||
|
||||
// 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 allPoints: PointsScheme[] = [];
|
||||
|
||||
|
||||
@@ -5,7 +5,10 @@ import { determineExecutionOrder } from "./functions/determineExecutionOrder";
|
||||
import { useSceneContext } from "../../scene/sceneContext";
|
||||
import SimulationHandler from "./SimulationHandler";
|
||||
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 { useSimulateId } from "../../../store/builder/store";
|
||||
|
||||
@@ -32,18 +35,23 @@ function Simulator() {
|
||||
handleAction(action);
|
||||
});
|
||||
}, [products, isPlaying, isReset, selectedProduct]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectId || !selectedVersion || !selectedProduct?.productUuid) return;
|
||||
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);
|
||||
if (!product) return;
|
||||
const products: productsSchema = [product];
|
||||
const products: ProductsSchema = [product];
|
||||
const getSimulate = getData?.data;
|
||||
console.log("getSimulate: ", getSimulate);
|
||||
// console.log("getSimulate: ", getSimulate);
|
||||
if (getData && getSimulate && getSimulate.productTimestamp === products[0]?.timestamp) {
|
||||
setSimulateId(getSimulate._id);
|
||||
console.log(" getSimulate.data: ", getSimulate.data);
|
||||
// console.log(" getSimulate.data: ", getSimulate.data);
|
||||
addSimulationRecords(
|
||||
projectId,
|
||||
selectedVersion?.versionId || "",
|
||||
@@ -58,15 +66,22 @@ function Simulator() {
|
||||
projectId: projectId,
|
||||
versionId: selectedVersion.versionId,
|
||||
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);
|
||||
console.log("simulations: ", simulations);
|
||||
// console.log("simulations: ", simulations);
|
||||
echo.log("Simulation data saved successfully");
|
||||
}
|
||||
};
|
||||
fetchSimulateData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <simulationHandler/> */}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { create } from "zustand";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
type ProductsStore = {
|
||||
products: productsSchema;
|
||||
products: ProductsSchema;
|
||||
selectedProduct: { productUuid: string; productName: string };
|
||||
|
||||
setSelectedProduct: (productUuid: string, productName: string) => void;
|
||||
@@ -10,7 +10,7 @@ type ProductsStore = {
|
||||
|
||||
// Product-level actions
|
||||
addProduct: (productName: string, productUuid: string) => void;
|
||||
setProducts: (products: productsSchema) => void;
|
||||
setProducts: (products: ProductsSchema) => void;
|
||||
clearProducts: () => void;
|
||||
removeProduct: (productUuid: string) => void;
|
||||
updateProduct: (productUuid: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import * as THREE from 'three';
|
||||
import { create } from "zustand";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
import * as THREE from "three";
|
||||
|
||||
interface SelectedEventSphereState {
|
||||
selectedEventSphere: THREE.Mesh | null;
|
||||
@@ -120,15 +120,9 @@ interface SelectedAnimationState {
|
||||
animationName: string;
|
||||
animationType: "behaviour" | "animatedTravel";
|
||||
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;
|
||||
setSelectedAnimation: (animation: {
|
||||
animationUuid: string;
|
||||
animationName: string;
|
||||
animationType: "behaviour" | "animatedTravel";
|
||||
animation: string | null;
|
||||
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
||||
}) => void;
|
||||
setSelectedAnimation: (animation: { animationUuid: string; animationName: string; animationType: "behaviour" | "animatedTravel"; animation: string | null; travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null } }) => void;
|
||||
clearSelectedAnimation: () => void;
|
||||
}
|
||||
|
||||
@@ -180,45 +174,55 @@ export const useIsRotating = create<IsRotatingState>()(
|
||||
}))
|
||||
);
|
||||
|
||||
interface MainProductState {
|
||||
mainProduct: { productUuid: string; productName: string } | null;
|
||||
setMainProduct: (productUuid: string, productName: string) => void;
|
||||
clearMainProduct: () => void;
|
||||
interface SimulationState {
|
||||
mainScene: {
|
||||
product: { productUuid: string; productName: string };
|
||||
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) => ({
|
||||
mainProduct: null,
|
||||
setMainProduct: (productUuid: string, productName: string) => {
|
||||
mainScene: {
|
||||
product: { productUuid: "", productName: "" },
|
||||
version: { versionUuid: "", versionName: "" },
|
||||
},
|
||||
comparisonScene: null,
|
||||
setMainState: (mainScene) => {
|
||||
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) => {
|
||||
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;
|
||||
}
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
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) => {
|
||||
clearMainState: () => {
|
||||
set((state) => {
|
||||
state.comparisonProduct = { productUuid, productName };
|
||||
state.mainScene.product = { productUuid: "", productName: "" };
|
||||
state.mainScene.version = { versionUuid: "", versionName: "" };
|
||||
});
|
||||
},
|
||||
clearComparisonProduct: () => {
|
||||
clearComparisonState: () => {
|
||||
set((state) => {
|
||||
state.comparisonProduct = null;
|
||||
state.comparisonScene = null;
|
||||
});
|
||||
},
|
||||
}))
|
||||
@@ -242,14 +246,14 @@ export const useSelectedPoints = create<SelectedPointsState>()(
|
||||
},
|
||||
addSelectedPoint: (point) => {
|
||||
set((state) => {
|
||||
if (!state.selectedPoints.find(p => p.uuid === point.uuid)) {
|
||||
if (!state.selectedPoints.find((p) => p.uuid === point.uuid)) {
|
||||
state.selectedPoints.push(point);
|
||||
}
|
||||
});
|
||||
},
|
||||
removeSelectedPoint: (uuid) => {
|
||||
set((state) => {
|
||||
state.selectedPoints = state.selectedPoints.filter(p => p.uuid !== uuid);
|
||||
state.selectedPoints = state.selectedPoints.filter((p) => p.uuid !== uuid);
|
||||
});
|
||||
},
|
||||
clearSelectedPoints: () => {
|
||||
|
||||
2
app/src/types/simulationTypes.d.ts
vendored
2
app/src/types/simulationTypes.d.ts
vendored
@@ -400,7 +400,7 @@ type MaterialsSchema = MaterialSchema[];
|
||||
|
||||
// Products
|
||||
|
||||
type productsSchema = {
|
||||
type ProductsSchema = {
|
||||
productName: string;
|
||||
productUuid: string;
|
||||
eventDatas: EventsSchema[];
|
||||
|
||||
@@ -6,12 +6,12 @@ import useCameraModeStore, { usePlayButtonStore } from "../../store/ui/usePlayBu
|
||||
import { detectModifierKeys } from "./detectModifierKeys";
|
||||
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||
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 { useSceneContext } from "../../modules/scene/sceneContext";
|
||||
|
||||
const KeyPressListener: React.FC = () => {
|
||||
const { comparisonProduct, clearComparisonProduct } = useComparisonProduct();
|
||||
const { comparisonScene, clearComparisonState } = useSimulationState();
|
||||
const { activeModule, setActiveModule } = useModuleStore();
|
||||
const { assetStore, versionStore } = useSceneContext();
|
||||
const { selectedAssets } = assetStore();
|
||||
@@ -178,7 +178,7 @@ const KeyPressListener: React.FC = () => {
|
||||
clearSelectedZone();
|
||||
setShowShortcuts(false);
|
||||
setIsComparing(false);
|
||||
clearComparisonProduct();
|
||||
clearComparisonState();
|
||||
setIsLogListVisible(false);
|
||||
setIsRenameMode(false);
|
||||
setDfxUploaded([]);
|
||||
@@ -203,7 +203,7 @@ const KeyPressListener: React.FC = () => {
|
||||
handleBuilderShortcuts(keyCombination);
|
||||
|
||||
// Shortcut to enter play mode
|
||||
if (keyCombination === "Ctrl+P" && !toggleView && !comparisonProduct) {
|
||||
if (keyCombination === "Ctrl+P" && !toggleView && !comparisonScene) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user