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 { 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 (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 />
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -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[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -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[] = [];
|
||||||
|
|||||||
@@ -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[] = [];
|
||||||
|
|||||||
@@ -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[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -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/> */}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>()(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|||||||
2
app/src/types/simulationTypes.d.ts
vendored
2
app/src/types/simulationTypes.d.ts
vendored
@@ -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[];
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user