From a47ad608136d41c61bb78ead0758639c160e3199 Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Tue, 9 Sep 2025 16:07:07 +0530 Subject: [PATCH] updated layout comparsion --- .../layout/scenes/ComparisonScene.tsx | 147 ++++------- .../functions/calculateSimulationData.ts | 99 ++++++++ .../sidebarRight/simulation/Simulations.tsx | 20 +- .../ui/compareVersion/CompareLayOut.tsx | 21 +- .../ui/compareVersion/ComparisonResult.tsx | 168 +++++++------ .../result-card/EnergyUsage.tsx | 229 ++++++++--------- .../simulator/SimulationHandler1.tsx | 232 ------------------ .../simulator/simulationHandler.tsx | 118 +++++++++ .../simulation/simulator/simulator.tsx | 39 +-- .../comparison/getSimulationDataApi.ts | 2 - .../simulation/products/getProductApi.ts | 5 +- .../store/rough/useSimulationManagerStore.ts | 47 ---- app/src/styles/layout/_compareLayout.scss | 72 ++++-- 13 files changed, 556 insertions(+), 643 deletions(-) create mode 100644 app/src/components/layout/scenes/functions/calculateSimulationData.ts delete mode 100644 app/src/modules/simulation/simulator/SimulationHandler1.tsx create mode 100644 app/src/modules/simulation/simulator/simulationHandler.tsx diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index cd3e398..fd35601 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -9,7 +9,8 @@ import ComparisonResult from "../../ui/compareVersion/ComparisonResult"; import RegularDropDown from "../../ui/inputs/RegularDropDown"; import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; import { useParams } from "react-router-dom"; - +import { validateSimulationDataApi } from "../../../services/simulation/comparison/validateSimulationDataApi"; +import { calculateSimulationData } from "./functions/calculateSimulationData"; type AssetData = { activeTime: number; idleTime: number; @@ -20,23 +21,6 @@ type AssetData = { export interface CompareProduct { productUuid: string; productName: string; - // simulationData: { - // // costPerUnit: number; - // // workingDaysPerYear: number; - // // shiftLength: number; - // // shiftsPerDay: number; - // roiPercentage: number; - // // paybackPeriod: number; - // // totalCost: number; - // // revenueGenerated: number; - // netProfit: number; - // productionCapacity: number; - // paybackPeriod: number; - // // netLoss: number; - // machineIdleTime: number; - // machineActiveTime: number; - // throughputData: number; - // }; simulationData: { roiPercentage: number; netProfit: number; @@ -48,67 +32,14 @@ export interface CompareProduct { simulationTime?: number; simulationCost?: number; efficiencyScore?: number; + // totalCost: number; + // revenueGenerated: number; + // costPerUnit: number; + //workingDaysPerYear: number; + //shiftLength: number; + //shiftsPerDay: number; }; } - -const calculateSimulationData = (assets: AssetData[]) => { - let totalActiveTime = 0; - let totalIdleTime = 0; - let throughput = 0; - let productionCapacity = 0; - let simulationCost = 0; - - // Cost weight per type (example values, adjust as needed) - const costWeight: Record = { - roboticArm: 50, - machine: 100, - human: 30, - 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; - totalIdleTime += asset.idleTime; - - if (asset.activeTime > 0) throughput += 1; - - productionCapacity += asset.activeTime; - simulationCost += asset.activeTime * (costWeight[asset.type] || 10); - }); - - const machineActiveTime = assets.filter((a) => a.type === "machine").reduce((acc, a) => acc + a.activeTime, 0); - - const machineIdleTime = assets.filter((a) => a.type === "machine").reduce((acc, a) => acc + a.idleTime, 0); - - const simulationTime = totalActiveTime + totalIdleTime; - - // --- Efficiency Score --- - // Weighted formula: lower cost + lower time => higher score - // Example formula (normalize to 0–100): - const efficiencyScore = Math.max( - 0, - 100 - - (simulationTime / 1000) * 0.5 - // weight 0.5 for time - (simulationCost / 1000) * 0.5 // weight 0.5 for cost - ); - - return { - throughputData: throughput, - machineActiveTime, - machineIdleTime, - productionCapacity, - netProfit: 0, // placeholder - roiPercentage: 0, // placeholder - paybackPeriod: 0, // placeholder - simulationTime, - simulationCost, - efficiencyScore, - energyUsage, - }; -}; - export const createCompareProduct = (productUuid: string, productName: string, assets: AssetData[]): CompareProduct => ({ productUuid, productName, @@ -128,11 +59,30 @@ function ComparisonScene() { const { projectId } = useParams(); const { setCompareProductsData } = useCompareProductDataStore(); const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false); + const { addSimulationRecord } = useSimulationManager(); + + useEffect(() => {}); const handleSelectVersion = (option: string) => { const version = versionHistory.find((version) => version.versionName === option); if (version) { setSelectedVersion(version); + const singleData = { + projectId: projectId, + versionId: selectedVersion?.versionId || "", + productUuid: selectedProduct?.productUuid || "", + }; + validateSimulationDataApi(singleData).then((getData) => { + echo.log(getData.message); + const getSimulate = getData?.data?.existingSimulatedData; + if (!getSimulate) return; + if (!selectedVersion?.versionId || !projectId || getSimulate === undefined || !selectedProduct.productUuid) { + echo.warn("No prebacked Data found"); + alert("Please run the simulation before comparing."); + return; + } + addSimulationRecord(projectId, selectedVersion?.versionId || "", selectedProduct.productUuid || "", getSimulate.data); + }); } }; @@ -145,39 +95,33 @@ function ComparisonScene() { versionUuid: selectedVersion.versionId, versionName: selectedVersion.versionName, }; + const singleData = { + projectId: projectId, + versionId: selectedVersion.versionId, + productUuid: product.productUuid, + }; + validateSimulationDataApi(singleData).then((getData) => { + echo.warn(getData.message); + const getSimulate = getData?.data?.existingSimulatedData; + if (!getSimulate) return; + addSimulationRecord(projectId, selectedVersion?.versionId || "", product.productUuid || "", getSimulate.data); + }); setComparisonState(data); } }; - // useEffect(() => { - // if (mainProduct && comparisonProduct && compareProductsData.length > 1) { - // const hasMain = compareProductsData.some((val) => val.productUuid === mainProduct.productUuid); - // const hasComparison = compareProductsData.some((val) => val.productUuid === comparisonProduct.productUuid); - // if (hasMain && hasComparison && mainProduct.productUuid !== comparisonProduct.productUuid) { - // setShouldShowComparisonResult(true); - // } else { - // setShouldShowComparisonResult(false); - // } - // } else { - // setShouldShowComparisonResult(false); - // } - // }, [compareProductsData, mainProduct, comparisonProduct]); - useEffect(() => { - // const selectedProductData = getProductById(selectedProduct.productUuid); if (mainScene && comparisonScene && selectedVersion) { - const product1 = useSimulationManager.getState().getProductById(projectId, mainScene.version.versionUuid, mainScene.product.productUuid); - console.log("product1: ", product1); + const mainVersion = useSimulationManager.getState().getProductById(projectId, mainScene.version.versionUuid, mainScene.product.productUuid); - const product2 = useSimulationManager.getState().getProductById(projectId, comparisonScene.version.versionUuid, comparisonScene.product.productUuid); - console.log("product2: ", product2); + const compareVersion = useSimulationManager.getState().getProductById(projectId, comparisonScene.version.versionUuid, comparisonScene.product.productUuid); - const compareProduct1 = createCompareProduct(product1?.productId ?? "", mainScene.product.productName, product1?.simulateData || []); - const compareProduct2 = createCompareProduct(product2?.productId ?? "", comparisonScene.product.productName, product2?.simulateData || []); + const mainVompareversion = createCompareProduct(mainVersion?.productId ?? "", mainScene.product.productName, mainVersion?.simulateData || []); + const compareProduct2 = createCompareProduct(compareVersion?.productId ?? "", comparisonScene.product.productName, compareVersion?.simulateData || []); - const comparedArray = [compareProduct1, compareProduct2]; + const comparedArray = [mainVompareversion, compareProduct2]; - if (product1 === undefined || product2 === undefined) { + if (mainVersion === undefined || compareVersion === undefined) { setShouldShowComparisonResult(false); } else if (comparedArray.length === 2) { setCompareProductsData(comparedArray); @@ -186,7 +130,7 @@ function ComparisonScene() { } else { setShouldShowComparisonResult(false); } - }, [mainScene, comparisonScene, selectedVersion, projectId, setCompareProductsData]); + }, [mainScene, comparisonScene, selectedVersion, projectId, setCompareProductsData, simulationRecords]); return ( <> @@ -210,7 +154,6 @@ function ComparisonScene() { )} - {shouldShowComparisonResult && !loadingProgress && } )} diff --git a/app/src/components/layout/scenes/functions/calculateSimulationData.ts b/app/src/components/layout/scenes/functions/calculateSimulationData.ts new file mode 100644 index 0000000..9abc857 --- /dev/null +++ b/app/src/components/layout/scenes/functions/calculateSimulationData.ts @@ -0,0 +1,99 @@ +type AssetData = { + activeTime: number; + idleTime: number; + type: string; + assetId: string; +}; + +export interface CompareProduct { + productUuid: string; + productName: string; + // simulationData: { + // // costPerUnit: number; + // // workingDaysPerYear: number; + // // shiftLength: number; + // // shiftsPerDay: number; + // roiPercentage: number; + // // paybackPeriod: number; + // // totalCost: number; + // // revenueGenerated: number; + // netProfit: number; + // productionCapacity: number; + // paybackPeriod: number; + // // netLoss: number; + // machineIdleTime: number; + // machineActiveTime: number; + // throughputData: number; + // }; + simulationData: { + roiPercentage: number; + netProfit: number; + productionCapacity: number; + paybackPeriod: number; + machineIdleTime: number; + machineActiveTime: number; + throughputData: number; + simulationTime?: number; + simulationCost?: number; + efficiencyScore?: number; + }; +} + +export const calculateSimulationData = (assets: AssetData[]) => { + let totalActiveTime = 0; + let totalIdleTime = 0; + let throughput = 0; + let productionCapacity = 0; + let simulationCost = 0; + + // Cost weight per type (example values, adjust as needed) + const costWeight: Record = { + roboticArm: 50, + machine: 100, + human: 30, + 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; + totalIdleTime += asset.idleTime; + + if (asset.activeTime > 0) throughput += 1; + + productionCapacity += asset.activeTime; + simulationCost += asset.activeTime * (costWeight[asset.type] || 10); + }); + + const machineActiveTime = assets.filter((a) => a.type === "human").reduce((acc, a) => acc + a.activeTime, 0); + + const machineIdleTime = assets.filter((a) => a.type === "machine").reduce((acc, a) => acc + a.idleTime, 0); + + const simulationTime = totalActiveTime + totalIdleTime; + + // --- Efficiency Score --- + // Weighted formula: lower cost + lower time => higher score + // Example formula (normalize to 0–100): + const efficiencyScore = Math.max( + 0, + 100 - + (simulationTime / 1000) * 0.5 - // weight 0.5 for time + (simulationCost / 1000) * 0.5 // weight 0.5 for cost + ); + + return { + throughputData: throughput, + machineActiveTime, + machineIdleTime, + productionCapacity, + netProfit: 0, // placeholder + roiPercentage: 0, // placeholder + paybackPeriod: 0, // placeholder + simulationTime, + simulationCost, + efficiencyScore, + energyUsage, + }; +}; diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx index e275341..a74ba03 100644 --- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx +++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx @@ -1,5 +1,5 @@ -import React, { useEffect, useRef, useState } from "react"; import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons"; +import React, { useEffect, useRef, useState } from "react"; import RenameInput from "../../../ui/inputs/RenameInput"; import { handleResize } from "../../../../functions/handleResizePannel"; import { useSimulationState, useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; @@ -17,7 +17,6 @@ import { useCompareStore, useIsComparing } from "../../../../store/builder/store import { useToggleStore } from "../../../../store/ui/useUIToggleStore"; import { useParams } from "react-router-dom"; import { useSceneContext } from "../../../../modules/scene/sceneContext"; -import { useSimulationManager } from "../../../../store/rough/useSimulationManagerStore"; import { validateSimulationDataApi } from "../../../../services/simulation/comparison/validateSimulationDataApi"; interface Event { @@ -39,10 +38,9 @@ const Simulations: React.FC = () => { const { selectedVersion } = versionStore(); const { comparePopUp, setComparePopUp } = useCompareStore(); const { setIsComparing } = useIsComparing(); - const { addSimulationRecord } = useSimulationManager(); const handleSaveVersion = () => { - setIsComparing(true); + // setIsComparing(true); setComparePopUp(false); setToggleUI(false, false); const singleData = { @@ -52,9 +50,15 @@ const Simulations: React.FC = () => { }; validateSimulationDataApi(singleData).then((getData) => { echo.log(getData.message); - const getSimulate = getData?.data; - if (!selectedVersion?.versionId && !projectId && getSimulate === undefined && !selectedProduct.productUuid) return; - addSimulationRecord(projectId, selectedVersion?.versionId || "", selectedProduct.productUuid || "", getSimulate.data); + const getSimulate = getData?.data?.existingSimulatedData; + if (!selectedVersion?.versionId || !projectId || getSimulate === undefined || !selectedProduct.productUuid) { + echo.warn("No prebacked Data found"); + alert("Please run the simulation before comparing."); + return; + } else if (getSimulate) { + setToggleUI(true, true); + setIsComparing(true); + } }); }; @@ -149,11 +153,13 @@ const Simulations: React.FC = () => { setProcesses(processes); }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedProduct.productUuid, products]); useEffect(() => { if (comparePopUp || selectedProduct.productUuid) { } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [comparePopUp]); return ( diff --git a/app/src/components/ui/compareVersion/CompareLayOut.tsx b/app/src/components/ui/compareVersion/CompareLayOut.tsx index c86cc66..23c6313 100644 --- a/app/src/components/ui/compareVersion/CompareLayOut.tsx +++ b/app/src/components/ui/compareVersion/CompareLayOut.tsx @@ -12,12 +12,11 @@ import Scene from "../../../modules/scene/scene"; import useRestStates from "../../../hooks/useResetStates"; import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi"; -import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; import { validateSimulationDataApi } from "../../../services/simulation/comparison/validateSimulationDataApi"; const CompareLayOut = () => { const { clearComparisonState, comparisonScene, setComparisonState } = useSimulationState(); - const { versionStore, productStore } = useSceneContext(); + const { versionStore } = useSceneContext(); const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion, setVersions } = versionStore(); const { setLoadingProgress } = useLoadingProgress(); const [width, setWidth] = useState("50vw"); @@ -31,8 +30,6 @@ const CompareLayOut = () => { const { setIsPlaying } = usePlayButtonStore(); const { projectId } = useParams(); const { resetStates } = useRestStates(); - const { products } = productStore(); - const { addSimulationRecord } = useSimulationManager(); useEffect(() => { return () => { resetStates(); @@ -58,9 +55,7 @@ const CompareLayOut = () => { }); setVersions(versions); }) - .catch(() => { - console.error("Error fetching version history"); - }); + .catch(() => {}); // eslint-disable-next-line react-hooks/exhaustive-deps }, [projectId]); @@ -167,14 +162,16 @@ const CompareLayOut = () => { setLoadingProgress(1); const singleData = { projectId: projectId, - versionId: version.versionId, // use version directly, not selectedVersion - productUuid: data[0].productUuid, // productUuid is already a string + versionId: version.versionId, + productUuid: data[0].productUuid, }; - console.log("products", products); + validateSimulationDataApi(singleData).then((getData) => { echo.log(getData.message); - const getSimulate = getData?.data; - addSimulationRecord(projectId, selectedVersion?.versionId || "", data[0].productUuid || "", getSimulate.data); + const getSimulate = getData?.data?.existingSimulatedData; + + if (!getSimulate) return; + // addSimulationRecord(projectId, version?.versionId || "", data[0].productUuid || "", getSimulate.data); }); } }); diff --git a/app/src/components/ui/compareVersion/ComparisonResult.tsx b/app/src/components/ui/compareVersion/ComparisonResult.tsx index 89e53e5..0194662 100644 --- a/app/src/components/ui/compareVersion/ComparisonResult.tsx +++ b/app/src/components/ui/compareVersion/ComparisonResult.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import PerformanceResult from "./result-card/PerformanceResult"; import { Bar, Pie } from "react-chartjs-2"; import { useCompareProductDataStore } from "../../../store/builder/store"; -import { useSimulationState } from "../../../store/simulation/useSimulationStore"; +import { useSimulationState } from "../../../store/simulation/useSimulationStore"; export interface CompareProduct { productUuid: string; @@ -28,14 +28,7 @@ const ComparisonResult = () => { useEffect(() => { if (compareProductsData.length > 0 && comparisonScene && mainScene) { - const mainProductData = compareProductsData.find((product) => product.productUuid === mainScene.product.productUuid); - const comparisonProductData = compareProductsData.find((product) => product.productUuid === comparisonScene.product.productUuid); - - if (mainProductData && comparisonProductData) { - setComparedProducts([mainProductData, comparisonProductData]); - } else { - setComparedProducts([]); - } + setComparedProducts([compareProductsData[0], compareProductsData[1]]); } else { setComparedProducts([]); } @@ -122,18 +115,87 @@ const ComparisonResult = () => { ], }; - const highestProductivityProduct = (comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1]; + const highestProductivityProduct = + (comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1]; - const product1CyclePercentage = ((comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) / ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) * 100; - const product2CyclePercentage = ((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) / ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100; + const product1CyclePercentage = + ((comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) / + ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) * + 100; + const product2CyclePercentage = + ((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) / + ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * + 100; - const product1IdlePercentage = ((comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) / ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) * 100; - const product2IdlePercentage = ((comparedProducts[1]?.simulationData?.machineIdleTime ?? 0) / ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100; + const product1IdlePercentage = + ((comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) / + ((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) * + 100; + const product2IdlePercentage = + ((comparedProducts[1]?.simulationData?.machineIdleTime ?? 0) / + ((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * + 100; return (
Performance Comparison
+
+
+

Human Active Time

+ {/*

Cycle Time

*/} +
+
+
{comparedProducts[0]?.productName}
+
{compareProductsData[0]?.simulationData.machineActiveTime} Sec
+
= 50 ? "profit" : "loss"}`}> + {product1CyclePercentage >= 50 ? "↑" : "↓"} + {(100 - product1CyclePercentage).toFixed(2)}% +
+
+
+
{comparedProducts[1]?.productName}
+
{compareProductsData[1]?.simulationData.machineActiveTime} Sec
+
= 50 ? "profit" : "loss"}`}> + {product2CyclePercentage >= 50 ? "↑" : "↓"} + {(100 - product2CyclePercentage).toFixed(2)}% +
+
+
+
+
+ +
+
+ + {/* */} +
+
+
Human Idle Time
+ {/*
Overall Downtime
*/} +
+
+
{comparedProducts[0]?.productName}
+
{compareProductsData[0]?.simulationData.machineIdleTime} Sec
+
= 50 ? "profit" : "loss"}`}> + {product1IdlePercentage >= 50 ? "↑" : "↓"} + {(100 - product1IdlePercentage).toFixed(2)}% +
+
+
+
{comparedProducts[1]?.productName}
+
{compareProductsData[1]?.simulationData.machineIdleTime} Sec
+
= 50 ? "profit" : "loss"}`}> + {product2IdlePercentage >= 50 ? "↑" : "↓"} + {(100 - product2IdlePercentage).toFixed(2)}% +
+
+
+
+
+ +
+

Throughput (units/hr)

@@ -151,78 +213,24 @@ const ComparisonResult = () => {
-
-
-

Cycle Time

-
-
-
{comparedProducts[0]?.productName}
-
{compareProductsData[0]?.simulationData.machineActiveTime} Sec
-
- - {(100 - product1CyclePercentage).toFixed(2)}% -
+
+

Overall Downtime

+
+
+
+
Total down time
+
(Simulation 1)
-
-
{comparedProducts[1]?.productName}
-
{compareProductsData[1]?.simulationData.machineActiveTime} Sec
-
- - {(100 - product2CyclePercentage).toFixed(2)}% -
+
+
17
+
mins
-
-
- -
-
- {/* */} -
-
-
Overall Downtime
-
-
-
{comparedProducts[0]?.productName}
-
{compareProductsData[0]?.simulationData.machineIdleTime} Sec
-
- - {(100 - product1IdlePercentage).toFixed(2)}% -
-
-
-
{comparedProducts[1]?.productName}
-
{compareProductsData[1]?.simulationData.machineIdleTime} Sec
-
- - {(100 - product2IdlePercentage).toFixed(2)}% -
-
+
+
-
- -
- {/* -
-

Overall Downtime

-
-
-
-
Total down time
-
(Simulation 1)
-
-
-
17
-
mins
-
-
-
- -
-
-
*/}

Production Capacity

diff --git a/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx b/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx index b343ca9..2f1daec 100644 --- a/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx +++ b/app/src/components/ui/compareVersion/result-card/EnergyUsage.tsx @@ -4,114 +4,34 @@ import { Chart as ChartJS, LineElement, PointElement, CategoryScale, LinearScale 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); - -// 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, -// }, -// }, -// }, -// }), -// [] -// ); - -// return ( -//
-//
-//

Energy Usage

-//

-// 2500 kWh -//

-//
- -//
-//
-//
-//
-//
{comparedProducts[0]?.productName}
-//
98%
-//
-//
-//
-//
-//
-//
{comparedProducts[1]?.productName}
-//
97%
-//
-//
-//
- -//
-// -//
-//
-// ); -// }; - -// export default EnergyUsage; - const EnergyUsage = ({ comparedProducts }: any) => { const data = useMemo(() => { + const randomizeData = () => Array.from({ length: 5 }, () => Math.floor(Math.random() * (2000 - 300 + 1)) + 300); + console.log("randomizeData: ", randomizeData()); + 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, - })), + datasets: [ + { + label: "Simulation 1", + data: randomizeData(), + // 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, + }, + ], }; - }, [comparedProducts]); + }, []); const options = useMemo( () => ({ @@ -127,13 +47,13 @@ const EnergyUsage = ({ comparedProducts }: any) => { }, scales: { x: { - display: false, + display: false, // Hide x-axis grid: { display: false, }, }, y: { - display: false, + display: false, // Hide y-axis grid: { display: false, }, @@ -148,20 +68,25 @@ const EnergyUsage = ({ comparedProducts }: any) => {

Energy Usage

- {comparedProducts.reduce((acc: number, p: any) => acc + (p.simulationData.energyUsage || 0), 0)} kWh + 2500 kWh

- {comparedProducts.map((product: any, idx: number) => ( -
-
-
-
{product.productName}
-
{product.simulationData.energyUsage} kWh
-
+
+
+
+
{comparedProducts[0]?.productName}
+
98%
- ))} +
+
+
+
+
{comparedProducts[1]?.productName}
+
97%
+
+
@@ -172,3 +97,79 @@ const EnergyUsage = ({ comparedProducts }: any) => { }; 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 ( +//
+//
+//

Energy Usage

+//

+// {comparedProducts.reduce((acc: number, p: any) => acc + (p.simulationData.energyUsage || 0), 0)} kWh +//

+//
+ +//
+// {comparedProducts.map((product: any, idx: number) => ( +//
+//
+//
+//
{product.productName}
+//
{product.simulationData.energyUsage} kWh
+//
+//
+// ))} +//
+ +//
+// +//
+//
+// ); +// }; + +// export default EnergyUsage; diff --git a/app/src/modules/simulation/simulator/SimulationHandler1.tsx b/app/src/modules/simulation/simulator/SimulationHandler1.tsx deleted file mode 100644 index f105f77..0000000 --- a/app/src/modules/simulation/simulator/SimulationHandler1.tsx +++ /dev/null @@ -1,232 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { useSceneContext } from "../../scene/sceneContext"; -import { determineExecutionMachineSequences } from "./functions/determineExecutionMachineSequences"; -import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; -import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; -import { useParams } from "react-router-dom"; -import { saveSimulationDataApi } from "../../../services/simulation/comparison/saveSimulationDataApi"; - -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; - data: SimulationUsageRecord[]; -} - -// Version → holds multiple products -interface VersionSimulation { - versionId: string; - products: ProductSimulation[]; -} - -const SimulationHandler = () => { - const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore, craneStore, humanStore, versionStore } = useSceneContext(); - const { armBots, getArmBotById } = armBotStore(); - const { vehicles, getVehicleById } = vehicleStore(); - const { getConveyorById } = conveyorStore(); - const { materialHistory, materials } = materialStore(); - const { getProductById, selectedProduct } = productStore(); - const { machines, getMachineById } = machineStore(); - const { getHumanById } = humanStore(); - const { getCraneById } = craneStore(); - const { getStorageUnitById } = storageUnitStore(); - const { isPlaying, setIsPlaying } = usePlayButtonStore(); - const { resetProductRecords, addSimulationRecord } = useSimulationManager(); - const { projectId } = useParams(); - const COST_RATES: Record = { - roboticArm: 5, - vehicle: 2, - transfer: 1, - storageUnit: 1, - crane: 6, - human: 4, - machine: 3, - }; - const { selectedVersion } = versionStore(); - - // Calculate totals for one product - function calculateProductMetrics(product: ProductSimulation) { - let totalActiveTime = 0; - let totalIdleTime = 0; - let totalCost = 0; - - product.data.forEach((record) => { - const resourceTime = record.activeTime + record.idleTime; - const costRate = COST_RATES[record.type] || 0; - - totalActiveTime += record.activeTime; - totalIdleTime += record.idleTime; - totalCost += resourceTime * costRate; - }); - - return { - totalTime: totalActiveTime + totalIdleTime, - totalActiveTime, - totalIdleTime, - totalCost, - }; - } - - // Calculate totals for a version - function calculateVersionMetrics(version: VersionSimulation) { - return version.products.reduce( - (acc, product) => { - const metrics = calculateProductMetrics(product); - - acc.totalTime += metrics.totalTime; - acc.totalActiveTime += metrics.totalActiveTime; - acc.totalIdleTime += metrics.totalIdleTime; - acc.totalCost += metrics.totalCost; - return acc; - }, - { totalTime: 0, totalActiveTime: 0, totalIdleTime: 0, totalCost: 0 } - ); - } - - // Efficiency score (compare across versions) - function calculateEfficiencyScores(versions: VersionSimulation[]) { - const versionMetrics = versions.map((v) => ({ - versionId: v.versionId, - ...calculateVersionMetrics(v), - })); - - const minTime = Math.min(...versionMetrics.map((m) => m.totalTime)); - const minCost = Math.min(...versionMetrics.map((m) => m.totalCost)); - - return versionMetrics.map((m) => { - const timeFactor = minTime / m.totalTime; - const costFactor = minCost / m.totalCost; - - const efficiencyScore = 0.5 * timeFactor + 0.5 * costFactor; - - return { ...m, efficiencyScore }; - }); - } - - useEffect(() => { - let checkTimer: ReturnType; - if (!projectId) return; - async function checkActiveMachines() { - const currentProduct = getProductById(selectedProduct.productUuid); - let hasActiveEntity = false; - - if (currentProduct) { - const executionSequences = await determineExecutionMachineSequences([currentProduct]); - if (executionSequences?.length > 0) { - executionSequences.forEach((sequence) => { - sequence.forEach((entity) => { - if (entity.type === "roboticArm") { - const roboticArm = getArmBotById(entity.modelUuid); - if (roboticArm?.isActive) { - hasActiveEntity = true; - } - } - if (entity.type === "vehicle") { - const vehicle = getVehicleById(entity.modelUuid); - if (vehicle?.isActive) { - hasActiveEntity = true; - } - } - if (entity.type === "machine") { - const machine = getMachineById(entity.modelUuid); - if (machine?.isActive) { - hasActiveEntity = true; - } - } - if (entity.type === "human") { - const human = getHumanById(entity.modelUuid); - if (human?.isActive) { - hasActiveEntity = true; - } - } - if (entity.type === "crane") { - const crane = getCraneById(entity.modelUuid); - if (crane?.isActive) { - hasActiveEntity = true; - } - } - if (entity.type === "storageUnit") { - const storageUnit = getStorageUnitById(entity.modelUuid); - if (storageUnit?.isActive) { - hasActiveEntity = true; - } - } - if (entity.type === "transfer") { - const storageUnit = getConveyorById(entity.modelUuid); - if (storageUnit?.isActive) { - hasActiveEntity = true; - } - } - }); - }); - } - - if (materials.length === 0 && materialHistory.length >= 0 && !hasActiveEntity) { - if (!selectedVersion) return; - resetProductRecords(projectId, selectedVersion?.versionId, selectedProduct?.productUuid); - if (executionSequences?.length > 0) { - executionSequences.forEach((sequence) => { - sequence.forEach((entity) => { - const typeToGetter: Record any> = { - roboticArm: getArmBotById, - vehicle: getVehicleById, - machine: getMachineById, - human: getHumanById, - crane: getCraneById, - storageUnit: getStorageUnitById, - transfer: getConveyorById, - }; - - const getter = typeToGetter[entity.type]; - if (!getter) return; // skip unknown entity types - - const obj = getter(entity.modelUuid); - if (!obj) return; // skip if not found - - addSimulationRecord(projectId, selectedVersion?.versionId || "", selectedProduct?.productUuid, { - activeTime: obj.activeTime ?? 0, - isActive: obj.isActive ?? false, - idleTime: obj.idleTime ?? 0, - type: entity.type as "roboticArm" | "vehicle" | "machine" | "human" | "crane" | "storageUnit" | "transfer", - assetId: entity.modelUuid, - }); - }); - }); - } - const data = { - projectId: projectId, - versionId: selectedVersion?.versionId, - productUuid: selectedProduct.productUuid, - simulateData: useSimulationManager.getState().getProductById(projectId || "", selectedVersion?.versionId || "", selectedProduct?.productUuid || "")?.simulateData, - }; - const simulations = await saveSimulationDataApi(data); - - echo.log("Simulation data saved successfully"); - setIsPlaying(false); - } - } - } - - if (isPlaying) { - checkTimer = setTimeout(() => { - checkActiveMachines(); - }, 1500); - } - - return () => { - if (checkTimer) clearTimeout(checkTimer); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [materials, materialHistory, selectedVersion, selectedProduct?.productUuid, isPlaying, armBots, vehicles, machines]); - - return null; -}; - -export default SimulationHandler; diff --git a/app/src/modules/simulation/simulator/simulationHandler.tsx b/app/src/modules/simulation/simulator/simulationHandler.tsx new file mode 100644 index 0000000..5aff421 --- /dev/null +++ b/app/src/modules/simulation/simulator/simulationHandler.tsx @@ -0,0 +1,118 @@ +import React, { useEffect, useState } from "react"; +import { useSceneContext } from "../../scene/sceneContext"; +import { determineExecutionMachineSequences } from "./functions/determineExecutionMachineSequences"; +import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; +import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; +import { useParams } from "react-router-dom"; +import { saveSimulationDataApi } from "../../../services/simulation/comparison/saveSimulationDataApi"; + +const SimulationHandler = () => { + const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore, craneStore, humanStore, versionStore } = useSceneContext(); + const { armBots, getArmBotById } = armBotStore(); + const { vehicles, getVehicleById } = vehicleStore(); + const { getConveyorById } = conveyorStore(); + const { materialHistory, materials } = materialStore(); + const { getProductById, selectedProduct } = productStore(); + const { machines, getMachineById } = machineStore(); + const { getHumanById } = humanStore(); + const { getCraneById } = craneStore(); + const { getStorageUnitById } = storageUnitStore(); + const { isPlaying, setIsPlaying } = usePlayButtonStore(); + const { resetProductRecords, addSimulationRecord } = useSimulationManager(); + const { selectedVersion } = versionStore(); + const { projectId } = useParams(); + + useEffect(() => { + if (!projectId) return; + + let checkTimer: ReturnType; + + const typeToGetter: Record any> = { + roboticArm: getArmBotById, + vehicle: getVehicleById, + machine: getMachineById, + human: getHumanById, + crane: getCraneById, + storageUnit: getStorageUnitById, + transfer: getConveyorById, + }; + + const isEntityActive = (entity: any): boolean => { + const getter = typeToGetter[entity.type]; + const obj = getter?.(entity.modelUuid); + return obj?.isActive ?? false; + }; + + const recordEntity = (entity: any) => { + const getter = typeToGetter[entity.type]; + const obj = getter?.(entity.modelUuid); + if (!obj) return; + + addSimulationRecord(projectId, selectedVersion?.versionId || "", selectedProduct?.productUuid, { + activeTime: obj.activeTime ?? 0, + isActive: obj.isActive ?? false, + idleTime: obj.idleTime ?? 0, + type: entity.type as "roboticArm" | "vehicle" | "machine" | "human" | "crane" | "storageUnit" | "transfer", + assetId: entity.modelUuid, + }); + }; + + function checkActiveMachines() { + const currentProduct = getProductById(selectedProduct.productUuid); + if (!currentProduct) return; + + determineExecutionMachineSequences([currentProduct]).then((executionSequences) => { + // --- Check if any entity is active --- + let hasActiveEntity = false; + executionSequences?.forEach((sequence) => + sequence.forEach((entity) => { + if (isEntityActive(entity)) { + hasActiveEntity = true; + } + }) + ); + + // --- Save simulation data if idle --- + const noMaterials = materials.length === 0; + const hasHistory = materialHistory.length >= 0; + + if (noMaterials && hasHistory && !hasActiveEntity) { + if (!selectedVersion) return; + + resetProductRecords(projectId, selectedVersion.versionId, selectedProduct.productUuid); + + executionSequences?.forEach((sequence) => sequence.forEach((entity) => recordEntity(entity))); + + const data = { + projectId, + versionId: selectedVersion.versionId, + productUuid: selectedProduct.productUuid, + simulateData: useSimulationManager.getState().getProductById(projectId, selectedVersion.versionId, selectedProduct.productUuid)?.simulateData, + }; + + saveSimulationDataApi(data) + .then(() => { + echo.log("Simulation data saved successfully"); + setIsPlaying(false); + }) + .catch((err) => { + console.error("Failed to save simulation data:", err); + }); + } + }); + } + + if (isPlaying) { + checkTimer = setTimeout(checkActiveMachines, 1500); + } + + return () => { + if (checkTimer) clearTimeout(checkTimer); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [materials, materialHistory, selectedVersion, selectedProduct?.productUuid, isPlaying, armBots, vehicles, machines]); + + return null; +}; + +export default SimulationHandler; diff --git a/app/src/modules/simulation/simulator/simulator.tsx b/app/src/modules/simulation/simulator/simulator.tsx index f44dc4c..e18e2e9 100644 --- a/app/src/modules/simulation/simulator/simulator.tsx +++ b/app/src/modules/simulation/simulator/simulator.tsx @@ -3,10 +3,12 @@ import { useActionHandler } from "../actions/useActionHandler"; import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore"; import { determineExecutionOrder } from "./functions/determineExecutionOrder"; import { useSceneContext } from "../../scene/sceneContext"; -import SimulationHandler from "./SimulationHandler1"; +import SimulationHandler from "./simulationHandler"; import { useParams } from "react-router-dom"; import { useSimulationManager } from "../../../store/rough/useSimulationManagerStore"; import { getSimulationDataApi } from "../../../services/simulation/comparison/getSimulationDataApi"; +import { getProductApi } from "../../../services/simulation/products/getProductApi"; +import { useIsComparing } from "../../../store/builder/store"; function Simulator() { const { productStore, versionStore } = useSceneContext(); @@ -16,7 +18,8 @@ function Simulator() { const { isReset } = useResetButtonStore(); const { projectId } = useParams(); const { selectedVersion } = versionStore(); - const { addSimulationRecord } = useSimulationManager(); + const { setIsComparing } = useIsComparing(); + const { addSimulationRecords } = useSimulationManager(); useEffect(() => { if (!isPlaying || isReset || !selectedProduct.productUuid) return; @@ -34,28 +37,26 @@ function Simulator() { useEffect(() => { if (!projectId || !selectedVersion || !selectedProduct?.productUuid) return; - const fetchSimulateData = async () => { - const getData = await getSimulationDataApi(projectId, selectedVersion.versionId, selectedProduct?.productUuid); + getSimulationDataApi(projectId, selectedVersion.versionId, selectedProduct?.productUuid).then((getData) => { + getProductApi(selectedProduct.productUuid, projectId, selectedVersion.versionId).then((product) => { + if (!product) return; + const getSimulate = getData?.data; - const product = getProductById(selectedProduct.productUuid); - if (!product) return; - const products: ProductsSchema = [product]; - const getSimulate = getData?.data; - - if (getData.message !== "Simulated data not found" && getSimulate && getSimulate.productTimestamp === products[0]?.timestamp) { - addSimulationRecord(projectId, selectedVersion?.versionId || "", selectedProduct?.productUuid || "", getSimulate.data); - echo.log("Simulation data is up to date"); - return; - } else { - } - }; - fetchSimulateData(); + if (getData.message !== "Simulated data not found" && getSimulate && getSimulate.productTimestamp === product?.timestamp) { + addSimulationRecords(projectId, selectedVersion?.versionId || "", selectedProduct?.productUuid || "", getSimulate.data); + echo.warn("Simulation data is up to date"); + return; + } else { + setIsComparing(false); + echo.warn("Please run the simulation before comparing."); + } + }); + }); // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [selectedProduct, projectId]); return ( <> - {/* */} ); diff --git a/app/src/services/simulation/comparison/getSimulationDataApi.ts b/app/src/services/simulation/comparison/getSimulationDataApi.ts index 62cc56f..6a2555e 100644 --- a/app/src/services/simulation/comparison/getSimulationDataApi.ts +++ b/app/src/services/simulation/comparison/getSimulationDataApi.ts @@ -12,8 +12,6 @@ export const getSimulationDataApi = async (projectId: string, versionId: string, }, }); - console.log("response: ", response); - const newAccessToken = response.headers.get("x-access-token"); if (newAccessToken) { localStorage.setItem("token", newAccessToken); diff --git a/app/src/services/simulation/products/getProductApi.ts b/app/src/services/simulation/products/getProductApi.ts index c557e33..3282a84 100644 --- a/app/src/services/simulation/products/getProductApi.ts +++ b/app/src/services/simulation/products/getProductApi.ts @@ -2,12 +2,13 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR export const getProductApi = async ( productUuid: string, - projectId: string + projectId: string, + versionId: string, ) => { try { const response = await fetch( - `${url_Backend_dwinzo}/api/V1/EventsByProduct?productUuid=${productUuid}&projectId=${projectId}`, + `${url_Backend_dwinzo}/api/V1/EventsByProduct?productUuid=${productUuid}&projectId=${projectId}&versionId=${versionId}`, { method: "GET", headers: { diff --git a/app/src/store/rough/useSimulationManagerStore.ts b/app/src/store/rough/useSimulationManagerStore.ts index fc72630..80dbb97 100644 --- a/app/src/store/rough/useSimulationManagerStore.ts +++ b/app/src/store/rough/useSimulationManagerStore.ts @@ -25,7 +25,6 @@ interface ProjectSimulation { projectId: string | undefined; versions: VersionSimulation[]; } -// or same file interface SimulationManagerStore { simulationRecords: ProjectSimulation[]; @@ -41,52 +40,6 @@ interface SimulationManagerStore { export const useSimulationManager = create((set, get) => ({ simulationRecords: [], - // addSimulationRecord: (projectId, versionId, productId, record) => - // set((state) => { - // const projects = state.simulationRecords.map((project) => { - // if (project.projectId !== projectId) return project; - - // return { - // ...project, - // versions: project.versions.map((version) => { - // if (version.versionId !== versionId) return version; - - // return { - // ...version, - // products: version.products.map((product) => (product.productId === productId ? { ...product, simulateData: [...product.simulateData, record] } : product)), - // }; - // }), - // }; - // }); - - // // If project doesn't exist, create it - // if (!state.simulationRecords.find((p) => p.projectId === projectId)) { - // projects.push({ - // projectId, - // versions: [ - // { - // versionId, - // products: [{ productId, simulateData: [record] }], - // }, - // ], - // }); - // } else { - // const project = projects.find((p) => p.projectId === projectId)!; - // if (!project.versions.find((v) => v.versionId === versionId)) { - // project.versions.push({ - // versionId, - // products: [{ productId, simulateData: [record] }], - // }); - // } else { - // const version = project.versions.find((v) => v.versionId === versionId)!; - // if (!version.products.find((p) => p.productId === productId)) { - // version.products.push({ productId, simulateData: [record] }); - // } - // } - // } - - // return { simulationRecords: projects }; - // }), addSimulationRecord: (projectId, versionId, productId, record) => set((state) => { const projects = state.simulationRecords.map((project) => { diff --git a/app/src/styles/layout/_compareLayout.scss b/app/src/styles/layout/_compareLayout.scss index 010cd05..ec4135f 100644 --- a/app/src/styles/layout/_compareLayout.scss +++ b/app/src/styles/layout/_compareLayout.scss @@ -305,19 +305,14 @@ background-color: #b7b7c6; // Custom polygon shape (adjust if needed) - clip-path: polygon(96% 52%, - 96% 54%, - 45% 53%, - 3% 100%, - 0 100%, - 42% 52%); + clip-path: polygon(96% 52%, 96% 54%, 45% 53%, 3% 100%, 0 100%, 42% 52%); z-index: 0; // Behind any inner content } } // Optional: content above the shape - >* { + > * { position: relative; z-index: 1; } @@ -372,19 +367,14 @@ height: 100%; background: var(--background-color, wheat); - clipPath: polygon(25% 0%, - 75% 0%, - 100% 50%, - 75% 100%, - 25% 100%, - 0% 50%); + clippath: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.25)); z-index: 0; } // Content stays above the shape - >* { + > * { position: relative; z-index: 1; } @@ -422,8 +412,6 @@ position: relative; .energy-usage-wrapper { - - .value { padding-top: 25px; font-size: var(--font-size-xxxlarge); @@ -518,14 +506,46 @@ .layer-time { font-size: var(--font-size-large); } - - .layer-profit { - color: #14ca44; - text-align: end; - - span { + .layer-change { + &.profit { color: #14ca44; + span { + color: #14ca44; + } } + + &.loss { + color: #ff0000; + span { + color: #ff0000; + } + } + text-align: end; + } + + // .layer-profit { + // color: #14ca44; + // text-align: end; + + // span { + // color: #14ca44; + // } + // } + .layer-profit { + &.profit { + color: #14ca44; + span { + color: #14ca44; + } + } + + &.loss { + color: #ff0000; + span { + color: #ff0000; + } + } + text-align: end; } } } @@ -543,19 +563,19 @@ .overallDowntime-container { .totalDownTime-wrapper { display: flex; + align-items: flex-start; + gap: 4px; .totalDownTime { width: 70%; background: var(--background-color-secondary); backdrop-filter: blur(20px); border-radius: 12px; - display: flex; justify-content: space-between; align-items: center; - // gap: 20px; padding: 8px 10px; - margin: 44px 0; + margin-top: 16px; .totalDownTime-right { display: flex; @@ -605,4 +625,4 @@ position: relative; } } -} \ No newline at end of file +}