146 lines
5.4 KiB
JavaScript
146 lines
5.4 KiB
JavaScript
import React, { useMemo } from "react";
|
|
import { Statistic, Card } from "antd";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
const ProductionStatistics = ({ data, cardSettings, reducerData }) => {
|
|
const { t } = useTranslation();
|
|
|
|
const calculateTotal = (items, key, subKey) => {
|
|
return items.reduce((acc, item) => acc + (item[key]?.aggregate?.sum?.[subKey] || 0), 0);
|
|
};
|
|
|
|
const calculateTotalAmount = (items, key) => {
|
|
return items.reduce((acc, item) => acc + (item[key]?.totals?.subtotal?.amount || 0), 0);
|
|
};
|
|
|
|
const calculateReducerTotal = (lanes, key, subKey) => {
|
|
return lanes.reduce((acc, lane) => {
|
|
return (
|
|
acc + lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata[key]?.aggregate?.sum?.[subKey] || 0), 0)
|
|
);
|
|
}, 0);
|
|
};
|
|
|
|
const calculateReducerTotalAmount = (lanes, key) => {
|
|
return lanes.reduce((acc, lane) => {
|
|
return (
|
|
acc + lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata[key]?.totals?.subtotal?.amount || 0), 0)
|
|
);
|
|
}, 0);
|
|
};
|
|
|
|
const formatValue = (value, type) => {
|
|
if (type === "Jobs") {
|
|
return value.toFixed(0);
|
|
}
|
|
if (type === "Hrs") {
|
|
return value.toFixed(2);
|
|
}
|
|
return value;
|
|
};
|
|
|
|
const totalHrs = useMemo(() => {
|
|
if (!cardSettings.totalHrs) return null;
|
|
const total = calculateTotal(data, "labhrs", "mod_lb_hrs") + calculateTotal(data, "larhrs", "mod_lb_hrs");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [data, cardSettings.totalHrs]);
|
|
|
|
const totalLAB = useMemo(() => {
|
|
if (!cardSettings.totalLAB) return null;
|
|
const total = calculateTotal(data, "labhrs", "mod_lb_hrs");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [data, cardSettings.totalLAB]);
|
|
|
|
const totalLAR = useMemo(() => {
|
|
if (!cardSettings.totalLAR) return null;
|
|
const total = calculateTotal(data, "larhrs", "mod_lb_hrs");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [data, cardSettings.totalLAR]);
|
|
|
|
const jobsInProduction = useMemo(
|
|
() => (cardSettings.jobsInProduction ? data.length : null),
|
|
[data, cardSettings.jobsInProduction]
|
|
);
|
|
|
|
const totalAmountInProduction = useMemo(() => {
|
|
if (!cardSettings.totalAmountInProduction) return null;
|
|
const total = calculateTotalAmount(data, "job_totals");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [data, cardSettings.totalAmountInProduction]);
|
|
|
|
const totalHrsOnBoard = useMemo(() => {
|
|
if (!reducerData || !cardSettings.totalHrsOnBoard) return null;
|
|
const total =
|
|
calculateReducerTotal(reducerData.lanes, "labhrs", "mod_lb_hrs") +
|
|
calculateReducerTotal(reducerData.lanes, "larhrs", "mod_lb_hrs");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [reducerData, cardSettings.totalHrsOnBoard]);
|
|
|
|
const totalLABOnBoard = useMemo(() => {
|
|
if (!reducerData || !cardSettings.totalLABOnBoard) return null;
|
|
const total = calculateReducerTotal(reducerData.lanes, "labhrs", "mod_lb_hrs");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [reducerData, cardSettings.totalLABOnBoard]);
|
|
|
|
const totalLAROnBoard = useMemo(() => {
|
|
if (!reducerData || !cardSettings.totalLAROnBoard) return null;
|
|
const total = calculateReducerTotal(reducerData.lanes, "larhrs", "mod_lb_hrs");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [reducerData, cardSettings.totalLAROnBoard]);
|
|
|
|
const jobsOnBoard = useMemo(
|
|
() =>
|
|
reducerData && cardSettings.jobsOnBoard
|
|
? reducerData.lanes.reduce((acc, lane) => acc + lane.cards.length, 0)
|
|
: null,
|
|
[reducerData, cardSettings.jobsOnBoard]
|
|
);
|
|
|
|
const totalAmountOnBoard = useMemo(() => {
|
|
if (!reducerData || !cardSettings.totalAmountOnBoard) return null;
|
|
const total = calculateReducerTotalAmount(reducerData.lanes, "job_totals");
|
|
return parseFloat(total.toFixed(2));
|
|
}, [reducerData, cardSettings.totalAmountOnBoard]);
|
|
|
|
const statistics = [
|
|
{ value: totalHrs, title: t("total_hours_in_production"), suffix: t("production.statistics.hours") },
|
|
{
|
|
value: totalAmountInProduction,
|
|
title: t("total_amount_in_production"),
|
|
prefix: t("production.statistics.currency_symbol")
|
|
},
|
|
{ value: totalLAB, title: t("total_lab_in_production"), suffix: t("production.statistics.hours") },
|
|
{ value: totalLAR, title: t("total_lar_in_production"), suffix: t("production.statistics.hours") },
|
|
{ value: jobsInProduction, title: t("jobs_in_production"), suffix: "Jobs" },
|
|
{ value: totalHrsOnBoard, title: t("total_hours_on_board"), suffix: t("production.statistics.hours") },
|
|
{
|
|
value: totalAmountOnBoard,
|
|
title: t("total_amount_on_board"),
|
|
prefix: t("production.statistics.currency_symbol")
|
|
},
|
|
{ value: totalLABOnBoard, title: t("total_lab_on_board"), suffix: t("production.statistics.hours") },
|
|
{ value: totalLAROnBoard, title: t("total_lar_on_board"), suffix: t("production.statistics.hours") },
|
|
{ value: jobsOnBoard, title: t("total_jobs_on_board"), suffix: "Jobs" }
|
|
];
|
|
|
|
return (
|
|
<div style={{ display: "flex", gap: "5px", flexWrap: "wrap", marginBottom: "5px" }}>
|
|
{statistics.map(
|
|
(stat, index) =>
|
|
stat.value !== null && (
|
|
<Card key={index}>
|
|
<Statistic
|
|
title={t(`production.statistics.${stat.title}`)}
|
|
value={formatValue(stat.value, stat.suffix)}
|
|
prefix={stat.prefix}
|
|
suffix={stat.suffix}
|
|
/>
|
|
</Card>
|
|
)
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ProductionStatistics;
|