Merge remote-tracking branch 'origin/v3-refactor' into v3
This commit is contained in:
commit
0cde60fa76
|
@ -6,7 +6,7 @@ import useModuleStore from '../../../store/useModuleStore';
|
||||||
import CompareLayOut from '../../ui/compareVersion/CompareLayOut';
|
import CompareLayOut from '../../ui/compareVersion/CompareLayOut';
|
||||||
import ComparisonResult from '../../ui/compareVersion/ComparisonResult';
|
import ComparisonResult from '../../ui/compareVersion/ComparisonResult';
|
||||||
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
|
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
|
||||||
import { usePauseButtonStore, usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
function ComparisonScene() {
|
function ComparisonScene() {
|
||||||
|
@ -18,7 +18,6 @@ function ComparisonScene() {
|
||||||
const { selectedProduct } = selectedProductStore();
|
const { selectedProduct } = selectedProductStore();
|
||||||
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||||
const { mainProduct } = useMainProduct();
|
const { mainProduct } = useMainProduct();
|
||||||
const { setIsPaused } = usePauseButtonStore();
|
|
||||||
const { loadingProgress } = useLoadingProgress();
|
const { loadingProgress } = useLoadingProgress();
|
||||||
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||||
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
|
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
|
||||||
|
@ -29,6 +28,37 @@ function ComparisonScene() {
|
||||||
setComparisonProduct(product.productUuid, product.productName);
|
setComparisonProduct(product.productUuid, product.productName);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// useEffect(() => {
|
||||||
|
// setCompareProductsData([
|
||||||
|
// {
|
||||||
|
// "productUuid": "15193386-ec58-4ec6-8a92-e665a39eebf1",
|
||||||
|
// "productName": "Product 1",
|
||||||
|
// "simulationData": {
|
||||||
|
// "roiPercentage": 273.9428571428571,
|
||||||
|
// "paybackPeriod": 1.8251981643721318,
|
||||||
|
// "netProfit": 9588000,
|
||||||
|
// "productionCapacity": 4508.5,
|
||||||
|
// "machineIdleTime": 1450,
|
||||||
|
// "machineActiveTime": 430,
|
||||||
|
// "throughputData": 180.34
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "productUuid": "f614bf50-f61d-41c5-acc0-3783fb4da6b8",
|
||||||
|
// "productName": "Product 2",
|
||||||
|
// "simulationData": {
|
||||||
|
// "roiPercentage": 281.7214285714286,
|
||||||
|
// "paybackPeriod": 1.7748028701097842,
|
||||||
|
// "netProfit": 9860250,
|
||||||
|
// "productionCapacity": 4599.25,
|
||||||
|
// "machineIdleTime": 1885,
|
||||||
|
// "machineActiveTime": 646,
|
||||||
|
// "throughputData": 183.97
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ])
|
||||||
|
// }, []); // ✅ Runs only once on mount
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mainProduct && comparisonProduct && compareProductsData.length > 1) {
|
if (mainProduct && comparisonProduct && compareProductsData.length > 1) {
|
||||||
|
@ -45,8 +75,6 @@ function ComparisonScene() {
|
||||||
}
|
}
|
||||||
}, [compareProductsData, mainProduct, comparisonProduct]);
|
}, [compareProductsData, mainProduct, comparisonProduct]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isVersionSaved && activeModule === "simulation" && selectedProduct && (
|
{isVersionSaved && activeModule === "simulation" && selectedProduct && (
|
||||||
|
|
|
@ -19,15 +19,15 @@ const Analysis: React.FC = () => {
|
||||||
// { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
|
// { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
|
||||||
],
|
],
|
||||||
"Production capacity": [
|
"Production capacity": [
|
||||||
{ type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 6 } },
|
{ type: "range", inputs: { label: "Shift length", activeOption: "hr", defaultValue: 1 } },
|
||||||
{ type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 2 } },
|
{ type: "default", inputs: { label: "Shifts / day", activeOption: "unit", defaultValue: 3 } },
|
||||||
{ type: "default", inputs: { label: "Working days / year", activeOption: "days", defaultValue: 300 } },
|
{ type: "default", inputs: { label: "Working days / year", activeOption: "days", defaultValue: 300 } },
|
||||||
{ type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 92 } },
|
{ type: "default", inputs: { label: "Yield rate", activeOption: "%", defaultValue: 98 } },
|
||||||
],
|
],
|
||||||
ROI: [
|
ROI: [
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Selling price", activeOption: "INR", defaultValue: 800 },
|
inputs: { label: "Selling price", activeOption: "INR", defaultValue: 500 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
|
@ -37,6 +37,10 @@ const Analysis: React.FC = () => {
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 150 },
|
inputs: { label: "Labor Cost", activeOption: "INR", defaultValue: 150 },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "default",
|
||||||
|
inputs: { label: "Labor Count", activeOption: "", defaultValue: 1 },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Maintenance cost", activeOption: "INR", defaultValue: 1200 },
|
inputs: { label: "Maintenance cost", activeOption: "INR", defaultValue: 1200 },
|
||||||
|
@ -47,11 +51,11 @@ const Analysis: React.FC = () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 1250 },
|
inputs: { label: "Fixed costs", activeOption: "INR", defaultValue: 1150 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 1500000 },
|
inputs: { label: "Initial Investment", activeOption: "INR", defaultValue: 3500000 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
|
|
|
@ -26,6 +26,8 @@ const ThroughputSummary: React.FC = () => {
|
||||||
unit: "KWH",
|
unit: "KWH",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Dynamic shift data
|
// Dynamic shift data
|
||||||
const shiftUtilization = [
|
const shiftUtilization = [
|
||||||
{ shift: 1, percentage: 30, color: "#F3C64D" },
|
{ shift: 1, percentage: 30, color: "#F3C64D" },
|
||||||
|
@ -126,7 +128,7 @@ const ThroughputSummary: React.FC = () => {
|
||||||
<div className="process-container">
|
<div className="process-container">
|
||||||
<div className="throughput-value">
|
<div className="throughput-value">
|
||||||
<span className="value">{productionCapacityData}</span>{" "}
|
<span className="value">{productionCapacityData}</span>{" "}
|
||||||
Units/hour
|
Units/Month
|
||||||
</div>
|
</div>
|
||||||
<div className="lineChart">
|
<div className="lineChart">
|
||||||
<div className="assetUsage">
|
<div className="assetUsage">
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
import SemiCircleProgress from "./SemiCircleProgress";
|
import SemiCircleProgress from "./SemiCircleProgress";
|
||||||
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
||||||
import SkeletonUI from "../../templates/SkeletonUI";
|
import SkeletonUI from "../../templates/SkeletonUI";
|
||||||
import { useROISummaryData } from "../../../store/builder/store";
|
import { useInputValues, useROISummaryData } from "../../../store/builder/store";
|
||||||
|
|
||||||
const ROISummary = ({
|
const ROISummary = ({
|
||||||
roiSummaryData = {
|
roiSummaryData = {
|
||||||
|
@ -67,6 +67,8 @@ const ROISummary = ({
|
||||||
},
|
},
|
||||||
}) => {
|
}) => {
|
||||||
const [isTableOpen, setIsTableOpen] = useState(false); // State to handle the table open/close
|
const [isTableOpen, setIsTableOpen] = useState(false); // State to handle the table open/close
|
||||||
|
const { inputValues } = useInputValues();
|
||||||
|
const productionPeriod = parseFloat(inputValues["Production period"]);
|
||||||
|
|
||||||
// Function to toggle the breakdown table visibility
|
// Function to toggle the breakdown table visibility
|
||||||
const toggleTable = () => {
|
const toggleTable = () => {
|
||||||
|
@ -95,6 +97,17 @@ const ROISummary = ({
|
||||||
}
|
}
|
||||||
}, [roiSummary]);
|
}, [roiSummary]);
|
||||||
|
|
||||||
|
function getPaybackDateFromYears(yearsToAdd: number) {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const totalMonths = Math.round(yearsToAdd * 12);
|
||||||
|
|
||||||
|
const paybackDate = new Date(now.getFullYear(), now.getMonth() + totalMonths, now.getDate());
|
||||||
|
const month = paybackDate.toLocaleString("en-GB", { month: "long" });
|
||||||
|
const year = paybackDate.getFullYear();
|
||||||
|
return `${month} ${year}`;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
|
@ -121,26 +134,30 @@ const ROISummary = ({
|
||||||
<SonarCrownIcon />
|
<SonarCrownIcon />
|
||||||
<div className="icon"></div>
|
<div className="icon"></div>
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<span>{roiSummary.roiPercentage}% </span>
|
<span>{roiSummary.roiPercentage.toFixed(2)}% </span>
|
||||||
ROI
|
ROI in the period of {productionPeriod} years
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="roi-details">
|
<div className="roi-details">
|
||||||
<div className="progress-wrapper">
|
<div className="progress-wrapper">
|
||||||
<SemiCircleProgress />
|
<SemiCircleProgress
|
||||||
|
progress={(parseFloat(roiSummary.paybackPeriod.toFixed(2)) / (productionPeriod)) * 100}
|
||||||
|
years={parseFloat(roiSummary.paybackPeriod.toFixed(2))}
|
||||||
|
/>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
you're on track to hit it by
|
you're on track to hit it by
|
||||||
<div className="key">July 2029</div>
|
<div className="key">{getPaybackDateFromYears(roiSummary.paybackPeriod)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="metrics">
|
<div className="metrics">
|
||||||
<div className="metric-wrapper">
|
<div className="metric-wrapper">
|
||||||
<div className="metric-item">
|
<div className="metric-item">
|
||||||
<span className="metric-label">Total Cost Incurred</span>
|
<span className="metric-label">Total Cost Incurred</span>
|
||||||
<span className="metric-value">
|
<span className="metric-value">
|
||||||
<span>₹</span>
|
<span>₹</span>
|
||||||
{roiSummary.totalCost}
|
{roiSummary.totalCost.toFixed(0)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="metric-item">
|
<div className="metric-item">
|
||||||
|
@ -148,7 +165,7 @@ const ROISummary = ({
|
||||||
<span className="metric-value">
|
<span className="metric-value">
|
||||||
<span>₹</span>
|
<span>₹</span>
|
||||||
|
|
||||||
{roiSummary.revenueGenerated}
|
{roiSummary.revenueGenerated.toFixed(0)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -162,8 +179,8 @@ const ROISummary = ({
|
||||||
<div className="metric-value">
|
<div className="metric-value">
|
||||||
<span>₹</span>
|
<span>₹</span>
|
||||||
{roiSummary.netProfit > 0
|
{roiSummary.netProfit > 0
|
||||||
? roiSummary.netProfit
|
? roiSummary.netProfit.toFixed(0)
|
||||||
: roiSummary.netLoss}
|
: roiSummary.netLoss.toFixed(0)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useMachineCount, useMachineUptime, useMaterialCycle, useProductionCapacityData, useThroughPutData } from "../../../store/builder/store";
|
import { useInputValues, useMachineCount, useMachineUptime, useMaterialCycle, useProductionCapacityData, useThroughPutData } from "../../../store/builder/store";
|
||||||
import {
|
import {
|
||||||
ThroughputSummaryIcon,
|
ThroughputSummaryIcon,
|
||||||
} from "../../icons/analysis";
|
} from "../../icons/analysis";
|
||||||
|
@ -14,29 +14,30 @@ const ProductionCapacity = ({
|
||||||
const { machineActiveTime } = useMachineUptime();
|
const { machineActiveTime } = useMachineUptime();
|
||||||
const { materialCycleTime } = useMaterialCycle();
|
const { materialCycleTime } = useMaterialCycle();
|
||||||
const { throughputData } = useThroughPutData()
|
const { throughputData } = useThroughPutData()
|
||||||
|
const { inputValues } = useInputValues();
|
||||||
|
|
||||||
const progressPercent = machineActiveTime;
|
const progressPercent = machineActiveTime;
|
||||||
|
|
||||||
|
const shiftLength = parseFloat(inputValues["Shift length"]);
|
||||||
|
|
||||||
const totalBars = 6;
|
const totalBars = 6;
|
||||||
const barsToFill = Math.floor((progressPercent / 100) * totalBars);
|
const barsToFill = Math.floor((progressPercent / 100) * totalBars);
|
||||||
const partialFillPercent =
|
const partialFillPercent = ((progressPercent / 1000) * totalBars - barsToFill) * 100;
|
||||||
((progressPercent / 100) * totalBars - barsToFill) * 100;
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('throughputData: ', throughputData);
|
|
||||||
if (throughputData > 0) {
|
if (throughputData > 0) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} else {
|
} else {
|
||||||
setIsLoading(true);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [throughputData])
|
}, [throughputData])
|
||||||
|
|
||||||
|
const Units_per_hour = ((shiftLength * 60) / (materialCycleTime / 60) / shiftLength)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
{!isLoading && <div className="throughtputSummary-container analysis-card">
|
{!isLoading && <div className="throughtputSummary-container analysis-card">
|
||||||
<div className="throughtputSummary-wrapper analysis-card-wrapper">
|
<div className="throughtputSummary-wrapper analysis-card-wrapper">
|
||||||
<div className="card-header">
|
<div className="card-header">
|
||||||
|
@ -54,8 +55,7 @@ const ProductionCapacity = ({
|
||||||
<>
|
<>
|
||||||
<div className="process-container">
|
<div className="process-container">
|
||||||
<div className="throughput-value">
|
<div className="throughput-value">
|
||||||
<span className="value">{throughputData}</span> Units/hour
|
<span className="value">{(Units_per_hour).toFixed(2) === "Infinity"? 0 : (Units_per_hour).toFixed(2) }</span> Units/hour
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dynamic Progress Bar */}
|
{/* Dynamic Progress Bar */}
|
||||||
|
|
|
@ -1,14 +1,41 @@
|
||||||
import React, { useMemo } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import PerformanceResult from "./result-card/PerformanceResult";
|
import PerformanceResult from "./result-card/PerformanceResult";
|
||||||
import EnergyUsage from "./result-card/EnergyUsage";
|
import EnergyUsage from "./result-card/EnergyUsage";
|
||||||
import { Bar, Line, Pie } from "react-chartjs-2";
|
import { Bar, Line, Pie } from "react-chartjs-2";
|
||||||
import { useCompareProductDataStore } from "../../../store/builder/store";
|
import { CompareProduct, useCompareProductDataStore } from "../../../store/builder/store";
|
||||||
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
|
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
|
||||||
|
|
||||||
const ComparisonResult = () => {
|
const ComparisonResult = () => {
|
||||||
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
|
||||||
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
|
||||||
const { mainProduct } = useMainProduct();
|
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(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
@ -30,11 +57,11 @@ const ComparisonResult = () => {
|
||||||
const purpleLight = "#b19cd9";
|
const purpleLight = "#b19cd9";
|
||||||
|
|
||||||
const throughputData = {
|
const throughputData = {
|
||||||
labels: ["Layout 1", "Layout 2"],
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "Throughput (units/hr)",
|
label: "Throughput (units/hr)",
|
||||||
data: [500, 550],
|
data: [comparedProducts[0]?.simulationData.throughputData, comparedProducts[1]?.simulationData.throughputData],
|
||||||
backgroundColor: [purpleDark, purpleLight],
|
backgroundColor: [purpleDark, purpleLight],
|
||||||
borderColor: [purpleDark, purpleLight],
|
borderColor: [purpleDark, purpleLight],
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
@ -46,11 +73,11 @@ const ComparisonResult = () => {
|
||||||
|
|
||||||
|
|
||||||
const cycleTimePieData = {
|
const cycleTimePieData = {
|
||||||
labels: ["Layout 1", "Layout 2"],
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "Cycle Time (sec)",
|
label: "Cycle Time (sec)",
|
||||||
data: [120, 110],
|
data: [comparedProducts[0]?.simulationData.machineActiveTime, comparedProducts[1]?.simulationData.machineActiveTime],
|
||||||
backgroundColor: [purpleDark, purpleLight],
|
backgroundColor: [purpleDark, purpleLight],
|
||||||
borderColor: "#fff",
|
borderColor: "#fff",
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
|
@ -59,11 +86,24 @@ const ComparisonResult = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const downtimeData = {
|
const downtimeData = {
|
||||||
labels: ["Layout 1", "Layout 2"],
|
labels: [comparedProducts[0]?.productName, comparedProducts[1]?.productName],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "Downtime (mins)",
|
label: "Downtime (mins)",
|
||||||
data: [17, 12],
|
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],
|
backgroundColor: [purpleDark, purpleLight],
|
||||||
borderColor: [purpleDark, purpleLight],
|
borderColor: [purpleDark, purpleLight],
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
@ -73,20 +113,21 @@ const ComparisonResult = () => {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const scrapRateData = {
|
const highestProductivityProduct = (comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1];
|
||||||
labels: ["Layout 1", "Layout 2"],
|
|
||||||
datasets: [
|
const product1CyclePercentage = (comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) /
|
||||||
{
|
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) +
|
||||||
label: "Scrap Rate (tons)",
|
(compareProductsData[0]?.simulationData?.machineIdleTime ?? 0)) * 100;
|
||||||
data: [2.7, 1.9],
|
const product2CyclePercentage = ((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) /
|
||||||
backgroundColor: [purpleDark, purpleLight],
|
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) +
|
||||||
borderColor: [purpleDark, purpleLight],
|
(compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) * 100;
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 10,
|
const product1IdlePercentage = (comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) /
|
||||||
borderSkipped: false,
|
((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 (
|
return (
|
||||||
<div className="compare-result-container">
|
<div className="compare-result-container">
|
||||||
|
@ -97,12 +138,12 @@ const ComparisonResult = () => {
|
||||||
<h4>Throughput (units/hr)</h4>
|
<h4>Throughput (units/hr)</h4>
|
||||||
<div className="layers-wrapper">
|
<div className="layers-wrapper">
|
||||||
<div className="layer-wrapper">
|
<div className="layer-wrapper">
|
||||||
<div className="key">Layout 1</div>
|
<div className="key">{comparedProducts[0]?.productName}</div>
|
||||||
<div className="value">500/ hr</div>
|
<div className="value">{comparedProducts[0]?.simulationData.throughputData}/ hr</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="layer-wrapper">
|
<div className="layer-wrapper">
|
||||||
<div className="key">Layout 2</div>
|
<div className="key">{comparedProducts[1]?.productName}</div>
|
||||||
<div className="value">550/ hr</div>
|
<div className="value">{comparedProducts[1]?.simulationData.throughputData}/ hr</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="chart">
|
<div className="chart">
|
||||||
<Bar data={throughputData} options={options} />
|
<Bar data={throughputData} options={options} />
|
||||||
|
@ -115,17 +156,17 @@ const ComparisonResult = () => {
|
||||||
<div className="cycle-header">Cycle Time</div>
|
<div className="cycle-header">Cycle Time</div>
|
||||||
<div className="layers-wrapper">
|
<div className="layers-wrapper">
|
||||||
<div className="layers">
|
<div className="layers">
|
||||||
<div className="layer-name">Layout 1</div>
|
<div className="layer-name">{comparedProducts[0]?.productName}</div>
|
||||||
<div className="layer-time">120 Sec</div>
|
<div className="layer-time">{compareProductsData[0]?.simulationData.machineActiveTime} Sec</div>
|
||||||
<div className="layer-profit">
|
<div className="layer-profit">
|
||||||
<span>↑</span>19.6%
|
<span>↑</span>{(100 - product1CyclePercentage).toFixed(2)}%
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="layers">
|
<div className="layers">
|
||||||
<div className="layer-name">Layout 2</div>
|
<div className="layer-name">{comparedProducts[1]?.productName}</div>
|
||||||
<div className="layer-time">110 Sec</div>
|
<div className="layer-time">{compareProductsData[1]?.simulationData.machineActiveTime} Sec</div>
|
||||||
<div className="layer-profit">
|
<div className="layer-profit">
|
||||||
<span>↑</span>1.6%
|
<span>↑</span>{(100 - product2CyclePercentage).toFixed(2)}%
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -135,6 +176,31 @@ const ComparisonResult = () => {
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div className="overallDowntime-container comparisionCard">
|
||||||
<div className="overallDowntime-header">Overall Downtime</div>
|
<div className="overallDowntime-header">Overall Downtime</div>
|
||||||
<div className="totalDownTime-wrapper">
|
<div className="totalDownTime-wrapper">
|
||||||
|
@ -152,23 +218,23 @@ const ComparisonResult = () => {
|
||||||
<Bar data={downtimeData} options={options} />
|
<Bar data={downtimeData} options={options} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="overallScrapRate comparisionCard">
|
<div className="overallScrapRate comparisionCard">
|
||||||
<div className="overallScrapRate-header">Production Capacity</div>
|
<div className="overallScrapRate-header">Production Capacity</div>
|
||||||
<div className="overallScrapRate-wrapper">
|
<div className="overallScrapRate-wrapper">
|
||||||
<div className="overallScrapRate-value">
|
<div className="overallScrapRate-value">
|
||||||
<div className="overallScrapRate-label">Layout 1</div>
|
<div className="overallScrapRate-label">{highestProductivityProduct?.productName}</div>
|
||||||
<div className="overallScrapRate-key">Total scrap produced by</div>
|
<div className="overallScrapRate-key">Total product produced</div>
|
||||||
<div className="overallScrapRateKey-value">2.7 ton</div>
|
<div className="overallScrapRateKey-value">{highestProductivityProduct?.simulationData.productionCapacity}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="chart">
|
<div className="chart">
|
||||||
<Bar data={scrapRateData} options={options} />
|
<Bar data={productionCapacityData} options={options} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PerformanceResult />
|
{ comparedProducts.length === 2 &&<PerformanceResult comparedProducts={comparedProducts}/>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,27 +20,32 @@ ChartJS.register(
|
||||||
);
|
);
|
||||||
|
|
||||||
const EnergyUsage = () => {
|
const EnergyUsage = () => {
|
||||||
const data = {
|
const data = useMemo(() => {
|
||||||
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
const randomizeData = () =>
|
||||||
datasets: [
|
Array.from({ length: 5 }, () => Math.floor(Math.random() * (2000 - 300 + 1)) + 300);
|
||||||
{
|
|
||||||
label: "Simulation 1",
|
return {
|
||||||
data: [400, 600, 450, 1000, 1000],
|
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
|
||||||
borderColor: "#6a0dad",
|
datasets: [
|
||||||
fill: false,
|
{
|
||||||
tension: 0.5, // More curved line
|
label: "Simulation 1",
|
||||||
pointRadius: 0, // Remove point indicators
|
data: randomizeData(),
|
||||||
},
|
borderColor: "#6a0dad",
|
||||||
{
|
fill: false,
|
||||||
label: "Simulation 2",
|
tension: 0.5, // More curved line
|
||||||
data: [300, 500, 700, 950, 1100],
|
pointRadius: 0, // Remove point indicators
|
||||||
borderColor: "#b19cd9",
|
},
|
||||||
fill: false,
|
{
|
||||||
tension: 0.5,
|
label: "Simulation 2",
|
||||||
pointRadius: 0,
|
data: randomizeData(),
|
||||||
},
|
borderColor: "#b19cd9",
|
||||||
],
|
fill: false,
|
||||||
};
|
tension: 0.5,
|
||||||
|
pointRadius: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const options = useMemo(
|
const options = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {
|
||||||
TickIcon,
|
TickIcon,
|
||||||
} from "../../../icons/ExportCommonIcons";
|
} from "../../../icons/ExportCommonIcons";
|
||||||
|
|
||||||
const PerformanceResult = () => {
|
const PerformanceResult = ({ comparedProducts }: any) => {
|
||||||
|
const ProfitProduct = comparedProducts[0].simulationData.netProfit > comparedProducts[1].simulationData.netProfit ? comparedProducts[0] : comparedProducts[1];
|
||||||
return (
|
return (
|
||||||
<div className="performanceResult-wrapper comparisionCard">
|
<div className="performanceResult-wrapper comparisionCard">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
|
@ -26,30 +27,30 @@ const PerformanceResult = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="metric-value">98%</div>
|
<div className="metric-value">98%</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="label">Environmental impact</div>
|
<div className="label">Net Profit</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="metrics-right">
|
<div className="metrics-right">
|
||||||
<div className="metric-wrapper">
|
<div className="metric-wrapper">
|
||||||
<div className="metric-label">Waste generation</div>
|
<div className="metric-label">ROI Percentage</div>
|
||||||
<div className="metric">
|
<div className="metric">
|
||||||
<div className="metric-icon">I</div>
|
<div className="metric-icon"></div>
|
||||||
<div className="metric-value">0.5%</div>
|
<div className="metric-value">{ProfitProduct.simulationData.roiPercentage.toFixed(2)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="metric-wrapper">
|
<div className="metric-wrapper">
|
||||||
<div className="metric-label">Risk
management</div>
|
<div className="metric-label">Payback Period</div>
|
||||||
<div className="metric">
|
<div className="metric">
|
||||||
<div className="metric-icon">I</div>
|
<div className="metric-icon"></div>
|
||||||
<div className="metric-value">0.1%</div>
|
<div className="metric-value">{ProfitProduct.simulationData.netProfit}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="metric-wrapper">
|
<div className="metric-wrapper">
|
||||||
<div className="metric">
|
<div className="metric">
|
||||||
<div className="metric-icon">I</div>
|
<div className="metric-icon"></div>
|
||||||
<div className="metric-value">0.5%</div>
|
<div className="metric-value">{parseFloat(ProfitProduct.simulationData.paybackPeriod.toFixed(2))}years</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
||||||
import { useProductContext } from '../../products/productContext';
|
import { useProductContext } from '../../products/productContext';
|
||||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||||
|
|
||||||
|
|
||||||
export default function ROIData() {
|
export default function ROIData() {
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { inputValues } = useInputValues();
|
const { inputValues } = useInputValues();
|
||||||
|
@ -36,6 +35,7 @@ export default function ROIData() {
|
||||||
const electricityCost = parseFloat(inputValues["Electricity cost"]);
|
const electricityCost = parseFloat(inputValues["Electricity cost"]);
|
||||||
const fixedCost = parseFloat(inputValues["Fixed costs"]);
|
const fixedCost = parseFloat(inputValues["Fixed costs"]);
|
||||||
const laborCost = parseFloat(inputValues["Labor Cost"]);
|
const laborCost = parseFloat(inputValues["Labor Cost"]);
|
||||||
|
const laborCount = parseFloat(inputValues["Labor Count"]);
|
||||||
const maintenanceCost = parseFloat(inputValues["Maintenance cost"]);
|
const maintenanceCost = parseFloat(inputValues["Maintenance cost"]);
|
||||||
const materialCost = parseFloat(inputValues["Material cost"]);
|
const materialCost = parseFloat(inputValues["Material cost"]);
|
||||||
const productionPeriod = parseFloat(inputValues["Production period"]);
|
const productionPeriod = parseFloat(inputValues["Production period"]);
|
||||||
|
@ -49,41 +49,103 @@ export default function ROIData() {
|
||||||
if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) &&
|
if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) &&
|
||||||
!isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) &&
|
!isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) &&
|
||||||
!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) {
|
!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) {
|
||||||
console.log('productionCapacityData: ', productionCapacityData);
|
|
||||||
|
|
||||||
const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear;
|
// const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear;
|
||||||
const annualProductionUnits = productionCapacityData * totalHoursPerYear;
|
// const annualProductionUnits = productionCapacityData * totalHoursPerYear;
|
||||||
const annualRevenue = annualProductionUnits * sellingPrice;
|
// const annualRevenue = annualProductionUnits * sellingPrice;
|
||||||
|
|
||||||
const totalMaterialCost = annualProductionUnits * materialCost;
|
// const totalMaterialCost = annualProductionUnits * materialCost;
|
||||||
const totalLaborCost = laborCost * totalHoursPerYear;
|
// const totalLaborCost = laborCost * totalHoursPerYear;
|
||||||
const totalEnergyCost = electricityCost * totalHoursPerYear;
|
// const totalEnergyCost = electricityCost * totalHoursPerYear;
|
||||||
const totalMaintenanceCost = maintenanceCost + fixedCost;
|
// const totalMaintenanceCost = maintenanceCost + fixedCost;
|
||||||
const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost;
|
// const totalAnnualCost = totalMaterialCost + totalLaborCost + totalEnergyCost + totalMaintenanceCost;
|
||||||
const annualProfit = annualRevenue - totalAnnualCost;
|
// const annualProfit = annualRevenue - totalAnnualCost;
|
||||||
|
|
||||||
const netProfit = annualProfit * productionPeriod;
|
// const netProfit = annualProfit * productionPeriod;
|
||||||
const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100;
|
// const roiPercentage = ((annualProfit + salvageValue - initialInvestment) / initialInvestment) * 100;
|
||||||
const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0
|
// const paybackPeriod = initialInvestment / (annualProfit || 1); // Avoid division by 0
|
||||||
|
|
||||||
|
// setRoiSummaryData({
|
||||||
|
// productName: selectedProduct.productName,
|
||||||
|
// roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)),
|
||||||
|
// paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
||||||
|
// totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
||||||
|
// revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
||||||
|
// netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0,
|
||||||
|
// netLoss: netProfit < 0 ? -netProfit : 0
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const productCount = 1000;
|
||||||
|
// const costPerUnit = totalAnnualCost / annualProductionUnits;
|
||||||
|
// const costForTargetUnits = productCount * costPerUnit;
|
||||||
|
// const revenueForTargetUnits = productCount * sellingPrice;
|
||||||
|
// const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits;
|
||||||
|
|
||||||
|
// const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0;
|
||||||
|
// const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0;
|
||||||
|
|
||||||
|
// const productData = getProductById(selectedProduct.productUuid);
|
||||||
|
// const prev = useCompareProductDataStore.getState().compareProductsData;
|
||||||
|
// const newData: CompareProduct = {
|
||||||
|
// productUuid: productData?.productUuid ?? '',
|
||||||
|
// productName: productData?.productName ?? '',
|
||||||
|
// simulationData: {
|
||||||
|
// // costPerUnit: parseFloat(costPerUnit.toFixed(2)),
|
||||||
|
// // workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)),
|
||||||
|
// // shiftLength: parseFloat(shiftLength.toFixed(2)),
|
||||||
|
// // shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)),
|
||||||
|
// roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)),
|
||||||
|
// // paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
||||||
|
// // totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
||||||
|
// // revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
||||||
|
// netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0,
|
||||||
|
// productionCapacity: parseFloat(productionCapacityData.toFixed(2)),
|
||||||
|
// // netLoss: netProfit < 0 ? parseFloat((-netProfit).toFixed(2)) : 0,
|
||||||
|
// machineIdleTime: parseFloat(machineIdleTime.toFixed(2)),
|
||||||
|
// machineActiveTime: parseFloat(machineActiveTime.toFixed(2)),
|
||||||
|
// throughputData: throughputData,
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const existingIndex = prev.findIndex((item: CompareProduct) =>
|
||||||
|
// item.productUuid === productData?.productUuid
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (existingIndex !== -1) {
|
||||||
|
// const updated = [...prev];
|
||||||
|
// updated[existingIndex] = newData;
|
||||||
|
// setCompareProductsData(updated);
|
||||||
|
// } else {
|
||||||
|
// setCompareProductsData([...prev, newData]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
const Annual_units = throughputData * workingDaysPerYear
|
||||||
|
const Total_units = Annual_units * productionPeriod
|
||||||
|
|
||||||
|
const Total_revenue = Total_units * sellingPrice
|
||||||
|
const Total_variable_cost = Total_units * (materialCost + (laborCost))
|
||||||
|
|
||||||
|
const Total_fixed_cost = (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear * productionPeriod
|
||||||
|
const Total_cost = Total_variable_cost + Total_fixed_cost
|
||||||
|
|
||||||
|
const Net_profit = Total_revenue - Total_cost + (salvageValue * workingDaysPerYear * productionPeriod)
|
||||||
|
|
||||||
|
const ROI = (Net_profit / initialInvestment) * 100
|
||||||
|
|
||||||
|
const Annual_net_profit = (Annual_units * (sellingPrice - materialCost - laborCost)) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + (salvageValue * workingDaysPerYear)
|
||||||
|
const Payback_period_years = initialInvestment / Annual_net_profit;
|
||||||
|
|
||||||
setRoiSummaryData({
|
setRoiSummaryData({
|
||||||
productName: selectedProduct.productName,
|
productName: selectedProduct.productName,
|
||||||
roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)),
|
roiPercentage: ROI,
|
||||||
paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
paybackPeriod: Payback_period_years,
|
||||||
totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
totalCost: Total_cost,
|
||||||
revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
revenueGenerated: Total_revenue,
|
||||||
netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0,
|
netProfit: Net_profit > 0 ? Net_profit : 0,
|
||||||
netLoss: netProfit < 0 ? -netProfit : 0
|
netLoss: Net_profit < 0 ? -Net_profit : 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const productCount = 1000;
|
|
||||||
const costPerUnit = totalAnnualCost / annualProductionUnits;
|
|
||||||
const costForTargetUnits = productCount * costPerUnit;
|
|
||||||
const revenueForTargetUnits = productCount * sellingPrice;
|
|
||||||
const profitForTargetUnits = revenueForTargetUnits - costForTargetUnits;
|
|
||||||
|
|
||||||
const netProfitForTarget = profitForTargetUnits > 0 ? profitForTargetUnits : 0;
|
|
||||||
const netLossForTarget = profitForTargetUnits < 0 ? -profitForTargetUnits : 0;
|
|
||||||
|
|
||||||
const productData = getProductById(selectedProduct.productUuid);
|
const productData = getProductById(selectedProduct.productUuid);
|
||||||
const prev = useCompareProductDataStore.getState().compareProductsData;
|
const prev = useCompareProductDataStore.getState().compareProductsData;
|
||||||
|
@ -91,18 +153,20 @@ export default function ROIData() {
|
||||||
productUuid: productData?.productUuid ?? '',
|
productUuid: productData?.productUuid ?? '',
|
||||||
productName: productData?.productName ?? '',
|
productName: productData?.productName ?? '',
|
||||||
simulationData: {
|
simulationData: {
|
||||||
// costPerUnit: parseFloat(costPerUnit.toFixed(2)),
|
// costPerUnit: costPerUnit,
|
||||||
// workingDaysPerYear: parseFloat(workingDaysPerYear.toFixed(2)),
|
// workingDaysPerYear: workingDaysPerYear,
|
||||||
// shiftLength: parseFloat(shiftLength.toFixed(2)),
|
// shiftLength: shiftLength,
|
||||||
// shiftsPerDay: parseFloat(shiftsPerDay.toFixed(2)),
|
// shiftsPerDay: shiftsPerDay,
|
||||||
roiPercentage: parseFloat((roiPercentage / 100).toFixed(2)),
|
roiPercentage: ROI,
|
||||||
// paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
paybackPeriod: Payback_period_years,
|
||||||
// totalCost: parseFloat(totalAnnualCost.toFixed(2)),
|
// paybackPeriod: paybackPeriod,
|
||||||
// revenueGenerated: parseFloat(annualRevenue.toFixed(2)),
|
// totalCost: totalAnnualCost,
|
||||||
netProfit: netProfit > 0 ? parseFloat(netProfit.toFixed(2)) : 0,
|
// revenueGenerated: annualRevenue,
|
||||||
// netLoss: netProfit < 0 ? parseFloat((-netProfit).toFixed(2)) : 0,
|
netProfit: Net_profit > 0 ? Net_profit : 0,
|
||||||
machineIdleTime: parseFloat(machineIdleTime.toFixed(2)),
|
productionCapacity: productionCapacityData,
|
||||||
machineActiveTime: parseFloat(machineActiveTime.toFixed(2)),
|
// netLoss: netProfit < 0 ? (-netProfit) : 0,
|
||||||
|
machineIdleTime: machineIdleTime,
|
||||||
|
machineActiveTime: machineActiveTime,
|
||||||
throughputData: throughputData,
|
throughputData: throughputData,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -120,10 +184,10 @@ export default function ROIData() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [inputValues, productionCapacityData, selectedProduct?.productUuid, isPlaying]);
|
}, [inputValues, productionCapacityData, throughputData, isPlaying]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('compareProductsData: ', compareProductsData);
|
|
||||||
}, [compareProductsData])
|
}, [compareProductsData])
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -13,45 +13,22 @@ export default function ProductionCapacityData() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
console.log('isPlaying: ', isPlaying);
|
|
||||||
setProductionCapacityData(0);
|
setProductionCapacityData(0);
|
||||||
}
|
}
|
||||||
}, [isPlaying]);
|
}, [isPlaying]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!inputValues || throughputData === undefined || !isPlaying) return;
|
if (!inputValues || throughputData === undefined || !isPlaying) return;
|
||||||
console.log('throughputData: ', throughputData);
|
|
||||||
|
|
||||||
const shiftLength = parseFloat(inputValues["Shift length"]);
|
|
||||||
console.log('shiftLength: ', shiftLength);
|
|
||||||
|
|
||||||
const shiftsPerDay = parseFloat(inputValues["Shifts / day"]);
|
|
||||||
|
|
||||||
const workingDaysPerYear = parseFloat(inputValues["Working days / year"]);
|
const workingDaysPerYear = parseFloat(inputValues["Working days / year"]);
|
||||||
|
|
||||||
const yieldRate = parseFloat(inputValues["Yield rate"]);
|
if (!isNaN(workingDaysPerYear) && throughputData > 0) {
|
||||||
|
const Monthly_working_days = workingDaysPerYear / 12;
|
||||||
|
const Production_capacity_per_month = throughputData * Monthly_working_days;
|
||||||
|
|
||||||
|
|
||||||
if (!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) &&
|
|
||||||
!isNaN(yieldRate) && throughputData > 0) {
|
|
||||||
// Total units produced per day before yield
|
|
||||||
const dailyProduction = throughputData * shiftLength * shiftsPerDay;
|
|
||||||
|
|
||||||
|
setProductionCapacityData(Number(Production_capacity_per_month.toFixed(2)));
|
||||||
// Units after applying yield rate
|
|
||||||
const goodUnitsPerDay = dailyProduction * (yieldRate / 100);
|
|
||||||
|
|
||||||
|
|
||||||
// Annual output
|
|
||||||
const annualProduction = goodUnitsPerDay * workingDaysPerYear;
|
|
||||||
|
|
||||||
|
|
||||||
// Final production capacity per hour (after yield)
|
|
||||||
const productionPerHour = throughputData * (yieldRate / 100);
|
|
||||||
|
|
||||||
|
|
||||||
// Set the final capacity (units/hour)
|
|
||||||
setProductionCapacityData(Number(productionPerHour.toFixed(2)));
|
|
||||||
}
|
}
|
||||||
}, [throughputData, inputValues, isPlaying]);
|
}, [throughputData, inputValues, isPlaying]);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||||
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
|
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
|
||||||
import { useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
|
import { useInputValues, useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
|
||||||
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../../store/usePlayButtonStore';
|
||||||
import { useSceneContext } from '../../../scene/sceneContext';
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
import { useProductContext } from '../../products/productContext';
|
import { useProductContext } from '../../products/productContext';
|
||||||
|
@ -25,6 +25,7 @@ export default function ThroughPutData() {
|
||||||
const { setProcessBar } = useProcessBar();
|
const { setProcessBar } = useProcessBar();
|
||||||
const { setThroughputData } = useThroughPutData()
|
const { setThroughputData } = useThroughPutData()
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
const { inputValues } = useInputValues();
|
||||||
|
|
||||||
// Setting machine count
|
// Setting machine count
|
||||||
let totalItems = 0;
|
let totalItems = 0;
|
||||||
|
@ -179,7 +180,7 @@ export default function ThroughPutData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive;
|
const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive;
|
||||||
if (allInactive && materials.length === 0 && materialHistory.length > 0) {
|
if (materials.length >= 0 && materialHistory.length > 0) {
|
||||||
|
|
||||||
let totalCycleTimeSum = 0;
|
let totalCycleTimeSum = 0;
|
||||||
let cycleCount = 0;
|
let cycleCount = 0;
|
||||||
|
@ -212,13 +213,17 @@ export default function ThroughPutData() {
|
||||||
}, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid])
|
}, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0 && isPlaying) {
|
const shiftLength = parseFloat(inputValues["Shift length"]);
|
||||||
const utilization = machineActiveTime / 3600; // Active time per hour
|
const shiftsPerDay = parseFloat(inputValues["Shifts / day"]);
|
||||||
const unitsPerMachinePerHour = 3600 / materialCycleTime;
|
const yieldRate = parseFloat(inputValues["Yield rate"]);
|
||||||
const throughput = unitsPerMachinePerHour * machineCount * utilization;
|
|
||||||
setThroughputData(Number(throughput.toFixed(2))); // Keep as number
|
if (shiftLength > 0 && materialCycleTime > 0 && machineCount > 0 && isPlaying) {
|
||||||
|
const Units_per_shift = (shiftLength * 60) / (materialCycleTime / 60);
|
||||||
|
|
||||||
|
const Throughput_per_day = Units_per_shift * shiftsPerDay * (yieldRate / 100);
|
||||||
|
setThroughputData(Number(Throughput_per_day.toFixed(2))); // Keep as number
|
||||||
}
|
}
|
||||||
}, [machineActiveTime, materialCycleTime, machineCount, selectedProduct?.productUuid, isPlaying]);
|
}, [materialCycleTime, machineCount, isPlaying, inputValues]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -48,7 +48,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||||
|
|
||||||
const computePath = useCallback(
|
const computePath = useCallback(
|
||||||
(start: any, end: any) => {
|
(start: any, end: any) => {
|
||||||
console.log('end: ', end);
|
|
||||||
try {
|
try {
|
||||||
const navMeshQuery = new NavMeshQuery(navMesh);
|
const navMeshQuery = new NavMeshQuery(navMesh);
|
||||||
const { path: segmentPath } = navMeshQuery.computePath(start, end);
|
const { path: segmentPath } = navMeshQuery.computePath(start, end);
|
||||||
|
@ -57,7 +56,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||||
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) &&
|
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) &&
|
||||||
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z)
|
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z)
|
||||||
) {
|
) {
|
||||||
console.log('if ', segmentPath);
|
|
||||||
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
|
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
|
||||||
} else {
|
} else {
|
||||||
console.log("There is no path here...Choose valid path")
|
console.log("There is no path here...Choose valid path")
|
||||||
|
|
|
@ -43,7 +43,7 @@ const UserAuth: React.FC = () => {
|
||||||
const organization = email.split("@")[1].split(".")[0];
|
const organization = email.split("@")[1].split(".")[0];
|
||||||
try {
|
try {
|
||||||
const res = await signInApi(email, password, organization, fingerprint);
|
const res = await signInApi(email, password, organization, fingerprint);
|
||||||
console.log('res: ', res);
|
// console.log('res: ', res);
|
||||||
if (res.message.message === "login successfull") {
|
if (res.message.message === "login successfull") {
|
||||||
setError("");
|
setError("");
|
||||||
setOrganization(organization);
|
setOrganization(organization);
|
||||||
|
@ -56,10 +56,10 @@ const UserAuth: React.FC = () => {
|
||||||
localStorage.setItem("refreshToken", res.message.refreshToken);
|
localStorage.setItem("refreshToken", res.message.refreshToken);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('res.message.userId: ', res.message.userId);
|
// console.log('res.message.userId: ', res.message.userId);
|
||||||
console.log('organization: ', organization);
|
// console.log('organization: ', organization);
|
||||||
const projects = await recentlyViewed(organization, res.message.userId);
|
const projects = await recentlyViewed(organization, res.message.userId);
|
||||||
console.log('projects: ', projects);
|
// console.log('projects: ', projects);
|
||||||
|
|
||||||
if (res.message.isShare) {
|
if (res.message.isShare) {
|
||||||
if (Object.values(projects.RecentlyViewed).length > 0) {
|
if (Object.values(projects.RecentlyViewed).length > 0) {
|
||||||
|
|
|
@ -726,6 +726,8 @@ export interface CompareProduct {
|
||||||
// totalCost: number;
|
// totalCost: number;
|
||||||
// revenueGenerated: number;
|
// revenueGenerated: number;
|
||||||
netProfit: number;
|
netProfit: number;
|
||||||
|
productionCapacity: number;
|
||||||
|
paybackPeriod: number;
|
||||||
// netLoss: number;
|
// netLoss: number;
|
||||||
machineIdleTime: number;
|
machineIdleTime: number;
|
||||||
machineActiveTime: number;
|
machineActiveTime: number;
|
||||||
|
|
|
@ -64,13 +64,14 @@
|
||||||
.production-details {
|
.production-details {
|
||||||
.production-wrapper {
|
.production-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
justify-content: start;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue