Files
bodyshop/client/src/components/dashboard-components/monthly-employee-efficiency/monthly-employee-efficiency.component.jsx
2025-08-19 16:23:29 -04:00

131 lines
4.3 KiB
JavaScript

import { Card } from "antd";
import _ from "lodash";
import dayjs from "../../../utils/day";
import { useTranslation } from "react-i18next";
import { Bar, CartesianGrid, ComposedChart, Legend, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
import * as Utils from "../../scoreboard-targets-table/scoreboard-targets-table.util";
import DashboardRefreshRequired from "../refresh-required.component";
export default function DashboardMonthlyEmployeeEfficiency({ data, ...cardProps }) {
const { t } = useTranslation();
if (!data) return null;
if (!data.monthly_employee_efficiency) return <DashboardRefreshRequired {...cardProps} />;
const ticketsByDate = _.groupBy(data.monthly_employee_efficiency, (item) => dayjs(item.date).format("YYYY-MM-DD"));
const listOfDays = Utils.ListOfDaysInCurrentMonth();
const chartData = listOfDays.reduce((acc, val) => {
//Sum up the current day.
let dailyHrs;
if (ticketsByDate[val]) {
dailyHrs = ticketsByDate[val].reduce(
(dayAcc, dayVal) => {
return {
actual: dayAcc.actual + dayVal.actualhrs,
productive: dayAcc.productive + dayVal.productivehrs
};
},
{ actual: 0, productive: 0 }
);
} else {
dailyHrs = { actual: 0, productive: 0 };
}
const dailyEfficiency = ((dailyHrs.productive - dailyHrs.actual) / dailyHrs.actual + 1) * 100;
const theValue = {
date: dayjs(val).format("DD"),
// ...dailyHrs,
actual: dailyHrs.actual.toFixed(1),
productive: dailyHrs.productive.toFixed(1),
dailyEfficiency: isNaN(dailyEfficiency) ? 0 : dailyEfficiency.toFixed(1),
accActual: acc.length > 0 ? acc[acc.length - 1].accActual + dailyHrs.actual : dailyHrs.actual,
accProductive: acc.length > 0 ? acc[acc.length - 1].accProductive + dailyHrs.productive : dailyHrs.productive,
accEfficiency: 0
};
theValue.accEfficiency = ((theValue.accProductive - theValue.accActual) / (theValue.accActual || 0) + 1) * 100;
if (isNaN(theValue.accEfficiency)) {
theValue.accEfficiency = 0;
} else {
theValue.accEfficiency = theValue.accEfficiency.toFixed(1);
}
return [...acc, theValue];
}, []);
return (
<Card title={t("dashboard.titles.monthlyemployeeefficiency")} {...cardProps}>
<div style={{ height: "100%" }}>
<ResponsiveContainer width="100%" height="100%">
<ComposedChart data={chartData} margin={{ top: 20, right: 20, bottom: 20, left: 20 }}>
<CartesianGrid stroke="#f5f5f5" />
<XAxis dataKey="date" />
<YAxis yAxisId="left" orientation="left" stroke="#8884d8" unit=" hrs" />
<YAxis yAxisId="right" orientation="right" stroke="#82ca9d" unit="%" />
<Tooltip />
<Legend />
<Line
yAxisId="right"
name="Accumulated Efficiency"
type="monotone"
unit="%"
dataKey="accEfficiency"
stroke="#152228"
connectNulls
// activeDot={{ r: 8 }}
/>
<Line
name="Daily Efficiency"
yAxisId="right"
unit="%"
type="monotone"
connectNulls
dataKey="dailyEfficiency"
stroke="#d31717"
/>
<Bar
name="Actual Hours"
dataKey="actual"
yAxisId="left"
unit=" hrs"
//stackId="day"
barSize={20}
fill="#102568"
format={"0.0"}
/>
<Bar
name="Productive Hours"
dataKey="productive"
yAxisId="left"
unit=" hrs"
//stackId="day"
barSize={20}
fill="#017664"
format={"0.0"}
/>
</ComposedChart>
</ResponsiveContainer>
</div>
</Card>
);
}
export const DashboardMonthlyEmployeeEfficiencyGql = `
monthly_employee_efficiency: timetickets(where: {_and: [{date: {_gte: "${dayjs()
.startOf("month")
.format("YYYY-MM-DD")}"}},{date: {_lte: "${dayjs().endOf("month").format("YYYY-MM-DD")}"}} ]}) {
actualhrs
productivehrs
employeeid
employee {
first_name
last_name
}
date
}
`;