- Finish up with Statistics
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user