244 lines
10 KiB
TypeScript
244 lines
10 KiB
TypeScript
import React, { useEffect, useMemo, useState } from "react";
|
|
import PerformanceResult from "./result-card/PerformanceResult";
|
|
import EnergyUsage from "./result-card/EnergyUsage";
|
|
import { Bar, Line, Pie } from "react-chartjs-2";
|
|
import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store";
|
|
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
|
|
|
|
const ComparisonResult = () => {
|
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
|
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
|
const { mainProduct } = useMainProduct();
|
|
const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>([]);
|
|
|
|
useEffect(() => {
|
|
if (compareProductsData.length > 0 && mainProduct && comparisonProduct) {
|
|
const mainProductData = compareProductsData.find(
|
|
(product) => product.productUuid === mainProduct.productUuid
|
|
);
|
|
const comparisonProductData = compareProductsData.find(
|
|
(product) => product.productUuid === comparisonProduct.productUuid
|
|
);
|
|
|
|
if (mainProductData && comparisonProductData) {
|
|
setComparedProducts([mainProductData, comparisonProductData]);
|
|
} else {
|
|
setComparedProducts([]);
|
|
}
|
|
} else {
|
|
setComparedProducts([]);
|
|
}
|
|
}, [compareProductsData, mainProduct, comparisonProduct]);
|
|
|
|
useEffect(() => {
|
|
if (comparedProducts.length === 2) {
|
|
|
|
}
|
|
}, [comparedProducts]);
|
|
|
|
const options = useMemo(
|
|
() => ({
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
title: { display: false },
|
|
legend: { display: false },
|
|
},
|
|
scales: {
|
|
x: { display: false, grid: { display: false } },
|
|
y: { display: false, grid: { display: false } },
|
|
},
|
|
}),
|
|
[]
|
|
);
|
|
|
|
// Color palette
|
|
const purpleDark = "#6a0dad";
|
|
const purpleLight = "#b19cd9";
|
|
|
|
const throughputData = {
|
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
|
datasets: [
|
|
{
|
|
label: "Throughput (units/hr)",
|
|
data: [comparedProducts[0]?.simulationData.throughputData, comparedProducts[1]?.simulationData.throughputData],
|
|
backgroundColor: [purpleDark, purpleLight],
|
|
borderColor: [purpleDark, purpleLight],
|
|
borderWidth: 1,
|
|
borderRadius: 10, // ✅ Rounded all corners (TypeScript-safe)
|
|
// borderSkipped: "bottom", // ✅ This is allowed by the Chart.js types
|
|
},
|
|
],
|
|
};
|
|
|
|
|
|
const cycleTimePieData = {
|
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
|
datasets: [
|
|
{
|
|
label: "Cycle Time (sec)",
|
|
data: [comparedProducts[0]?.simulationData.machineActiveTime, comparedProducts[1]?.simulationData.machineActiveTime],
|
|
backgroundColor: [purpleDark, purpleLight],
|
|
borderColor: "#fff",
|
|
borderWidth: 2,
|
|
},
|
|
],
|
|
};
|
|
|
|
const downtimeData = {
|
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
|
datasets: [
|
|
{
|
|
label: "Downtime (mins)",
|
|
data: [comparedProducts[0]?.simulationData.machineIdleTime, comparedProducts[1]?.simulationData.machineIdleTime],
|
|
backgroundColor: [purpleDark, purpleLight],
|
|
borderColor: "#fff",
|
|
borderWidth: 2,
|
|
},
|
|
],
|
|
};
|
|
|
|
const productionCapacityData = {
|
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
|
datasets: [
|
|
{
|
|
label: "Production Capacity (units)",
|
|
data: [comparedProducts[0]?.simulationData.productionCapacity, comparedProducts[1]?.simulationData.productionCapacity],
|
|
backgroundColor: [purpleDark, purpleLight],
|
|
borderColor: [purpleDark, purpleLight],
|
|
borderWidth: 1,
|
|
borderRadius: 10,
|
|
borderSkipped: false,
|
|
},
|
|
],
|
|
};
|
|
|
|
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 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 (
|
|
<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">
|
|
<div className="layer-wrapper">
|
|
<div className="key">{comparedProducts[0]?.productName}</div>
|
|
<div className="value">{comparedProducts[0]?.simulationData.throughputData}/ hr</div>
|
|
</div>
|
|
<div className="layer-wrapper">
|
|
<div className="key">{comparedProducts[1]?.productName}</div>
|
|
<div className="value">{comparedProducts[1]?.simulationData.throughputData}/ hr</div>
|
|
</div>
|
|
<div className="chart">
|
|
<Bar data={throughputData} options={options} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="cycle-time-container comparisionCard">
|
|
<div className="cycle-main">
|
|
<h4 className="cycle-header">Cycle Time</h4>
|
|
<div className="layers-wrapper">
|
|
<div className="layers">
|
|
<div className="layer-name">{comparedProducts[0]?.productName}</div>
|
|
<div className="layer-time">{compareProductsData[0]?.simulationData.machineActiveTime} Sec</div>
|
|
<div className="layer-profit">
|
|
<span>↑</span>{(100 - product1CyclePercentage).toFixed(2)}%
|
|
</div>
|
|
</div>
|
|
<div className="layers">
|
|
<div className="layer-name">{comparedProducts[1]?.productName}</div>
|
|
<div className="layer-time">{compareProductsData[1]?.simulationData.machineActiveTime} Sec</div>
|
|
<div className="layer-profit">
|
|
<span>↑</span>{(100 - product2CyclePercentage).toFixed(2)}%
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="chart">
|
|
<Pie data={cycleTimePieData} options={options} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="cycle-time-container comparisionCard">
|
|
<div className="cycle-main">
|
|
<div className="cycle-header">Overall Downtime</div>
|
|
<div className="layers-wrapper">
|
|
<div className="layers">
|
|
<div className="layer-name">{comparedProducts[0]?.productName}</div>
|
|
<div className="layer-time">{compareProductsData[0]?.simulationData.machineIdleTime} Sec</div>
|
|
<div className="layer-profit">
|
|
<span>↑</span>{(100 - product1IdlePercentage).toFixed(2)}%
|
|
</div>
|
|
</div>
|
|
<div className="layers">
|
|
<div className="layer-name">{comparedProducts[1]?.productName}</div>
|
|
<div className="layer-time">{compareProductsData[1]?.simulationData.machineIdleTime} Sec</div>
|
|
<div className="layer-profit">
|
|
<span>↑</span>{(100 - product2IdlePercentage).toFixed(2)}%
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="chart">
|
|
<Pie data={downtimeData} options={options} />
|
|
</div>
|
|
</div>
|
|
{/*
|
|
<div className="overallDowntime-container comparisionCard">
|
|
<h4 className="overallDowntime-header">Overall Downtime</h4>
|
|
<div className="totalDownTime-wrapper">
|
|
<div className="totalDownTime">
|
|
<div className="totalDownTime-right">
|
|
<div className="totalDownTime-label">Total down time</div>
|
|
<div className="totalDownTime-subLabel">(Simulation 1)</div>
|
|
</div>
|
|
<div className="totalDownTime-left">
|
|
<div className="value">17</div>
|
|
<div className="key">mins</div>
|
|
</div>
|
|
</div>
|
|
<div className="chart">
|
|
<Bar data={downtimeData} options={options} />
|
|
</div>
|
|
</div>
|
|
</div> */}
|
|
|
|
<div className="overallScrapRate comparisionCard">
|
|
<h4 className="overallScrapRate-header">Production Capacity</h4>
|
|
<div className="overallScrapRate-wrapper">
|
|
<div className="overallScrapRate-value">
|
|
<div className="overallScrapRate-label">{highestProductivityProduct?.productName}</div>
|
|
<div className="overallScrapRate-key">Total product produced</div>
|
|
<div className="overallScrapRateKey-value">{highestProductivityProduct?.simulationData.productionCapacity}</div>
|
|
</div>
|
|
<div className="chart">
|
|
<Bar data={productionCapacityData} options={options} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{ comparedProducts.length === 2 &&<PerformanceResult comparedProducts={comparedProducts}/>}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ComparisonResult;
|