Refactor loading state management and enhance data handling in analysis components
This commit is contained in:
parent
952602469d
commit
d88e93395f
|
@ -91,11 +91,12 @@ const ThroughputSummary: React.FC = () => {
|
|||
|
||||
useEffect(() => {
|
||||
if (productionCapacityData >= 0) {
|
||||
setIsLoading(true);
|
||||
console.log('productionCapacityData: ', productionCapacityData);
|
||||
setIsLoading(false);
|
||||
console.log("productionCapacityData: ", productionCapacityData);
|
||||
} else {
|
||||
setIsLoading(true);
|
||||
}
|
||||
|
||||
}, [productionCapacityData])
|
||||
}, [productionCapacityData]);
|
||||
|
||||
return (
|
||||
<div className="production analysis-card">
|
||||
|
|
|
@ -85,16 +85,13 @@ const ROISummary = ({
|
|||
const { roiSummary } = useROISummaryData();
|
||||
|
||||
useEffect(() => {
|
||||
if (roiSummary && typeof roiSummary === 'object') {
|
||||
|
||||
if (roiSummary && typeof roiSummary === "object") {
|
||||
console.log('roiSummary: ', roiSummary);
|
||||
setIsLoading(true)
|
||||
setIsLoading(false); // Data loaded
|
||||
} else {
|
||||
setIsLoading(true); // Show skeleton while loading
|
||||
}
|
||||
|
||||
}, [roiSummary])
|
||||
|
||||
|
||||
|
||||
}, [roiSummary]);
|
||||
|
||||
return (
|
||||
<div className="roiSummary-container analysis-card">
|
||||
|
@ -113,13 +110,13 @@ const ROISummary = ({
|
|||
<div className="product-info">
|
||||
<ROISummaryProductName />
|
||||
<div className="product-label">Product :</div>
|
||||
<div className="product-name">{roiSummaryData.productName}</div>
|
||||
<div className="product-name">{roiSummary.productName}</div>
|
||||
</div>
|
||||
<div className="playBack">
|
||||
<SonarCrownIcon />
|
||||
<div className="icon"></div>
|
||||
<div className="info">
|
||||
<span>+{roiSummary.roiPercentage}%</span> ROI with payback
|
||||
<span> {roiSummary.roiPercentage}%</span> ROI with payback
|
||||
in just <span>{roiSummary.paybackPeriod}</span> months
|
||||
</div>
|
||||
</div>
|
||||
|
@ -150,8 +147,7 @@ const ROISummary = ({
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`metric-item net-profit ${roiSummary.netProfit ?? "loss"
|
||||
}`}
|
||||
className={`metric-item net-profit ${roiSummary.netProfit > 0 ? "profit" : "loss"}`}
|
||||
>
|
||||
<div className="metric-label">
|
||||
<span>↑</span>
|
||||
|
@ -159,7 +155,7 @@ const ROISummary = ({
|
|||
</div>
|
||||
<div className="metric-value">
|
||||
<span>₹</span>
|
||||
{roiSummary.netProfit
|
||||
{roiSummary.netProfit > 0
|
||||
? roiSummary.netProfit
|
||||
: roiSummary.netLoss}
|
||||
</div>
|
||||
|
@ -241,6 +237,7 @@ const ROISummary = ({
|
|||
</>
|
||||
) : (
|
||||
<SkeletonUI type={"default"} />
|
||||
// <div> No Data</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
||||
import { useActiveTool } from "../../../store/builder/store";
|
||||
import { useActiveTool, useProcessBar } from "../../../store/builder/store";
|
||||
import {
|
||||
useAnimationPlaySpeed,
|
||||
usePauseButtonStore,
|
||||
|
@ -109,21 +109,25 @@ const SimulationPlayer: React.FC = () => {
|
|||
const hourlySimulation = 25;
|
||||
const dailyProduction = 75;
|
||||
const monthlyROI = 50;
|
||||
const { processBar, setProcessBar } = useProcessBar();
|
||||
// const process = [
|
||||
// { name: "process 1", completed: 0 }, // 0% completed
|
||||
// { name: "process 2", completed: 20 }, // 20% completed
|
||||
// { name: "process 3", completed: 40 }, // 40% completed
|
||||
// { name: "process 4", completed: 60 }, // 60% completed
|
||||
// { name: "process 5", completed: 80 }, // 80% completed
|
||||
// { name: "process 6", completed: 100 }, // 100% completed
|
||||
// { name: "process 7", completed: 0 }, // 0% completed
|
||||
// { name: "process 8", completed: 50 }, // 50% completed
|
||||
// { name: "process 9", completed: 90 }, // 90% completed
|
||||
// { name: "process 10", completed: 30 }, // 30% completed
|
||||
// ];
|
||||
|
||||
const process = [
|
||||
{ name: "process 1", completed: 0 }, // 0% completed
|
||||
{ name: "process 2", completed: 20 }, // 20% completed
|
||||
{ name: "process 3", completed: 40 }, // 40% completed
|
||||
{ name: "process 4", completed: 60 }, // 60% completed
|
||||
{ name: "process 5", completed: 80 }, // 80% completed
|
||||
{ name: "process 6", completed: 100 }, // 100% completed
|
||||
{ name: "process 7", completed: 0 }, // 0% completed
|
||||
{ name: "process 8", completed: 50 }, // 50% completed
|
||||
{ name: "process 9", completed: 90 }, // 90% completed
|
||||
{ name: "process 10", completed: 30 }, // 30% completed
|
||||
];
|
||||
useEffect(() => {
|
||||
// console.log('processBar: ', processBar);
|
||||
}, [processBar])
|
||||
|
||||
const intervals = [10, 20, 30, 40, 50, 60]; // in minutes
|
||||
const intervals = [50, 20, 30, 40, 50, 60]; // in minutes
|
||||
const totalSegments = intervals.length;
|
||||
const progress = 20; // percent (example)
|
||||
|
||||
|
@ -285,11 +289,10 @@ const SimulationPlayer: React.FC = () => {
|
|||
</div>
|
||||
{index < intervals.length - 1 && (
|
||||
<div
|
||||
className={`line ${
|
||||
progress >= ((index + 1) / totalSegments) * 100
|
||||
? "filled"
|
||||
: ""
|
||||
}`}
|
||||
className={`line ${progress >= ((index + 1) / totalSegments) * 100
|
||||
? "filled"
|
||||
: ""
|
||||
}`}
|
||||
></div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
|
@ -328,9 +331,8 @@ const SimulationPlayer: React.FC = () => {
|
|||
<div className="custom-slider-wrapper">
|
||||
<div className="custom-slider">
|
||||
<button
|
||||
className={`slider-handle ${
|
||||
isDragging ? "dragging" : ""
|
||||
}`}
|
||||
className={`slider-handle ${isDragging ? "dragging" : ""
|
||||
}`}
|
||||
style={{ left: `${calculateHandlePosition()}%` }}
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
|
@ -365,22 +367,26 @@ const SimulationPlayer: React.FC = () => {
|
|||
ref={processWrapperRef}
|
||||
onMouseDown={handleProcessMouseDown}
|
||||
>
|
||||
{process.map((item, index) => (
|
||||
<div
|
||||
key={`${index}-${item.name}`}
|
||||
className="process"
|
||||
style={{
|
||||
width: `${item.completed}%`,
|
||||
backgroundColor: getAvatarColor(index),
|
||||
}}
|
||||
>
|
||||
{processBar?.length > 0 ? (
|
||||
processBar.map((item: any, index: any) => (
|
||||
<div
|
||||
className="process-player"
|
||||
ref={processPlayerRef}
|
||||
style={{ left: playerPosition, position: "absolute" }}
|
||||
></div>
|
||||
</div>
|
||||
))}
|
||||
key={`${index}-${item.name}`}
|
||||
className="process"
|
||||
style={{
|
||||
width: `${item.completed}%`,
|
||||
backgroundColor: getAvatarColor(index),
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="process-player"
|
||||
ref={processPlayerRef}
|
||||
style={{ left: playerPosition, position: "absolute" }}
|
||||
></div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div>No process data available</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { useInputValues, useProductionCapacityData, useROISummaryData } from '../../../../store/builder/store';
|
||||
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
|
||||
|
||||
export default function ROIData() {
|
||||
const { inputValues } = useInputValues();
|
||||
const { productionCapacityData } = useProductionCapacityData()
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
|
||||
|
||||
const { setRoiSummaryData } = useROISummaryData();
|
||||
|
@ -42,6 +44,11 @@ export default function ROIData() {
|
|||
console.log('RevenueForYear: ', RevenueForYear);
|
||||
|
||||
//Costs
|
||||
|
||||
let materialCount = 1200;
|
||||
|
||||
//Material Cost
|
||||
|
||||
let MaterialCost = productionCapacityData * materialCost
|
||||
console.log('MaterialCost: ', MaterialCost);
|
||||
let LaborCost = laborCost * shiftLength * shiftsPerDay * workingDaysPerYear;
|
||||
|
@ -52,7 +59,7 @@ export default function ROIData() {
|
|||
console.log('MaintenceCost: ', MaintenceCost);
|
||||
|
||||
//Total Anuual Cost
|
||||
let TotalAnnualCost = MaterialCost + LaborCost + EnergyCost + MaintenceCost;
|
||||
let TotalAnnualCost = (MaterialCost * materialCount) + LaborCost + EnergyCost + MaintenceCost;
|
||||
console.log('TotalAnnualCost: ', TotalAnnualCost);
|
||||
|
||||
|
||||
|
@ -73,11 +80,12 @@ export default function ROIData() {
|
|||
// Payback Period
|
||||
const paybackPeriod = initialInvestment / ProfitforYear;
|
||||
console.log('paybackPeriod: ', paybackPeriod);
|
||||
|
||||
|
||||
|
||||
setRoiSummaryData({
|
||||
roiPercentage: ROIData,
|
||||
paybackPeriod,
|
||||
productName: selectedProduct.productName,
|
||||
roiPercentage: parseFloat((ROIData / 100).toFixed(2)),
|
||||
paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
|
||||
totalCost: TotalAnnualCost,
|
||||
revenueGenerated: RevenueForYear,
|
||||
netProfit: NetProfit > 0 ? NetProfit : 0,
|
||||
|
|
|
@ -28,18 +28,14 @@ export default function ProductionCapacityData() {
|
|||
console.log('afterYield: ', afterYield.toFixed(2));
|
||||
//Annual Output
|
||||
const annualProduction = afterYield * workingDaysPerYear;
|
||||
console.log('annualProduction: ', annualProduction.toFixed(2));
|
||||
setProductionCapacityData(annualProduction);
|
||||
console.log('annualProduction: ', Number(annualProduction.toFixed(2)));
|
||||
//Production per Hour
|
||||
const productionPerHour = throughputData * (yieldRate / 100);
|
||||
console.log('productionPerHour: ', productionPerHour);
|
||||
setProductionCapacityData(Number(productionPerHour.toFixed(2)));
|
||||
}
|
||||
}, [throughputData, inputValues]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useSelectedProduct } from '../../../../store/simulation/useSimulationSt
|
|||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
|
||||
import { useArmBotStore } from '../../../../store/simulation/useArmBotStore';
|
||||
import { useMachineCount, useMachineUptime, useMaterialCycle, useThroughPutData } from '../../../../store/builder/store';
|
||||
import { useMachineCount, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
|
||||
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
||||
import { useMachineStore } from '../../../../store/simulation/useMachineStore';
|
||||
import { useConveyorStore } from '../../../../store/simulation/useConveyorStore';
|
||||
|
@ -25,6 +25,7 @@ export default function ThroughPutData() {
|
|||
const { machineActiveTime, setMachineActiveTime } = useMachineUptime();
|
||||
|
||||
const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle();
|
||||
const { processBar, setProcessBar } = useProcessBar();
|
||||
|
||||
// const [totalActiveTime, setTotalActiveTime] = useState(0);
|
||||
const { setThroughputData } = useThroughPutData() // <=== ADD THIS
|
||||
|
@ -32,7 +33,8 @@ export default function ThroughPutData() {
|
|||
|
||||
// Setting machine count
|
||||
useEffect(() => {
|
||||
if (materialCycleTime < 0) return
|
||||
if (materialCycleTime <= 0) return
|
||||
let process: any = [];
|
||||
const fetchProductSequenceData = async () => {
|
||||
const productData = getProductById(selectedProduct.productId);
|
||||
if (productData) {
|
||||
|
@ -42,45 +44,45 @@ export default function ThroughPutData() {
|
|||
let totalActiveTime = 0;
|
||||
productSequenceData.forEach((sequence) => {
|
||||
sequence.forEach((item) => {
|
||||
|
||||
if (item.type === "roboticArm") {
|
||||
armBots.filter(arm => arm.modelUuid === item.modelUuid)
|
||||
.forEach(arm => {
|
||||
|
||||
if (arm.activeTime >= 0) {
|
||||
process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime })
|
||||
totalActiveTime += arm.activeTime;
|
||||
}
|
||||
});
|
||||
} else if (item.type === "vehicle") {
|
||||
vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid)
|
||||
.forEach(vehicle => {
|
||||
|
||||
if (vehicle.activeTime >= 0) {
|
||||
// totalActiveTime += vehicle.activeTime;
|
||||
totalActiveTime += 34;
|
||||
process.push({ modelid: vehicle.modelUuid, modelName: vehicle.modelName, activeTime: vehicle?.activeTime })
|
||||
|
||||
totalActiveTime += vehicle.activeTime;
|
||||
}
|
||||
});
|
||||
} else if (item.type === "machine") {
|
||||
machines.filter(machine => machine.modelUuid === item.modelUuid)
|
||||
.forEach(machine => {
|
||||
if (machine.activeTime >= 0) {
|
||||
// totalActiveTime += machine.activeTime;
|
||||
totalActiveTime += 12;
|
||||
process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime })
|
||||
totalActiveTime += machine.activeTime;
|
||||
}
|
||||
});
|
||||
} else if (item.type === "transfer") {
|
||||
conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid)
|
||||
.forEach(conveyor => {
|
||||
if (conveyor.activeTime >= 0) {
|
||||
// totalActiveTime += conveyor.activeTime;
|
||||
totalActiveTime += 89;
|
||||
totalActiveTime += conveyor.activeTime;
|
||||
}
|
||||
});
|
||||
} else if (item.type === "storageUnit") {
|
||||
storageUnits.filter(storage => storage.modelUuid === item.modelUuid)
|
||||
.forEach(storage => {
|
||||
if (storage.activeTime >= 0) {
|
||||
// totalActiveTime += storage.activeTime;
|
||||
totalActiveTime += 45;
|
||||
totalActiveTime += storage.activeTime;
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -90,13 +92,20 @@ export default function ThroughPutData() {
|
|||
|
||||
setMachineCount(totalItems);
|
||||
setMachineActiveTime(totalActiveTime);
|
||||
let arr = process.map((item: any) => ({
|
||||
name: item.modelName,
|
||||
completed: Math.round((item.activeTime / totalActiveTime) * 100)
|
||||
}));
|
||||
setProcessBar(arr);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchProductSequenceData();
|
||||
}, [products, selectedProduct, getProductById, setMachineCount, isPlaying, armBots, materialCycleTime]);
|
||||
}, [products, selectedProduct, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]);
|
||||
|
||||
// Setting material cycle time
|
||||
useEffect(() => {
|
||||
|
@ -106,8 +115,8 @@ export default function ThroughPutData() {
|
|||
|
||||
if (start === 0 || end === 0) return;
|
||||
|
||||
const totalCycleTime = end - start;
|
||||
setMaterialCycleTime(totalCycleTime.toFixed(2)); // Set the material cycle time in the store
|
||||
const totalCycleTime = (end - start) / 1000; // Convert milliseconds to seconds
|
||||
setMaterialCycleTime(Number(totalCycleTime.toFixed(2))); // Set the material cycle time in the store
|
||||
});
|
||||
}, [materialHistory]);
|
||||
|
||||
|
@ -115,16 +124,21 @@ export default function ThroughPutData() {
|
|||
|
||||
useEffect(() => {
|
||||
if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0) {
|
||||
const avgProcessTime = (machineActiveTime / materialCycleTime) * 100; // % value
|
||||
const throughput = (3600 / materialCycleTime) * machineCount * (avgProcessTime / 100); // ✅ division by 100
|
||||
const avgProcessTime = (machineActiveTime / materialCycleTime) * 100;
|
||||
const throughput = (3600 / materialCycleTime) * machineCount * (avgProcessTime / 100);
|
||||
setThroughputData(throughput.toFixed(2)); // Set the throughput data in the store
|
||||
|
||||
|
||||
console.log('---Throughput Results---');
|
||||
console.log('Total Active Time:', machineActiveTime);
|
||||
console.log('Material Cycle Time:', materialCycleTime);
|
||||
console.log('Machine Count:', machineCount);
|
||||
console.log('Average Process Time (%):', avgProcessTime);
|
||||
console.log('Calculated Throughput:', throughput);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}, [machineActiveTime, materialCycleTime, machineCount]);
|
||||
|
||||
|
|
|
@ -475,6 +475,11 @@ export const useProductionCapacityData = create<any>((set: any) => ({
|
|||
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
|
||||
}));
|
||||
|
||||
export const useProcessBar = create<any>((set: any) => ({
|
||||
processBar: [],
|
||||
setProcessBar: (x: any) => set({ processBar: x }),
|
||||
}));
|
||||
|
||||
|
||||
type InputValuesStore = {
|
||||
inputValues: Record<string, string>;
|
||||
|
@ -495,6 +500,7 @@ export const useInputValues = create<InputValuesStore>((set) => ({
|
|||
}));
|
||||
|
||||
export interface ROISummaryData {
|
||||
productName: string;
|
||||
roiPercentage: number;
|
||||
paybackPeriod: number;
|
||||
totalCost: number;
|
||||
|
@ -510,6 +516,7 @@ interface ROISummaryStore {
|
|||
|
||||
export const useROISummaryData = create<ROISummaryStore>((set) => ({
|
||||
roiSummary: {
|
||||
productName: "",
|
||||
roiPercentage: 0,
|
||||
paybackPeriod: 0,
|
||||
totalCost: 0,
|
||||
|
@ -518,4 +525,6 @@ export const useROISummaryData = create<ROISummaryStore>((set) => ({
|
|||
netLoss: 0,
|
||||
},
|
||||
setRoiSummaryData: (values) => set({ roiSummary: values }),
|
||||
}));
|
||||
}));
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue