layout worked with backend
This commit is contained in:
@@ -27,6 +27,7 @@ export interface CompareProduct {
|
||||
simulationTime?: number;
|
||||
simulationCost?: number;
|
||||
efficiencyScore?: number;
|
||||
energyUsage?: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,6 +53,7 @@ const calculateSimulationData = (assets: AssetData[]) => {
|
||||
transfer: 20,
|
||||
storageUnit: 10,
|
||||
};
|
||||
const energyUsage = assets.filter((a) => a.type === "human").reduce((sum, a) => sum + a.activeTime * 1, 0);
|
||||
|
||||
assets.forEach((asset) => {
|
||||
totalActiveTime += asset.activeTime;
|
||||
@@ -90,6 +92,7 @@ const calculateSimulationData = (assets: AssetData[]) => {
|
||||
simulationTime,
|
||||
simulationCost,
|
||||
efficiencyScore,
|
||||
energyUsage,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -102,11 +105,13 @@ export const createCompareProduct = (productUuid: string, productName: string, a
|
||||
function ComparisonScene() {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { productStore } = useSceneContext();
|
||||
const { products } = productStore();
|
||||
const { products, getProductById } = productStore();
|
||||
const { isVersionSaved } = useSaveVersion();
|
||||
|
||||
const { activeModule } = useModuleStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
|
||||
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||
const { mainProduct } = useMainProduct();
|
||||
const { loadingProgress } = useLoadingProgress();
|
||||
@@ -171,15 +176,15 @@ function ComparisonScene() {
|
||||
|
||||
// useEffect(() => {
|
||||
|
||||
// console.log('mainProduct: ', mainProduct);
|
||||
// console.log('comparisonProduct: ', comparisonProduct);
|
||||
//
|
||||
//
|
||||
// if (mainProduct && comparisonProduct) {
|
||||
// // if (mainProduct && comparisonProduct && compareProductsData.length > 1) {
|
||||
// // console.log('compareProductsData: ', compareProductsData);
|
||||
// //
|
||||
// const hasMain = compareProductsData.some(val => val.productUuid === mainProduct.productUuid);
|
||||
// const hasComparison = compareProductsData.some(val => val.productUuid === comparisonProduct.productUuid);
|
||||
// console.log('hasMain: ', hasMain);
|
||||
// console.log('hasComparison: ', hasComparison);
|
||||
//
|
||||
//
|
||||
// if (hasMain && hasComparison) {
|
||||
// setShouldShowComparisonResult(true);
|
||||
// } else {
|
||||
@@ -189,20 +194,20 @@ function ComparisonScene() {
|
||||
// }, [compareProductsData, mainProduct, comparisonProduct]);
|
||||
|
||||
useEffect(() => {
|
||||
const selectedProductData = getProductById(selectedProduct.productUuid);
|
||||
if (mainProduct && comparisonProduct && selectedVersion) {
|
||||
const product1 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, mainProduct.productUuid);
|
||||
|
||||
const product2 = useSimulationManager.getState().getProductById(projectId, selectedVersion?.versionId, comparisonProduct.productUuid);
|
||||
|
||||
const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainProduct.productName, product1?.data || []);
|
||||
const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonProduct.productName, product2?.data || []);
|
||||
const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainProduct.productName, product1?.simulateData || []);
|
||||
const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonProduct.productName, product2?.simulateData || []);
|
||||
|
||||
const comparedArray = [compareProduct1, compareProduct2];
|
||||
|
||||
if (product1 == undefined || product2 === undefined) {
|
||||
setShouldShowComparisonResult(false);
|
||||
} else if (comparedArray.length === 2) {
|
||||
console.log("comparedArray: ", comparedArray);
|
||||
setCompareProductsData(comparedArray);
|
||||
setShouldShowComparisonResult(true);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ function MainScene() {
|
||||
const { assetStore, productStore } = useSceneContext();
|
||||
const { products } = productStore();
|
||||
const { setName, selectedAssets, setSelectedAssets } = assetStore();
|
||||
const { projectId } = useParams()
|
||||
const { projectId } = useParams();
|
||||
const { organization, userId } = getUserData();
|
||||
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
|
||||
const { versionHistory } = useVersionHistoryStore();
|
||||
@@ -66,15 +66,15 @@ function MainScene() {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
resetStates();
|
||||
}
|
||||
}, [])
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== 'simulation') {
|
||||
if (activeModule !== "simulation") {
|
||||
clearComparisonProduct();
|
||||
setIsVersionSaved(false);
|
||||
}
|
||||
}, [activeModule, clearComparisonProduct, setIsVersionSaved])
|
||||
}, [activeModule, clearComparisonProduct, setIsVersionSaved]);
|
||||
|
||||
useEffect(() => {
|
||||
if (versionHistory.length > 0 && organization && userId) {
|
||||
@@ -88,9 +88,9 @@ function MainScene() {
|
||||
} else {
|
||||
setSelectedVersion(versionHistory[0]);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}, [setSelectedVersion, versionHistory, projectId])
|
||||
}, [setSelectedVersion, versionHistory, projectId]);
|
||||
|
||||
const handleSelectVersion = (option: string) => {
|
||||
const version = versionHistory.find((version) => version.versionName === option);
|
||||
@@ -107,33 +107,33 @@ function MainScene() {
|
||||
};
|
||||
|
||||
const handleObjectRename = async (newName: string) => {
|
||||
if (!projectId) return
|
||||
if (!projectId) return;
|
||||
if (selectedFloorAsset) {
|
||||
setAssetsApi({
|
||||
modelUuid: selectedFloorAsset.userData.modelUuid,
|
||||
modelName: newName,
|
||||
projectId,
|
||||
versionId: selectedVersion?.versionId || ''
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
}).then(() => {
|
||||
selectedFloorAsset.userData = { ...selectedFloorAsset.userData, modelName: newName };
|
||||
setSelectedFloorAsset(selectedFloorAsset);
|
||||
setIsRenameMode(false);
|
||||
setName(selectedFloorAsset.userData.modelUuid, newName);
|
||||
})
|
||||
});
|
||||
} else if (selectedAssets.length === 1) {
|
||||
setAssetsApi({
|
||||
modelUuid: selectedAssets[0].userData.modelUuid,
|
||||
modelName: newName,
|
||||
projectId,
|
||||
versionId: selectedVersion?.versionId || ''
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
}).then(() => {
|
||||
selectedAssets[0].userData = { ...selectedAssets[0].userData, modelName: newName };
|
||||
setSelectedAssets(selectedAssets);
|
||||
setIsRenameMode(false);
|
||||
setName(selectedAssets[0].userData.modelUuid, newName);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -150,11 +150,9 @@ function MainScene() {
|
||||
)}
|
||||
<RealTimeVisulization />
|
||||
{activeModule === "market" && <MarketPlace />}
|
||||
{activeModule !== "market" && !isPlaying && !isVersionSaved && (
|
||||
<Tools />
|
||||
)}
|
||||
{(isPlaying) && activeModule === "simulation" && loadingProgress === 0 && <SimulationPlayer />}
|
||||
{(isPlaying) && activeModule !== "simulation" && <ControlsPlayer />}
|
||||
{activeModule !== "market" && !isPlaying && !isVersionSaved && <Tools />}
|
||||
{isPlaying && activeModule === "simulation" && loadingProgress === 0 && <SimulationPlayer />}
|
||||
{isPlaying && activeModule !== "simulation" && <ControlsPlayer />}
|
||||
|
||||
{isRenameMode && (selectedFloorAsset?.userData.modelName || selectedAssets.length === 1) && <RenameTooltip name={selectedFloorAsset?.userData.modelName || selectedAssets[0].userData.modelName} onSubmit={handleObjectRename} />}
|
||||
{/* remove this later */}
|
||||
@@ -168,8 +166,7 @@ function MainScene() {
|
||||
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
|
||||
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
||||
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
||||
borderRadius:
|
||||
isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||
}}
|
||||
role="application"
|
||||
onDrop={(event) =>
|
||||
@@ -180,7 +177,7 @@ function MainScene() {
|
||||
setFloatingWidget,
|
||||
event,
|
||||
projectId,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
})
|
||||
}
|
||||
onDragOver={(event) => event.preventDefault()}
|
||||
@@ -210,11 +207,7 @@ function MainScene() {
|
||||
|
||||
<VersionSaved />
|
||||
|
||||
{
|
||||
(commentPositionState !== null || selectedComment !== null) &&
|
||||
<ThreadChat />
|
||||
}
|
||||
|
||||
{(commentPositionState !== null || selectedComment !== null) && <ThreadChat />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,93 @@
|
||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||
interface SimulationData {
|
||||
key: string;
|
||||
data?: object | any;
|
||||
key: string;
|
||||
data?: object | any;
|
||||
}
|
||||
export const saveSimulationData = ({ key, data }: SimulationData) => {
|
||||
console.log("key: ", key);
|
||||
localStorage.setItem(key, JSON.stringify(data));
|
||||
interface SimulationUsageRecord {
|
||||
activeTime: number;
|
||||
isActive: boolean;
|
||||
idleTime: number;
|
||||
type: "roboticArm" | "vehicle" | "transfer" | "storageUnit" | "crane" | "human" | "machine";
|
||||
assetId: string;
|
||||
}
|
||||
|
||||
// Product → holds multiple usage records
|
||||
interface ProductSimulation {
|
||||
productId: string;
|
||||
simulateData: SimulationUsageRecord[];
|
||||
}
|
||||
|
||||
// Version → holds multiple products
|
||||
interface VersionSimulation {
|
||||
versionId: string;
|
||||
products: ProductSimulation[];
|
||||
}
|
||||
|
||||
// Project → holds multiple versions
|
||||
interface ProjectSimulation {
|
||||
projectId: string | undefined;
|
||||
versions: VersionSimulation[];
|
||||
}
|
||||
export const saveSimulationData = async (data: any) => {
|
||||
try {
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/V1/SimulatedUpsert`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer <access_token>",
|
||||
"Content-Type": "application/json",
|
||||
token: localStorage.getItem("token") || "",
|
||||
refresh_token: localStorage.getItem("refreshToken") || "",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const newAccessToken = response.headers.get("x-access-token");
|
||||
if (newAccessToken) {
|
||||
localStorage.setItem("token", newAccessToken);
|
||||
}
|
||||
if (!response.ok) {
|
||||
console.error("Failed to add project");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.log(error.message);
|
||||
} else {
|
||||
console.log("An unknown error occurred");
|
||||
}
|
||||
}
|
||||
};
|
||||
export const getSimulationData = ({ key }: SimulationData) => {
|
||||
const data = localStorage.getItem(key);
|
||||
console.log("data: ", JSON.parse(data || "{}"));
|
||||
return data;
|
||||
export const getSimulationData = async (data: any) => {
|
||||
try {
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/V1/ValidateSimulated`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: "Bearer <access_token>",
|
||||
"Content-Type": "application/json",
|
||||
token: localStorage.getItem("token") || "",
|
||||
refresh_token: localStorage.getItem("refreshToken") || "",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const newAccessToken = response.headers.get("x-access-token");
|
||||
if (newAccessToken) {
|
||||
localStorage.setItem("token", newAccessToken);
|
||||
}
|
||||
if (!response.ok) {
|
||||
console.error("Failed to add project");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.log(error.message);
|
||||
} else {
|
||||
console.log("An unknown error occurred");
|
||||
}
|
||||
}
|
||||
};
|
||||
export const clearSimulationData = ({ key, data }: SimulationData) => {};
|
||||
|
||||
@@ -135,7 +135,6 @@ const ComparisonResult = () => {
|
||||
<div className="compare-result-container">
|
||||
<div className="header">Performance Comparison</div>
|
||||
<div className="compare-result-wrapper">
|
||||
<EnergyUsage comparedProducts={comparedProducts} />
|
||||
<div className="throughPutCard-container comparisionCard">
|
||||
<h4>Throughput (units/hr)</h4>
|
||||
<div className="layers-wrapper">
|
||||
@@ -179,7 +178,7 @@ const ComparisonResult = () => {
|
||||
<Pie data={cycleTimePieData} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <EnergyUsage comparedProducts={comparedProducts} /> */}
|
||||
<div className="cycle-time-container comparisionCard">
|
||||
<div className="cycle-main">
|
||||
<div className="cycle-header">Overall Downtime</div>
|
||||
|
||||
@@ -1,113 +1,174 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { Line } from "react-chartjs-2";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
LineElement,
|
||||
PointElement,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
Tooltip,
|
||||
Legend,
|
||||
} from "chart.js";
|
||||
import { Chart as ChartJS, LineElement, PointElement, CategoryScale, LinearScale, Tooltip, Legend } from "chart.js";
|
||||
|
||||
ChartJS.register(
|
||||
LineElement,
|
||||
PointElement,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
Tooltip,
|
||||
Legend
|
||||
);
|
||||
ChartJS.register(LineElement, PointElement, CategoryScale, LinearScale, Tooltip, Legend);
|
||||
|
||||
const EnergyUsage = ({comparedProducts}:any) => {
|
||||
const data = useMemo(() => {
|
||||
const randomizeData = () =>
|
||||
Array.from({ length: 5 }, () => Math.floor(Math.random() * (2000 - 300 + 1)) + 300);
|
||||
// const EnergyUsage = ({comparedProducts}:any) => {
|
||||
// const data = useMemo(() => {
|
||||
// const randomizeData = () =>
|
||||
// Array.from({ length: 5 }, () => Math.floor(Math.random() * (2000 - 300 + 1)) + 300);
|
||||
|
||||
return {
|
||||
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Simulation 1",
|
||||
data: randomizeData(),
|
||||
borderColor: "#6a0dad",
|
||||
fill: false,
|
||||
tension: 0.5, // More curved line
|
||||
pointRadius: 0, // Remove point indicators
|
||||
},
|
||||
{
|
||||
label: "Simulation 2",
|
||||
data: randomizeData(),
|
||||
borderColor: "#b19cd9",
|
||||
fill: false,
|
||||
tension: 0.5,
|
||||
pointRadius: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
}, []);
|
||||
// return {
|
||||
// labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
||||
// datasets: [
|
||||
// {
|
||||
// label: "Simulation 1",
|
||||
// data: randomizeData(),
|
||||
// borderColor: "#6a0dad",
|
||||
// fill: false,
|
||||
// tension: 0.5, // More curved line
|
||||
// pointRadius: 0, // Remove point indicators
|
||||
// },
|
||||
// {
|
||||
// label: "Simulation 2",
|
||||
// data: randomizeData(),
|
||||
// borderColor: "#b19cd9",
|
||||
// fill: false,
|
||||
// tension: 0.5,
|
||||
// pointRadius: 0,
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: false, // Hide x-axis
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
display: false, // Hide y-axis
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
[]
|
||||
);
|
||||
// const options = useMemo(
|
||||
// () => ({
|
||||
// responsive: true,
|
||||
// maintainAspectRatio: false,
|
||||
// plugins: {
|
||||
// title: {
|
||||
// display: true,
|
||||
// },
|
||||
// legend: {
|
||||
// display: false,
|
||||
// },
|
||||
// },
|
||||
// scales: {
|
||||
// x: {
|
||||
// display: false, // Hide x-axis
|
||||
// grid: {
|
||||
// display: false,
|
||||
// },
|
||||
// },
|
||||
// y: {
|
||||
// display: false, // Hide y-axis
|
||||
// grid: {
|
||||
// display: false,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }),
|
||||
// []
|
||||
// );
|
||||
|
||||
return (
|
||||
<div className="comparisionCard energy-usage">
|
||||
<div className="energy-usage-wrapper">
|
||||
<h4>Energy Usage</h4>
|
||||
<p className="value">
|
||||
2500 <span>kWh</span>
|
||||
</p>
|
||||
</div>
|
||||
// return (
|
||||
// <div className="comparisionCard energy-usage">
|
||||
// <div className="energy-usage-wrapper">
|
||||
// <h4>Energy Usage</h4>
|
||||
// <p className="value">
|
||||
// 2500 <span>kWh</span>
|
||||
// </p>
|
||||
// </div>
|
||||
|
||||
<div className="simulation-details">
|
||||
<div className="simulation-wrapper sim-1">
|
||||
<div className="icon"></div>
|
||||
<div className="simulation-details-wrapper">
|
||||
<div className="label">{comparedProducts[0]?.productName}</div>
|
||||
<div className="value">98%</div>
|
||||
</div>
|
||||
// <div className="simulation-details">
|
||||
// <div className="simulation-wrapper sim-1">
|
||||
// <div className="icon"></div>
|
||||
// <div className="simulation-details-wrapper">
|
||||
// <div className="label">{comparedProducts[0]?.productName}</div>
|
||||
// <div className="value">98%</div>
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className="simulation-wrapper sim-2">
|
||||
// <div className="icon"></div>
|
||||
// <div className="simulation-details-wrapper">
|
||||
// <div className="label">{comparedProducts[1]?.productName}</div>
|
||||
// <div className="value">97%</div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// <div className="chart">
|
||||
// <Line data={data} options={options} />
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default EnergyUsage;
|
||||
|
||||
const EnergyUsage = ({ comparedProducts }: any) => {
|
||||
const data = useMemo(() => {
|
||||
return {
|
||||
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
||||
datasets: comparedProducts.map((product: any, idx: number) => ({
|
||||
label: product.productName,
|
||||
// use actual energyUsage instead of random data
|
||||
data: Array(5).fill(product.simulationData.energyUsage),
|
||||
borderColor: idx === 0 ? "#6a0dad" : "#b19cd9",
|
||||
fill: false,
|
||||
tension: 0.5,
|
||||
pointRadius: 0,
|
||||
})),
|
||||
};
|
||||
}, [comparedProducts]);
|
||||
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: false,
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="comparisionCard energy-usage">
|
||||
<div className="energy-usage-wrapper">
|
||||
<h4>Energy Usage</h4>
|
||||
<p className="value">
|
||||
{comparedProducts.reduce((acc: number, p: any) => acc + (p.simulationData.energyUsage || 0), 0)} <span>kWh</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="simulation-details">
|
||||
{comparedProducts.map((product: any, idx: number) => (
|
||||
<div key={product.productUuid} className={`simulation-wrapper sim-${idx + 1}`}>
|
||||
<div className="icon"></div>
|
||||
<div className="simulation-details-wrapper">
|
||||
<div className="label">{product.productName}</div>
|
||||
<div className="value">{product.simulationData.energyUsage} kWh</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="chart">
|
||||
<Line data={data} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="simulation-wrapper sim-2">
|
||||
<div className="icon"></div>
|
||||
<div className="simulation-details-wrapper">
|
||||
<div className="label">{comparedProducts[1]?.productName}</div>
|
||||
<div className="value">97%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="chart">
|
||||
<Line data={data} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default EnergyUsage;
|
||||
|
||||
@@ -68,7 +68,7 @@ const SimulationPlayer: React.FC = () => {
|
||||
useEffect(() => {
|
||||
if (materialData.length === 0) return;
|
||||
console.log('materialData: ', materialData);
|
||||
saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
|
||||
// saveSimulationData({ key: selectedProduct.productUuid, data: materialData });
|
||||
}, [materialData])
|
||||
|
||||
// Button functions
|
||||
|
||||
Reference in New Issue
Block a user