feat: add loading state with timeout for ThroughputSummary and ROISummary components

This commit is contained in:
Gomathi 2025-06-09 18:10:37 +05:30
parent 3d9f625e3d
commit db8536100c
3 changed files with 194 additions and 180 deletions

View File

@ -91,8 +91,11 @@ const ThroughputSummary: React.FC = () => {
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
if (productionCapacityData >= 0) {
setIsLoading(false);
if (productionCapacityData >0) {
setTimeout(() => {
setIsLoading(false);
}, 3000);
console.log("productionCapacityData: ", productionCapacityData);
} else {
setIsLoading(true);
@ -100,7 +103,8 @@ const ThroughputSummary: React.FC = () => {
}, [productionCapacityData]);
return (
<div className="production analysis-card">
<>
{!isLoading && <div className="production analysis-card">
<div className="production-wrapper analysis-card-wrapper">
<div className="card-header">
<div className="header">
@ -184,7 +188,8 @@ const ThroughputSummary: React.FC = () => {
<SkeletonUI type={"default"} />
)}
</div>
</div>
</div>}
</>
);
};

View File

@ -84,135 +84,142 @@ const ROISummary = ({
const { roiSummary } = useROISummaryData();
useEffect(() => {
if (roiSummary && typeof roiSummary === "object") {
setIsLoading(false); // Data loaded
if (roiSummary.productName) {
// If productName is set, assume data is loaded
setTimeout(() => {
setIsLoading(false);
}, 3000);
// setIsLoading(false);
} else {
setIsLoading(true); // Show skeleton while loading
// If productName is empty, assume still loading
setIsLoading(true);
}
}, [roiSummary]);
return (
<div className="roiSummary-container analysis-card">
<div className="roiSummary-wrapper analysis-card-wrapper">
<div className="card-header">
<div className="header">
<div className="main-header">ROI Summary</div>
<div className="sub-header">From {getCurrentDate()}</div>
</div>
<div className="icon-wrapper">
<ROISummaryIcon />
</div>
</div>
{!isLoading ? (
<>
<div className="product-info">
<ROISummaryProductName />
<div className="product-label">Product :</div>
<div className="product-name">{roiSummary.productName}</div>
<>
{!isLoading && <div className="roiSummary-container analysis-card">
<div className="roiSummary-wrapper analysis-card-wrapper">
<div className="card-header">
<div className="header">
<div className="main-header">ROI Summary</div>
<div className="sub-header">From {getCurrentDate()}</div>
</div>
<div className="playBack">
<SonarCrownIcon />
<div className="icon"></div>
<div className="info">
<span> {roiSummary.roiPercentage}%</span> ROI with payback
in just <span>{roiSummary.paybackPeriod}</span> months
<div className="icon-wrapper">
<ROISummaryIcon />
</div>
</div>
{!isLoading ? (
<>
<div className="product-info">
<ROISummaryProductName />
<div className="product-label">Product :</div>
<div className="product-name">{roiSummary.productName}</div>
</div>
</div>
<div className="roi-details">
<div className="progress-wrapper">
<SemiCircleProgress />
<div className="content">
you're on track to hit it by
<div className="key">July 2029</div>
<div className="playBack">
<SonarCrownIcon />
<div className="icon"></div>
<div className="info">
<span> {roiSummary.roiPercentage}%</span> ROI with payback
in just <span>{roiSummary.paybackPeriod}</span> months
</div>
</div>
<div className="metrics">
<div className="metric-wrapper">
<div className="metric-item">
<span className="metric-label">Total Cost Incurred</span>
<span className="metric-value">
<span></span>
{roiSummary.totalCost}
</span>
<div className="roi-details">
<div className="progress-wrapper">
<SemiCircleProgress />
<div className="content">
you're on track to hit it by
<div className="key">July 2029</div>
</div>
<div className="metric-item">
<span className="metric-label">Revenue Generated</span>
<span className="metric-value">
<span></span>
</div>
<div className="metrics">
<div className="metric-wrapper">
<div className="metric-item">
<span className="metric-label">Total Cost Incurred</span>
<span className="metric-value">
<span></span>
{roiSummary.totalCost}
</span>
</div>
<div className="metric-item">
<span className="metric-label">Revenue Generated</span>
<span className="metric-value">
<span></span>
{roiSummary.revenueGenerated}
</span>
{roiSummary.revenueGenerated}
</span>
</div>
</div>
<div
className={`metric-item net-profit ${roiSummary.netProfit > 0 ? "profit" : "loss"}`}
>
<div className="metric-label">
<span></span>
Net Profit
</div>
<div className="metric-value">
<span></span>
{roiSummary.netProfit > 0
? roiSummary.netProfit
: roiSummary.netLoss}
</div>
</div>
</div>
</div>
<div className="cost-breakdown">
<div className="breakdown-header" onClick={toggleTable}>
<div className="section-wrapper">
<CostBreakDownIcon />
<span className="section-title">Cost Breakdown</span>
</div>
<span className={`expand-icon ${isTableOpen ? "open" : ""}`}>
<ArrowIcon />
</span>
</div>
<div
className={`metric-item net-profit ${roiSummary.netProfit > 0 ? "profit" : "loss"}`}
className={`breakdown-table-wrapper ${isTableOpen ? "open" : "closed"
}`}
style={{
transition: "max-height 0.3s ease-in-out",
overflow: "hidden",
}}
>
<div className="metric-label">
<span></span>
Net Profit
</div>
<div className="metric-value">
<span></span>
{roiSummary.netProfit > 0
? roiSummary.netProfit
: roiSummary.netLoss}
</div>
</div>
</div>
</div>
<div className="cost-breakdown">
<div className="breakdown-header" onClick={toggleTable}>
<div className="section-wrapper">
<CostBreakDownIcon />
<span className="section-title">Cost Breakdown</span>
</div>
<span className={`expand-icon ${isTableOpen ? "open" : ""}`}>
<ArrowIcon />
</span>
</div>
<div
className={`breakdown-table-wrapper ${isTableOpen ? "open" : "closed"
}`}
style={{
transition: "max-height 0.3s ease-in-out",
overflow: "hidden",
}}
>
<table className="breakdown-table">
<thead>
<tr>
<th>Item</th>
<th>Unit Cost</th>
<th>Labor Cost</th>
<th>Total Cost</th>
<th>Selling Price</th>
</tr>
</thead>
<tbody>
{roiSummaryData.costBreakdown.map((row, index) => (
<tr
key={index}
className={
row.item === "Total"
? "total-row"
: row.item === "Net Profit"
? "net-profit-row"
: ""
}
>
<td>{row.item}</td>
<td>{row.unitCost}</td>
<td>{row.laborCost}</td>
<td>{row.totalCost}</td>
<td>{row.sellingPrice}</td>
<table className="breakdown-table">
<thead>
<tr>
<th>Item</th>
<th>Unit Cost</th>
<th>Labor Cost</th>
<th>Total Cost</th>
<th>Selling Price</th>
</tr>
))}
</tbody>
</table>
</thead>
<tbody>
{roiSummaryData.costBreakdown.map((row, index) => (
<tr
key={index}
className={
row.item === "Total"
? "total-row"
: row.item === "Net Profit"
? "net-profit-row"
: ""
}
>
<td>{row.item}</td>
<td>{row.unitCost}</td>
<td>{row.laborCost}</td>
<td>{row.totalCost}</td>
<td>{row.sellingPrice}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
{/* <div className="tips-section">
{/* <div className="tips-section">
<div className="tip-header">
<span className="lightbulb-icon">
<LightBulpIcon />
@ -232,13 +239,14 @@ const ROISummary = ({
<div className="btn">Get ROI Boost Tips</div>
</button>
</div> */}
</>
) : (
<SkeletonUI type={"default"} />
// <div> No Data</div>
)}
</div>
</div>
</>
) : (
<SkeletonUI type={"default"} />
// <div> No Data</div>
)}
</div>
</div>}
</>
);
};

View File

@ -30,72 +30,73 @@ const ProductionCapacity = ({
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (throughputData >= 0) {
// console.log('machineActiveTime: ', machineActiveTime);
// console.log('materialCycleTime: ', materialCycleTime);
// console.log('throughputData: ', throughputData);
// console.log('productionCapacityData: ', productionCapacityData);
console.log('throughputData: ', throughputData > 0);
if (throughputData > 0) {
setIsLoading(false);
} else {
setIsLoading(true);
}
}, [throughputData])
return (
<div className="throughtputSummary-container analysis-card">
<div className="throughtputSummary-wrapper analysis-card-wrapper">
<div className="card-header">
<div className="header">
<div className="main-header">Throughput Summary</div>
<div className="sub-header">
{timeRange.startTime} - {timeRange.endTime}
<>
{!isLoading && <div className="throughtputSummary-container analysis-card">
<div className="throughtputSummary-wrapper analysis-card-wrapper">
<div className="card-header">
<div className="header">
<div className="main-header">Throughput Summary</div>
<div className="sub-header">
{timeRange.startTime} - {timeRange.endTime}
</div>
</div>
<div className="icon-wrapper">
<ThroughputSummaryIcon />
</div>
</div>
<div className="icon-wrapper">
<ThroughputSummaryIcon />
</div>
{!isLoading ? (
<>
<div className="process-container">
<div className="throughput-value">
<span className="value">{throughputData}</span> Units/hour
</div>
{/* Dynamic Progress Bar */}
<div className="progress-bar-wrapper">
{[...Array(totalBars)].map((_, i) => (
<div className="progress-bar" key={i}>
{i < barsToFill ? (
<div className="bar-fill full" />
) : i === barsToFill ? (
<div
className="bar-fill partial"
style={{ width: `${partialFillPercent}%` }}
/>
) : null}
</div>
))}
</div>
</div>
<div className="metrics-section">
<div className="metric">
<span className="label">Avg. Process Time</span>
<span className="value">{materialCycleTime} secs/unit </span>
</div>
<div className="metric">
<span className="label">Machine Utilization</span>
<span className="value">{machineActiveTime}</span>
{/* <span className="value">{machineActiveTime}</span> */}
</div>
</div>
</>
) : (
<SkeletonUI type={"default"} />
)}
</div>
{isLoading ? (
<>
<div className="process-container">
<div className="throughput-value">
<span className="value">{throughputData}</span> Units/hour
</div>
{/* Dynamic Progress Bar */}
<div className="progress-bar-wrapper">
{[...Array(totalBars)].map((_, i) => (
<div className="progress-bar" key={i}>
{i < barsToFill ? (
<div className="bar-fill full" />
) : i === barsToFill ? (
<div
className="bar-fill partial"
style={{ width: `${partialFillPercent}%` }}
/>
) : null}
</div>
))}
</div>
</div>
<div className="metrics-section">
<div className="metric">
<span className="label">Avg. Process Time</span>
<span className="value">{materialCycleTime} secs/unit </span>
</div>
<div className="metric">
<span className="label">Machine Utilization</span>
<span className="value">{machineActiveTime}</span>
{/* <span className="value">{machineActiveTime}</span> */}
</div>
</div>
</>
) : (
<SkeletonUI type={"default"} />
)}
</div>
</div>
</div>}
</>
);
};