refactor: update various components to improve readability and maintainability

This commit is contained in:
Gomathi 2025-06-09 17:58:23 +05:30
parent d706a6a8a2
commit 6884ffd562
11 changed files with 381 additions and 263 deletions

View File

@ -14,9 +14,9 @@ const Analysis: React.FC = () => {
const AnalysisPresets: AnalysisPresetsType = { const AnalysisPresets: AnalysisPresetsType = {
"Throughput time": [ "Throughput time": [
{ type: "default", inputs: { label: "Cycle time", activeOption: "s" } }, // { type: "default", inputs: { label: "Cycle time", activeOption: "s" } },
{ type: "default", inputs: { label: "machines / lines", activeOption: "item" } }, // { type: "default", inputs: { label: "machines / lines", activeOption: "item" } },
{ type: "default", inputs: { label: "Machine uptime", activeOption: "%" } }, // { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
], ],
"Production capacity": [ "Production capacity": [
{ type: "default", inputs: { label: "Shift length", activeOption: "hr" } }, { type: "default", inputs: { label: "Shift length", activeOption: "hr" } },

View File

@ -8,6 +8,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import axios from "axios"; import axios from "axios";
import RenameInput from "../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../ui/inputs/RenameInput";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSocketStore } from "../../../../../store/builder/store";
type Props = {}; type Props = {};
@ -26,6 +27,7 @@ const BarChartInput = (props: Props) => {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
const [isLoading, setLoading] = useState<boolean>(true); const [isLoading, setLoading] = useState<boolean>(true);
const { projectId } = useParams(); const { projectId } = useParams();
const { visualizationSocket } = useSocketStore();
useEffect(() => { useEffect(() => {
@ -92,6 +94,25 @@ const BarChartInput = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// const userId = localStorage.getItem("userId");
// let newWidget = {
// id: selectedChartId.id,
// panel: selectedChartId.panel,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// }
// }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
try { try {
const response = await axios.post( const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`, `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`,

View File

@ -124,6 +124,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import axios from "axios"; import axios from "axios";
import RenameInput from "../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../ui/inputs/RenameInput";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSocketStore } from "../../../../../store/builder/store";
type Props = {}; type Props = {};
@ -142,6 +143,7 @@ const LineGrapInput = (props: Props) => {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
const [isLoading, setLoading] = useState<boolean>(true); const [isLoading, setLoading] = useState<boolean>(true);
const { projectId } = useParams(); const { projectId } = useParams();
const { visualizationSocket } = useSocketStore();
useEffect(() => { useEffect(() => {
const fetchZoneData = async () => { const fetchZoneData = async () => {
@ -207,6 +209,25 @@ const LineGrapInput = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// const userId = localStorage.getItem("userId");
// let newWidget = {
// id: selectedChartId.id,
// panel: selectedChartId.panel,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// }
// }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
try { try {
const response = await axios.post( const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`, `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`,

View File

@ -8,6 +8,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import axios from "axios"; import axios from "axios";
import RenameInput from "../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../ui/inputs/RenameInput";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSocketStore } from "../../../../../store/builder/store";
type Props = {}; type Props = {};
@ -26,6 +27,7 @@ const PieChartInput = (props: Props) => {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
const [isLoading, setLoading] = useState<boolean>(true); const [isLoading, setLoading] = useState<boolean>(true);
const { projectId } = useParams(); const { projectId } = useParams();
const { visualizationSocket } = useSocketStore();
useEffect(() => { useEffect(() => {
@ -92,6 +94,26 @@ const PieChartInput = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// const userId = localStorage.getItem("userId");
// let newWidget = {
// id: selectedChartId.id,
// panel: selectedChartId.panel,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// },
// }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
try { try {
const response = await axios.post( const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`, `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`,

View File

@ -8,6 +8,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import axios from "axios"; import axios from "axios";
import RenameInput from "../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../ui/inputs/RenameInput";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSocketStore } from "../../../../../store/builder/store";
type Props = {}; type Props = {};
@ -26,6 +27,7 @@ const Progress1Input = (props: Props) => {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
const [isLoading, setLoading] = useState<boolean>(true); const [isLoading, setLoading] = useState<boolean>(true);
const { projectId } = useParams(); const { projectId } = useParams();
const { visualizationSocket } = useSocketStore();
useEffect(() => { useEffect(() => {
@ -92,6 +94,25 @@ const Progress1Input = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// const userId = localStorage.getItem("userId");
// let newWidget = {
// id: selectedChartId.id,
// panel: selectedChartId.panel,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// },
// }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
try { try {
const response = await axios.post( const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`, `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`,

View File

@ -8,6 +8,7 @@ import { useWidgetStore } from "../../../../../store/useWidgetStore";
import axios from "axios"; import axios from "axios";
import RenameInput from "../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../ui/inputs/RenameInput";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSocketStore } from "../../../../../store/builder/store";
type Props = {}; type Props = {};
@ -26,6 +27,7 @@ const Progress2Input = (props: Props) => {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
const [isLoading, setLoading] = useState<boolean>(true); const [isLoading, setLoading] = useState<boolean>(true);
const { projectId } = useParams(); const { projectId } = useParams();
const { visualizationSocket } = useSocketStore();
useEffect(() => { useEffect(() => {
@ -92,6 +94,25 @@ const Progress2Input = (props: Props) => {
inputDuration: any, inputDuration: any,
inputName: any inputName: any
) => { ) => {
// const userId = localStorage.getItem("userId");
// let newWidget = {
// id: selectedChartId.id,
// panel: selectedChartId.panel,
// widgetName: inputName,
// Data: {
// measurements: inputMeasurement,
// duration: inputDuration,
// }
// }
// const adding3dWidget = {
// organization: organization,
// widget: newWidget,
// zoneUuid: selectedZone.zoneUuid,
// projectId, userId
// };
// if (visualizationSocket) {
// visualizationSocket.emit("v1:viz-3D-widget:add", adding3dWidget);
// }
try { try {
const response = await axios.post( const response = await axios.post(
`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`, `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/V1/widget/save`,

View File

@ -91,7 +91,8 @@ const ThroughputSummary: React.FC = () => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
useEffect(() => { useEffect(() => {
if (productionCapacityData >= 0) { // console.log('productionCapacityData > 0: ', productionCapacityData > 0);
if (productionCapacityData > 0) {
setIsLoading(false); setIsLoading(false);
console.log("productionCapacityData: ", productionCapacityData); console.log("productionCapacityData: ", productionCapacityData);
} else { } else {
@ -100,91 +101,93 @@ const ThroughputSummary: React.FC = () => {
}, [productionCapacityData]); }, [productionCapacityData]);
return ( return (
<div className="production analysis-card"> <>
<div className="production-wrapper analysis-card-wrapper"> {!isLoading && <div className="production analysis-card">
<div className="card-header"> <div className="production-wrapper analysis-card-wrapper">
<div className="header"> <div className="card-header">
<div className="main-header">Production Capacity</div> <div className="header">
<div className="sub-header"> <div className="main-header">Production Capacity</div>
{timeRange.startTime} - {timeRange.endTime} <div className="sub-header">
{timeRange.startTime} - {timeRange.endTime}
</div>
</div>
<div className="icon-wrapper">
<ProductionCapacityIcon />
</div> </div>
</div> </div>
<div className="icon-wrapper">
<ProductionCapacityIcon />
</div>
</div>
{!isLoading ? ( {!isLoading ? (
<> <>
<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/hour
</div>
<div className="lineChart">
<div className="assetUsage">
<div className="key">Asset usage</div>
<div className="value">{parseFloat(inputValues["Yield rate"])}%</div>
</div> </div>
<Line data={chartData} options={chartOptions} /> <div className="lineChart">
</div> <div className="assetUsage">
</div> <div className="key">Asset usage</div>
<div className="value">{parseFloat(inputValues["Yield rate"])}%</div>
<div className="footer">
<div className="energyConsumption footer-card">
<div className="header">Energy Consumption</div>
<div className="value-container">
<div className="energy-icon">
<PowerIcon />
</div> </div>
<div className="value-wrapper"> <Line data={chartData} options={chartOptions} />
<div className="value"> </div>
{energyConsumption.energyConsumed} </div>
<div className="footer">
<div className="energyConsumption footer-card">
<div className="header">Energy Consumption</div>
<div className="value-container">
<div className="energy-icon">
<PowerIcon />
</div> </div>
<div className="unit">{energyConsumption.unit}</div> <div className="value-wrapper">
</div> <div className="value">
</div> {energyConsumption.energyConsumed}
</div>
<div className="shiftUtilization footer-card">
<div className="header">Shift Utilization</div>
<div className="value-container">
<div className="value">{throughputData.assetUsage}%</div>
<div className="progress-wrapper">
{/* Dynamically create progress bars based on shiftUtilization array */}
{shiftUtilization.map((shift, index) => (
<div
key={shift.shift}
className={`progress shift-${shift.shift}`}
style={{
width: `${shift.percentage}%`,
backgroundColor: shift.color,
}}
></div>
))}
</div>
<div className="progress-indicator">
{/* Dynamically create shift indicators with random colors */}
{shiftUtilization.map((shift, index) => (
<div className="shift-wrapper" key={shift.shift}>
<span
className={`indicator shift-${shift.shift}`}
style={{ backgroundColor: shift.color }} // Random color for indicator
></span>
<label>Shift {shift.shift}</label>
</div> </div>
))} <div className="unit">{energyConsumption.unit}</div>
</div>
</div>
</div>
<div className="shiftUtilization footer-card">
<div className="header">Shift Utilization</div>
<div className="value-container">
<div className="value">{throughputData.assetUsage}%</div>
<div className="progress-wrapper">
{/* Dynamically create progress bars based on shiftUtilization array */}
{shiftUtilization.map((shift, index) => (
<div
key={shift.shift}
className={`progress shift-${shift.shift}`}
style={{
width: `${shift.percentage}%`,
backgroundColor: shift.color,
}}
></div>
))}
</div>
<div className="progress-indicator">
{/* Dynamically create shift indicators with random colors */}
{shiftUtilization.map((shift, index) => (
<div className="shift-wrapper" key={shift.shift}>
<span
className={`indicator shift-${shift.shift}`}
style={{ backgroundColor: shift.color }} // Random color for indicator
></span>
<label>Shift {shift.shift}</label>
</div>
))}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </>
</> ) : (
) : ( <SkeletonUI type={"default"} />
<SkeletonUI type={"default"} /> )}
)} </div>
</div> </div>}
</div> </>
); );
}; };

View File

@ -83,136 +83,142 @@ const ROISummary = ({
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { roiSummary } = useROISummaryData(); const { roiSummary } = useROISummaryData();
useEffect(() => { useEffect(() => {
if (roiSummary && typeof roiSummary === "object") { if (roiSummary.productName) {
setIsLoading(false); // Data loaded // If productName is set, assume data is loaded
setIsLoading(false);
} else { } else {
setIsLoading(true); // Show skeleton while loading // If productName is empty, assume still loading
setIsLoading(true);
} }
}, [roiSummary]); }, [roiSummary]);
return ( return (
<div className="roiSummary-container analysis-card"> <>
<div className="roiSummary-wrapper analysis-card-wrapper">
<div className="card-header"> {
<div className="header"> !isLoading && <div className="roiSummary-container analysis-card">
<div className="main-header">ROI Summary</div> <div className="roiSummary-wrapper analysis-card-wrapper">
<div className="sub-header">From {getCurrentDate()}</div> <div className="card-header">
</div> <div className="header">
<div className="icon-wrapper"> <div className="main-header">ROI Summary</div>
<ROISummaryIcon /> <div className="sub-header">From {getCurrentDate()}</div>
</div> </div>
</div> <div className="icon-wrapper">
{!isLoading ? ( <ROISummaryIcon />
<>
<div className="product-info">
<ROISummaryProductName />
<div className="product-label">Product :</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
in just <span>{roiSummary.paybackPeriod}</span> months
</div> </div>
</div> </div>
<div className="roi-details"> {!isLoading ? (
<div className="progress-wrapper"> <>
<SemiCircleProgress /> <div className="product-info">
<div className="content"> <ROISummaryProductName />
you're on track to hit it by <div className="product-label">Product :</div>
<div className="key">July 2029</div> <div className="product-name">{roiSummary.productName}</div>
</div> </div>
</div> <div className="playBack">
<div className="metrics"> <SonarCrownIcon />
<div className="metric-wrapper"> <div className="icon"></div>
<div className="metric-item"> <div className="info">
<span className="metric-label">Total Cost Incurred</span> <span> {roiSummary.roiPercentage}%</span> ROI with payback
<span className="metric-value"> in just <span>{roiSummary.paybackPeriod}</span> months
<span></span> </div>
{roiSummary.totalCost} </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>
</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>
</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> </span>
</div> </div>
<div className="metric-item"> <div
<span className="metric-label">Revenue Generated</span> className={`breakdown-table-wrapper ${isTableOpen ? "open" : "closed"
<span className="metric-value"> }`}
<span></span> style={{
transition: "max-height 0.3s ease-in-out",
{roiSummary.revenueGenerated} overflow: "hidden",
</span> }}
>
<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>
</tr>
))}
</tbody>
</table>
</div> </div>
</div> </div>
<div {/* <div className="tips-section">
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={`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>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* <div className="tips-section">
<div className="tip-header"> <div className="tip-header">
<span className="lightbulb-icon"> <span className="lightbulb-icon">
<LightBulpIcon /> <LightBulpIcon />
@ -232,13 +238,14 @@ const ROISummary = ({
<div className="btn">Get ROI Boost Tips</div> <div className="btn">Get ROI Boost Tips</div>
</button> </button>
</div> */} </div> */}
</> </>
) : ( ) : (
<SkeletonUI type={"default"} /> <SkeletonUI type={"default"} />
// <div> No Data</div> // <div> No Data</div>
)} )}
</div> </div>
</div> </div>}
</>
); );
}; };

View File

@ -30,72 +30,79 @@ const ProductionCapacity = ({
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
useEffect(() => { useEffect(() => {
if (throughputData >= 0) { console.log('typeof throughputData:', typeof throughputData);
console.log('throughputData > 0: ', throughputData > 0);
if (throughputData > 0) {
// console.log('machineActiveTime: ', machineActiveTime); // console.log('machineActiveTime: ', machineActiveTime);
// console.log('materialCycleTime: ', materialCycleTime); // console.log('materialCycleTime: ', materialCycleTime);
// console.log('throughputData: ', throughputData); // console.log('throughputData: ', throughputData);
// console.log('productionCapacityData: ', productionCapacityData); // console.log('productionCapacityData: ', productionCapacityData);
setIsLoading(false);
} else {
setIsLoading(true); setIsLoading(true);
} }
}, [throughputData]) }, [throughputData])
return ( return (
<div className="throughtputSummary-container analysis-card"> <>
<div className="throughtputSummary-wrapper analysis-card-wrapper">
<div className="card-header"> {!isLoading && <div className="throughtputSummary-container analysis-card">
<div className="header"> <div className="throughtputSummary-wrapper analysis-card-wrapper">
<div className="main-header">Throughput Summary</div> <div className="card-header">
<div className="sub-header"> <div className="header">
{timeRange.startTime} - {timeRange.endTime} <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> </div>
<div className="icon-wrapper"> {isLoading ? (
<ThroughputSummaryIcon /> <>
</div> <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>
{isLoading ? ( </div>}
<> </>
<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>
); );
}; };

View File

@ -165,7 +165,7 @@ const SimulationPlayer: React.FC = () => {
<div className="icon"> <div className="icon">
<HourlySimulationIcon /> <HourlySimulationIcon />
</div> </div>
<div className="label">Hourly Simulation</div> <div className="label">ThroughPut Data</div>
</div> </div>
<div className="progress-wrapper"> <div className="progress-wrapper">
<div <div

View File

@ -361,10 +361,7 @@ export default function Dropped3dWidgets() {
} }
}, [rightSelect, rightClickSelected]); }, [rightSelect, rightClickSelected]);
function isPointInPolygon( function isPointInPolygon(point: [number, number], polygon: Array<[number, number]>): boolean {
point: [number, number],
polygon: Array<[number, number]>
): boolean {
const [x, z] = point; const [x, z] = point;
let inside = false; let inside = false;
@ -434,8 +431,6 @@ export default function Dropped3dWidgets() {
} }
} }
}; };
const handleMouseMove = (event: MouseEvent) => { const handleMouseMove = (event: MouseEvent) => {
if (!rightClickSelected || !rightSelect) return; if (!rightClickSelected || !rightSelect) return;
const selectedzoneUuid = Object.keys(zoneWidgetData).find( const selectedzoneUuid = Object.keys(zoneWidgetData).find(