Files
bodyshop/client/src/components/time-tickets-summary-employees/time-tickets-summary-employees.component.jsx

215 lines
6.7 KiB
JavaScript

import React from "react";
import { Statistic, Space, List, Button, Typography } from "antd";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { useTranslation } from "react-i18next";
import moment from "moment";
import RenderTemplate, {
displayTemplateInWindow,
} from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { onlyUnique } from "../../utils/arrayHelper";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function TimeTicketsSummaryEmployees({
bodyshop,
loading,
timetickets,
startDate,
endDate,
}) {
const { t } = useTranslation();
//Group everything by employee
//Then sum the individual time TimeTicketsSummary.
//Calculate job based tickets.
const jobTicketsByEmployee = {};
timetickets
.filter((i) => i.cost_center !== "timetickets.labels.shift")
.map((tt) => {
if (!!!jobTicketsByEmployee[tt.employeeid]) {
jobTicketsByEmployee[tt.employeeid] = [];
}
jobTicketsByEmployee[tt.employeeid].push(tt);
return null;
});
const jobTickets = Object.keys(jobTicketsByEmployee).map(function (key) {
return {
employee: jobTicketsByEmployee[key][0].employee,
tickets: jobTicketsByEmployee[key],
};
});
//Calculate shift based tickets.
const shiftTicketsByEmployee = {};
timetickets
.filter((i) => i.cost_center === "timetickets.labels.shift")
.map((tt) => {
if (!!!shiftTicketsByEmployee[tt.employeeid]) {
shiftTicketsByEmployee[tt.employeeid] = [];
}
shiftTicketsByEmployee[tt.employeeid].push(tt);
return null;
});
const shiftTickets = Object.keys(shiftTicketsByEmployee).map(function (key) {
return {
employee: shiftTicketsByEmployee[key][0].employee,
tickets: shiftTicketsByEmployee[key],
};
});
const handlePrintEmployeeTicket = async (empId) => {
const html = await RenderTemplate(
{
name: TemplateList().time_tickets_by_employee.key,
variables: { id: empId, start: startDate, end: endDate },
},
bodyshop
);
displayTemplateInWindow(html);
};
return (
<div>
<List
header={
<Typography.Title level={3}>
{t("timetickets.labels.jobhours")}
</Typography.Title>
}
itemLayout="horizontal"
//dataSource={jobTickets}
>
{jobTickets.map((item, idx) => {
const employeeCostCenters = item.tickets
.map((i) => i.cost_center)
.filter(onlyUnique);
return employeeCostCenters.map((costCenter) => {
const actHrs = item.tickets
.filter((ticket) => ticket.cost_center === costCenter)
.reduce((acc, val) => acc + val.actualhrs, 0);
const prodHrs = item.tickets
.filter((ticket) => ticket.cost_center === costCenter)
.reduce((acc, val) => acc + val.productivehrs, 0);
const clockHrs = item.tickets
.filter((ticket) => ticket.cost_center === costCenter)
.reduce((acc, val) => {
if (!!val.clockoff && !!val.clockon)
return (
acc +
moment(val.clockoff).diff(
moment(val.clockon),
"hours",
true
)
);
return acc;
}, 0);
return (
<List.Item
key={`${idx}${costCenter}`}
actions={[
<Button
onClick={() => handlePrintEmployeeTicket(item.employee.id)}
>
{t("timetickets.actions.printemployee")}
</Button>,
]}
>
<LoadingSkeleton loading={loading}>
<List.Item.Meta
title={`${item.employee.first_name} ${item.employee.last_name}`}
description={costCenter}
/>
<Space>
<Statistic
title={t("timetickets.fields.actualhrs")}
precision={1}
value={actHrs}
/>
<Statistic
title={t("timetickets.fields.productivehrs")}
precision={1}
value={prodHrs}
/>
<Statistic
title={t("timetickets.fields.efficiency")}
precision={1}
value={(prodHrs / actHrs) * 100}
suffix={"%"}
/>
<Statistic
title={t("timetickets.fields.clockhours")}
precision={1}
value={clockHrs}
/>
</Space>
</LoadingSkeleton>
</List.Item>
);
});
})}
</List>
<List
header={
<Typography.Title level={3}>
{t("timetickets.labels.clockhours")}
</Typography.Title>
}
itemLayout="horizontal"
dataSource={shiftTickets}
renderItem={(item) => {
const clockHrs = item.tickets.reduce((acc, val) => {
if (!!val.clockoff && !!val.clockon)
return (
acc +
moment(val.clockoff).diff(moment(val.clockon), "hours", true)
);
return acc;
}, 0);
return (
<List.Item
actions={[
<Button
onClick={() => handlePrintEmployeeTicket(item.employee.id)}
>
{t("timetickets.actions.printemployee")}
</Button>,
]}
>
<LoadingSkeleton loading={loading}>
<List.Item.Meta
title={`${item.employee.first_name} ${item.employee.last_name}`}
/>
<Statistic
title={t("timetickets.fields.clockhours")}
precision={2}
value={clockHrs}
/>
</LoadingSkeleton>
</List.Item>
);
}}
/>
</div>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TimeTicketsSummaryEmployees);