Refactor loading state management and enhance data handling in analysis components

This commit is contained in:
Gomathi 2025-05-14 18:21:49 +05:30
parent 952602469d
commit d88e93395f
7 changed files with 116 additions and 85 deletions

View File

@ -91,11 +91,12 @@ const ThroughputSummary: React.FC = () => {
useEffect(() => { useEffect(() => {
if (productionCapacityData >= 0) { if (productionCapacityData >= 0) {
setIsLoading(true); setIsLoading(false);
console.log('productionCapacityData: ', productionCapacityData); console.log("productionCapacityData: ", productionCapacityData);
} else {
setIsLoading(true);
} }
}, [productionCapacityData]);
}, [productionCapacityData])
return ( return (
<div className="production analysis-card"> <div className="production analysis-card">

View File

@ -85,16 +85,13 @@ const ROISummary = ({
const { roiSummary } = useROISummaryData(); const { roiSummary } = useROISummaryData();
useEffect(() => { useEffect(() => {
if (roiSummary && typeof roiSummary === 'object') { if (roiSummary && typeof roiSummary === "object") {
console.log('roiSummary: ', roiSummary); console.log('roiSummary: ', roiSummary);
setIsLoading(true) setIsLoading(false); // Data loaded
} else {
setIsLoading(true); // Show skeleton while loading
} }
}, [roiSummary]);
}, [roiSummary])
return ( return (
<div className="roiSummary-container analysis-card"> <div className="roiSummary-container analysis-card">
@ -113,13 +110,13 @@ const ROISummary = ({
<div className="product-info"> <div className="product-info">
<ROISummaryProductName /> <ROISummaryProductName />
<div className="product-label">Product :</div> <div className="product-label">Product :</div>
<div className="product-name">{roiSummaryData.productName}</div> <div className="product-name">{roiSummary.productName}</div>
</div> </div>
<div className="playBack"> <div className="playBack">
<SonarCrownIcon /> <SonarCrownIcon />
<div className="icon"></div> <div className="icon"></div>
<div className="info"> <div className="info">
<span>+{roiSummary.roiPercentage}%</span> ROI with payback <span> {roiSummary.roiPercentage}%</span> ROI with payback
in just <span>{roiSummary.paybackPeriod}</span> months in just <span>{roiSummary.paybackPeriod}</span> months
</div> </div>
</div> </div>
@ -150,8 +147,7 @@ const ROISummary = ({
</div> </div>
</div> </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"> <div className="metric-label">
<span></span> <span></span>
@ -159,7 +155,7 @@ const ROISummary = ({
</div> </div>
<div className="metric-value"> <div className="metric-value">
<span></span> <span></span>
{roiSummary.netProfit {roiSummary.netProfit > 0
? roiSummary.netProfit ? roiSummary.netProfit
: roiSummary.netLoss} : roiSummary.netLoss}
</div> </div>
@ -241,6 +237,7 @@ const ROISummary = ({
</> </>
) : ( ) : (
<SkeletonUI type={"default"} /> <SkeletonUI type={"default"} />
// <div> No Data</div>
)} )}
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons"; import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
import { useActiveTool } from "../../../store/builder/store"; import { useActiveTool, useProcessBar } from "../../../store/builder/store";
import { import {
useAnimationPlaySpeed, useAnimationPlaySpeed,
usePauseButtonStore, usePauseButtonStore,
@ -109,21 +109,25 @@ const SimulationPlayer: React.FC = () => {
const hourlySimulation = 25; const hourlySimulation = 25;
const dailyProduction = 75; const dailyProduction = 75;
const monthlyROI = 50; 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 = [ useEffect(() => {
{ name: "process 1", completed: 0 }, // 0% completed // console.log('processBar: ', processBar);
{ name: "process 2", completed: 20 }, // 20% completed }, [processBar])
{ 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 intervals = [10, 20, 30, 40, 50, 60]; // in minutes const intervals = [50, 20, 30, 40, 50, 60]; // in minutes
const totalSegments = intervals.length; const totalSegments = intervals.length;
const progress = 20; // percent (example) const progress = 20; // percent (example)
@ -285,11 +289,10 @@ const SimulationPlayer: React.FC = () => {
</div> </div>
{index < intervals.length - 1 && ( {index < intervals.length - 1 && (
<div <div
className={`line ${ className={`line ${progress >= ((index + 1) / totalSegments) * 100
progress >= ((index + 1) / totalSegments) * 100 ? "filled"
? "filled" : ""
: "" }`}
}`}
></div> ></div>
)} )}
</React.Fragment> </React.Fragment>
@ -328,9 +331,8 @@ const SimulationPlayer: React.FC = () => {
<div className="custom-slider-wrapper"> <div className="custom-slider-wrapper">
<div className="custom-slider"> <div className="custom-slider">
<button <button
className={`slider-handle ${ className={`slider-handle ${isDragging ? "dragging" : ""
isDragging ? "dragging" : "" }`}
}`}
style={{ left: `${calculateHandlePosition()}%` }} style={{ left: `${calculateHandlePosition()}%` }}
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
> >
@ -365,22 +367,26 @@ const SimulationPlayer: React.FC = () => {
ref={processWrapperRef} ref={processWrapperRef}
onMouseDown={handleProcessMouseDown} onMouseDown={handleProcessMouseDown}
> >
{process.map((item, index) => ( {processBar?.length > 0 ? (
<div processBar.map((item: any, index: any) => (
key={`${index}-${item.name}`}
className="process"
style={{
width: `${item.completed}%`,
backgroundColor: getAvatarColor(index),
}}
>
<div <div
className="process-player" key={`${index}-${item.name}`}
ref={processPlayerRef} className="process"
style={{ left: playerPosition, position: "absolute" }} style={{
></div> width: `${item.completed}%`,
</div> 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> </div>
</div> </div>

View File

@ -1,9 +1,11 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useInputValues, useProductionCapacityData, useROISummaryData } from '../../../../store/builder/store'; import { useInputValues, useProductionCapacityData, useROISummaryData } from '../../../../store/builder/store';
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
export default function ROIData() { export default function ROIData() {
const { inputValues } = useInputValues(); const { inputValues } = useInputValues();
const { productionCapacityData } = useProductionCapacityData() const { productionCapacityData } = useProductionCapacityData()
const { selectedProduct } = useSelectedProduct();
const { setRoiSummaryData } = useROISummaryData(); const { setRoiSummaryData } = useROISummaryData();
@ -42,6 +44,11 @@ export default function ROIData() {
console.log('RevenueForYear: ', RevenueForYear); console.log('RevenueForYear: ', RevenueForYear);
//Costs //Costs
let materialCount = 1200;
//Material Cost
let MaterialCost = productionCapacityData * materialCost let MaterialCost = productionCapacityData * materialCost
console.log('MaterialCost: ', MaterialCost); console.log('MaterialCost: ', MaterialCost);
let LaborCost = laborCost * shiftLength * shiftsPerDay * workingDaysPerYear; let LaborCost = laborCost * shiftLength * shiftsPerDay * workingDaysPerYear;
@ -52,7 +59,7 @@ export default function ROIData() {
console.log('MaintenceCost: ', MaintenceCost); console.log('MaintenceCost: ', MaintenceCost);
//Total Anuual Cost //Total Anuual Cost
let TotalAnnualCost = MaterialCost + LaborCost + EnergyCost + MaintenceCost; let TotalAnnualCost = (MaterialCost * materialCount) + LaborCost + EnergyCost + MaintenceCost;
console.log('TotalAnnualCost: ', TotalAnnualCost); console.log('TotalAnnualCost: ', TotalAnnualCost);
@ -73,11 +80,12 @@ export default function ROIData() {
// Payback Period // Payback Period
const paybackPeriod = initialInvestment / ProfitforYear; const paybackPeriod = initialInvestment / ProfitforYear;
console.log('paybackPeriod: ', paybackPeriod); console.log('paybackPeriod: ', paybackPeriod);
setRoiSummaryData({ setRoiSummaryData({
roiPercentage: ROIData, productName: selectedProduct.productName,
paybackPeriod, roiPercentage: parseFloat((ROIData / 100).toFixed(2)),
paybackPeriod: parseFloat(paybackPeriod.toFixed(2)),
totalCost: TotalAnnualCost, totalCost: TotalAnnualCost,
revenueGenerated: RevenueForYear, revenueGenerated: RevenueForYear,
netProfit: NetProfit > 0 ? NetProfit : 0, netProfit: NetProfit > 0 ? NetProfit : 0,

View File

@ -28,18 +28,14 @@ export default function ProductionCapacityData() {
console.log('afterYield: ', afterYield.toFixed(2)); console.log('afterYield: ', afterYield.toFixed(2));
//Annual Output //Annual Output
const annualProduction = afterYield * workingDaysPerYear; const annualProduction = afterYield * workingDaysPerYear;
console.log('annualProduction: ', annualProduction.toFixed(2)); console.log('annualProduction: ', Number(annualProduction.toFixed(2)));
setProductionCapacityData(annualProduction); //Production per Hour
const productionPerHour = throughputData * (yieldRate / 100);
console.log('productionPerHour: ', productionPerHour);
setProductionCapacityData(Number(productionPerHour.toFixed(2)));
} }
}, [throughputData, inputValues]); }, [throughputData, inputValues]);
useEffect(() => {
}, [])
return ( return (
<></> <></>
) )

View File

@ -3,7 +3,7 @@ import { useSelectedProduct } from '../../../../store/simulation/useSimulationSt
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 { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; 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 { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
import { useMachineStore } from '../../../../store/simulation/useMachineStore'; import { useMachineStore } from '../../../../store/simulation/useMachineStore';
import { useConveyorStore } from '../../../../store/simulation/useConveyorStore'; import { useConveyorStore } from '../../../../store/simulation/useConveyorStore';
@ -25,6 +25,7 @@ export default function ThroughPutData() {
const { machineActiveTime, setMachineActiveTime } = useMachineUptime(); const { machineActiveTime, setMachineActiveTime } = useMachineUptime();
const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle(); const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle();
const { processBar, setProcessBar } = useProcessBar();
// const [totalActiveTime, setTotalActiveTime] = useState(0); // const [totalActiveTime, setTotalActiveTime] = useState(0);
const { setThroughputData } = useThroughPutData() // <=== ADD THIS const { setThroughputData } = useThroughPutData() // <=== ADD THIS
@ -32,7 +33,8 @@ export default function ThroughPutData() {
// Setting machine count // Setting machine count
useEffect(() => { useEffect(() => {
if (materialCycleTime < 0) return if (materialCycleTime <= 0) return
let process: any = [];
const fetchProductSequenceData = async () => { const fetchProductSequenceData = async () => {
const productData = getProductById(selectedProduct.productId); const productData = getProductById(selectedProduct.productId);
if (productData) { if (productData) {
@ -42,45 +44,45 @@ export default function ThroughPutData() {
let totalActiveTime = 0; let totalActiveTime = 0;
productSequenceData.forEach((sequence) => { productSequenceData.forEach((sequence) => {
sequence.forEach((item) => { sequence.forEach((item) => {
if (item.type === "roboticArm") { if (item.type === "roboticArm") {
armBots.filter(arm => arm.modelUuid === item.modelUuid) armBots.filter(arm => arm.modelUuid === item.modelUuid)
.forEach(arm => { .forEach(arm => {
if (arm.activeTime >= 0) { if (arm.activeTime >= 0) {
process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime })
totalActiveTime += arm.activeTime; totalActiveTime += arm.activeTime;
} }
}); });
} else if (item.type === "vehicle") { } else if (item.type === "vehicle") {
vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid) vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid)
.forEach(vehicle => { .forEach(vehicle => {
if (vehicle.activeTime >= 0) { if (vehicle.activeTime >= 0) {
// totalActiveTime += vehicle.activeTime; process.push({ modelid: vehicle.modelUuid, modelName: vehicle.modelName, activeTime: vehicle?.activeTime })
totalActiveTime += 34;
totalActiveTime += vehicle.activeTime;
} }
}); });
} else if (item.type === "machine") { } else if (item.type === "machine") {
machines.filter(machine => machine.modelUuid === item.modelUuid) machines.filter(machine => machine.modelUuid === item.modelUuid)
.forEach(machine => { .forEach(machine => {
if (machine.activeTime >= 0) { if (machine.activeTime >= 0) {
// totalActiveTime += machine.activeTime; process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime })
totalActiveTime += 12; totalActiveTime += machine.activeTime;
} }
}); });
} else if (item.type === "transfer") { } else if (item.type === "transfer") {
conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid) conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid)
.forEach(conveyor => { .forEach(conveyor => {
if (conveyor.activeTime >= 0) { if (conveyor.activeTime >= 0) {
// totalActiveTime += conveyor.activeTime; totalActiveTime += conveyor.activeTime;
totalActiveTime += 89;
} }
}); });
} else if (item.type === "storageUnit") { } else if (item.type === "storageUnit") {
storageUnits.filter(storage => storage.modelUuid === item.modelUuid) storageUnits.filter(storage => storage.modelUuid === item.modelUuid)
.forEach(storage => { .forEach(storage => {
if (storage.activeTime >= 0) { if (storage.activeTime >= 0) {
// totalActiveTime += storage.activeTime; totalActiveTime += storage.activeTime;
totalActiveTime += 45;
} }
}); });
} }
@ -90,13 +92,20 @@ export default function ThroughPutData() {
setMachineCount(totalItems); setMachineCount(totalItems);
setMachineActiveTime(totalActiveTime); setMachineActiveTime(totalActiveTime);
let arr = process.map((item: any) => ({
name: item.modelName,
completed: Math.round((item.activeTime / totalActiveTime) * 100)
}));
setProcessBar(arr);
} }
} }
}; };
fetchProductSequenceData(); fetchProductSequenceData();
}, [products, selectedProduct, getProductById, setMachineCount, isPlaying, armBots, materialCycleTime]); }, [products, selectedProduct, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]);
// Setting material cycle time // Setting material cycle time
useEffect(() => { useEffect(() => {
@ -106,8 +115,8 @@ export default function ThroughPutData() {
if (start === 0 || end === 0) return; if (start === 0 || end === 0) return;
const totalCycleTime = end - start; const totalCycleTime = (end - start) / 1000; // Convert milliseconds to seconds
setMaterialCycleTime(totalCycleTime.toFixed(2)); // Set the material cycle time in the store setMaterialCycleTime(Number(totalCycleTime.toFixed(2))); // Set the material cycle time in the store
}); });
}, [materialHistory]); }, [materialHistory]);
@ -115,16 +124,21 @@ export default function ThroughPutData() {
useEffect(() => { useEffect(() => {
if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0) { if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0) {
const avgProcessTime = (machineActiveTime / materialCycleTime) * 100; // % value const avgProcessTime = (machineActiveTime / materialCycleTime) * 100;
const throughput = (3600 / materialCycleTime) * machineCount * (avgProcessTime / 100); // ✅ division by 100 const throughput = (3600 / materialCycleTime) * machineCount * (avgProcessTime / 100);
setThroughputData(throughput.toFixed(2)); // Set the throughput data in the store setThroughputData(throughput.toFixed(2)); // Set the throughput data in the store
console.log('---Throughput Results---'); console.log('---Throughput Results---');
console.log('Total Active Time:', machineActiveTime); console.log('Total Active Time:', machineActiveTime);
console.log('Material Cycle Time:', materialCycleTime); console.log('Material Cycle Time:', materialCycleTime);
console.log('Machine Count:', machineCount); console.log('Machine Count:', machineCount);
console.log('Average Process Time (%):', avgProcessTime); console.log('Average Process Time (%):', avgProcessTime);
console.log('Calculated Throughput:', throughput); console.log('Calculated Throughput:', throughput);
} }
}, [machineActiveTime, materialCycleTime, machineCount]); }, [machineActiveTime, materialCycleTime, machineCount]);

View File

@ -475,6 +475,11 @@ export const useProductionCapacityData = create<any>((set: any) => ({
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }), setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
})); }));
export const useProcessBar = create<any>((set: any) => ({
processBar: [],
setProcessBar: (x: any) => set({ processBar: x }),
}));
type InputValuesStore = { type InputValuesStore = {
inputValues: Record<string, string>; inputValues: Record<string, string>;
@ -495,6 +500,7 @@ export const useInputValues = create<InputValuesStore>((set) => ({
})); }));
export interface ROISummaryData { export interface ROISummaryData {
productName: string;
roiPercentage: number; roiPercentage: number;
paybackPeriod: number; paybackPeriod: number;
totalCost: number; totalCost: number;
@ -510,6 +516,7 @@ interface ROISummaryStore {
export const useROISummaryData = create<ROISummaryStore>((set) => ({ export const useROISummaryData = create<ROISummaryStore>((set) => ({
roiSummary: { roiSummary: {
productName: "",
roiPercentage: 0, roiPercentage: 0,
paybackPeriod: 0, paybackPeriod: 0,
totalCost: 0, totalCost: 0,
@ -518,4 +525,6 @@ export const useROISummaryData = create<ROISummaryStore>((set) => ({
netLoss: 0, netLoss: 0,
}, },
setRoiSummaryData: (values) => set({ roiSummary: values }), setRoiSummaryData: (values) => set({ roiSummary: values }),
})); }));