- the great reformat

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-02-06 18:20:58 -05:00
parent 30c530bcc4
commit e83badb454
912 changed files with 108516 additions and 107493 deletions

View File

@@ -1,77 +1,78 @@
import { Card } from "antd";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import {Card} from "antd";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {
Bar,
CartesianGrid,
ComposedChart,
Legend,
ReferenceLine,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
Bar,
CartesianGrid,
ComposedChart,
Legend,
ReferenceLine,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis,
} from "recharts";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import {createStructuredSelector} from "reselect";
import {selectBodyshop} from "../../redux/user/user.selectors";
import TimeTicketsDatesSelector from "../ticket-tickets-dates-selector/time-tickets-dates-selector.component";
const graphProps = {
strokeWidth: 3,
strokeWidth: 3,
};
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
mapStateToProps,
mapDispatchToProps
)(ScoreboardTicketsBar);
export function ScoreboardTicketsBar({ data, bodyshop }) {
const { t } = useTranslation();
return (
<Card
title={t("scoreboard.labels.productivetimeticketsoverdate")}
extra={<TimeTicketsDatesSelector />}
>
<ResponsiveContainer width="100%" height={475}>
<ComposedChart
data={data.chartData}
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
export function ScoreboardTicketsBar({data, bodyshop}) {
const {t} = useTranslation();
return (
<Card
title={t("scoreboard.labels.productivetimeticketsoverdate")}
extra={<TimeTicketsDatesSelector/>}
>
<CartesianGrid stroke="#f5f5f5" />
<XAxis dataKey="date" strokeWidth={graphProps.strokeWidth} />
<YAxis strokeWidth={graphProps.strokeWidth} />
<Tooltip />
<Legend />
<ReferenceLine
y={
bodyshop.scoreboard_target.dailyBodyTarget +
bodyshop.scoreboard_target.dailyPaintTarget
}
label="Daily Target"
stroke="red"
strokeDasharray="3 3"
/>
{data &&
data.employees.map((e, idx) => (
<Bar
key={`${e}productive`}
name={e}
dataKey={`employees.${e}.productive`}
stackId="productive"
// barSize={20}
fill={data.colors[idx]}
>
{/* <LabelList position="top" /> */}
</Bar>
))}
</ComposedChart>
</ResponsiveContainer>
</Card>
);
<ResponsiveContainer width="100%" height={475}>
<ComposedChart
data={data.chartData}
margin={{top: 20, right: 20, bottom: 20, left: 20}}
>
<CartesianGrid stroke="#f5f5f5"/>
<XAxis dataKey="date" strokeWidth={graphProps.strokeWidth}/>
<YAxis strokeWidth={graphProps.strokeWidth}/>
<Tooltip/>
<Legend/>
<ReferenceLine
y={
bodyshop.scoreboard_target.dailyBodyTarget +
bodyshop.scoreboard_target.dailyPaintTarget
}
label="Daily Target"
stroke="red"
strokeDasharray="3 3"
/>
{data &&
data.employees.map((e, idx) => (
<Bar
key={`${e}productive`}
name={e}
dataKey={`employees.${e}.productive`}
stackId="productive"
// barSize={20}
fill={data.colors[idx]}
>
{/* <LabelList position="top" /> */}
</Bar>
))}
</ComposedChart>
</ResponsiveContainer>
</Card>
);
}

View File

@@ -1,11 +1,11 @@
import { useQuery } from "@apollo/client";
import { Col, Row } from "antd";
import {useQuery} from "@apollo/client";
import {Col, Row} from "antd";
import _ from "lodash";
import dayjs from "../../utils/day";
import queryString from "query-string";
import React, { useMemo } from "react";
import { useLocation } from "react-router-dom";
import { QUERY_TIME_TICKETS_IN_RANGE_SB } from "../../graphql/timetickets.queries";
import React, {useMemo} from "react";
import {useLocation} from "react-router-dom";
import {QUERY_TIME_TICKETS_IN_RANGE_SB} from "../../graphql/timetickets.queries";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
@@ -13,273 +13,273 @@ import ScoreboardTicketsBar from "./scoreboard-timetickets.bar.component";
import ScoreboardTicketsStats from "./scoreboard-timetickets.stats.component";
export default function ScoreboardTimeTickets() {
const searchParams = queryString.parse(useLocation().search);
const { start, end } = searchParams;
const startDate = start
? dayjs(start)
: dayjs().startOf("week").subtract(7, "day");
const endDate = end ? dayjs(end) : dayjs().endOf("week");
const searchParams = queryString.parse(useLocation().search);
const {start, end} = searchParams;
const startDate = start
? dayjs(start)
: dayjs().startOf("week").subtract(7, "day");
const endDate = end ? dayjs(end) : dayjs().endOf("week");
const fixedPeriods = useMemo(() => {
const endOfThisMonth = dayjs().endOf("month");
const startofthisMonth = dayjs().startOf("month");
const fixedPeriods = useMemo(() => {
const endOfThisMonth = dayjs().endOf("month");
const startofthisMonth = dayjs().startOf("month");
const endOfLastmonth = dayjs().subtract(1, "month").endOf("month");
const startOfLastmonth = dayjs().subtract(1, "month").startOf("month");
const endOfLastmonth = dayjs().subtract(1, "month").endOf("month");
const startOfLastmonth = dayjs().subtract(1, "month").startOf("month");
const endOfThisWeek = dayjs().endOf("week");
const startOfThisWeek = dayjs().startOf("week");
const endOfThisWeek = dayjs().endOf("week");
const startOfThisWeek = dayjs().startOf("week");
const endOfLastWeek = dayjs().subtract(1, "week").endOf("week");
const startOfLastWeek = dayjs().subtract(1, "week").startOf("week");
const endOfLastWeek = dayjs().subtract(1, "week").endOf("week");
const startOfLastWeek = dayjs().subtract(1, "week").startOf("week");
const allDates = [
endOfThisMonth,
startofthisMonth,
endOfLastmonth,
startOfLastmonth,
endOfThisWeek,
startOfThisWeek,
endOfLastWeek,
startOfLastWeek,
];
const start = dayjs.min(allDates);
const end = dayjs.max(allDates);
return {
start,
end,
endOfThisMonth,
startofthisMonth,
endOfLastmonth,
startOfLastmonth,
endOfThisWeek,
startOfThisWeek,
endOfLastWeek,
startOfLastWeek,
};
}, []);
const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE_SB, {
variables: {
start: startDate.format("YYYY-MM-DD"),
end: endDate.format("YYYY-MM-DD"),
fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
jobStart: startDate,
jobEnd: endDate,
},
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
pollInterval: 60000,
skip: !fixedPeriods,
});
const calculatedData = useMemo(() => {
if (!data) return [];
const ret = {
totalThisWeek: 0,
totalLastWeek: 0,
totalThisMonth: 0,
totalLastMonth: 0,
totalOverPeriod: 0,
actualTotalOverPeriod: 0,
totalEffieciencyOverPeriod: 0,
employees: {},
};
data.fixedperiod.forEach((ticket) => {
const ticketDate = dayjs(ticket.date);
if (!ret.employees[ticket.employee.employee_number]) {
ret.employees[ticket.employee.employee_number] = {
totalThisWeek: 0,
totalLastWeek: 0,
totalThisMonth: 0,
totalLastMonth: 0,
totalOverPeriod: 0,
actualTotalOverPeriod: 0,
totalEffieciencyOverPeriod: 0,
const allDates = [
endOfThisMonth,
startofthisMonth,
endOfLastmonth,
startOfLastmonth,
endOfThisWeek,
startOfThisWeek,
endOfLastWeek,
startOfLastWeek,
];
const start = dayjs.min(allDates);
const end = dayjs.max(allDates);
return {
start,
end,
endOfThisMonth,
startofthisMonth,
endOfLastmonth,
startOfLastmonth,
endOfThisWeek,
startOfThisWeek,
endOfLastWeek,
startOfLastWeek,
};
}
}, []);
if (
ticketDate.isBetween(
fixedPeriods.startOfThisWeek,
fixedPeriods.endOfThisWeek,
undefined,
"[]"
)
) {
ret.totalThisWeek = ret.totalThisWeek + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalThisWeek =
ret.employees[ticket.employee.employee_number].totalThisWeek +
ticket.productivehrs;
} else if (
ticketDate.isBetween(
fixedPeriods.startOfLastWeek,
fixedPeriods.endOfLastWeek,
undefined,
"[]"
)
) {
ret.totalLastWeek = ret.totalLastWeek + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalLastWeek =
ret.employees[ticket.employee.employee_number].totalLastWeek +
ticket.productivehrs;
}
if (
ticketDate.isBetween(
fixedPeriods.startofthisMonth,
fixedPeriods.endOfThisMonth,
undefined,
"[]"
)
) {
ret.totalThisMonth = ret.totalThisMonth + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalThisMonth =
ret.employees[ticket.employee.employee_number].totalThisMonth +
ticket.productivehrs;
} else if (
ticketDate.isBetween(
fixedPeriods.startOfLastmonth,
fixedPeriods.endOfLastmonth,
undefined,
"[]"
)
) {
ret.totalLastMonth = ret.totalLastMonth + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalLastMonth =
ret.employees[ticket.employee.employee_number].totalLastMonth +
ticket.productivehrs;
}
});
const ticketsGroupedByDate = _.groupBy(data.timetickets, "date");
const listOfDays = Utils.ListDaysBetween({
start: startDate,
end: endDate,
});
const employees = [];
const ret2 = [];
let totals = {
totalproductive: 0,
totalactual: 0,
employees: {},
};
listOfDays.forEach((day) => {
const r = {
date: dayjs(day).format("MM/DD"),
actualtotal: 0,
productivetotal: 0,
employees: {},
};
if (ticketsGroupedByDate[day]) {
ticketsGroupedByDate[day].forEach((ticket) => {
r.actualtotal = r.actualtotal + ticket.actualhrs;
r.productivetotal = r.productivetotal + ticket.productivehrs;
totals.totalactual = totals.totalactual + ticket.actualhrs;
totals.totalproductive =
totals.totalproductive + ticket.productivehrs;
employees.push(ticket.employee.employee_number);
//Add to table data.
ret.employees[ticket.employee.employee_number].totalOverPeriod =
ret.employees[ticket.employee.employee_number].totalOverPeriod +
ticket.productivehrs;
ret.employees[ticket.employee.employee_number].actualTotalOverPeriod =
ret.employees[ticket.employee.employee_number]
.actualTotalOverPeriod + (ticket.actualhrs || 0);
if (!totals.employees[ticket.employee.employee_number])
totals.employees[ticket.employee.employee_number] = {
totalactual: 0,
totalproductive: 0,
};
if (!r.employees[ticket.employee.employee_number])
r.employees[ticket.employee.employee_number] = {
actual: 0,
productive: 0,
};
//Add to totals.
totals.employees[ticket.employee.employee_number].totalproductive =
totals.employees[ticket.employee.employee_number].totalproductive +
ticket.productivehrs;
totals.employees[ticket.employee.employee_number].totalactual =
totals.employees[ticket.employee.employee_number].totalactual +
ticket.actualhrs;
//Add to dailys.
r.employees[ticket.employee.employee_number].productive =
r.employees[ticket.employee.employee_number].productive +
ticket.productivehrs;
r.employees[ticket.employee.employee_number].actual =
r.employees[ticket.employee.employee_number].actual +
ticket.actualhrs;
});
}
ret2.push(r);
});
// Add total efficiency of employees
const totalActualAndProductive = Object.keys(ret.employees)
.map((key) => {
return { employee_number: key, ...ret.employees[key] };
})
.reduce(
(acc, e) => {
return {
totalOverPeriod: acc.totalOverPeriod + e.totalOverPeriod,
actualTotalOverPeriod:
acc.actualTotalOverPeriod + e.actualTotalOverPeriod,
};
const {loading, error, data} = useQuery(QUERY_TIME_TICKETS_IN_RANGE_SB, {
variables: {
start: startDate.format("YYYY-MM-DD"),
end: endDate.format("YYYY-MM-DD"),
fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
jobStart: startDate,
jobEnd: endDate,
},
{ totalOverPeriod: 0, actualTotalOverPeriod: 0 }
);
fetchPolicy: "network-only",
nextFetchPolicy: "network-only",
pollInterval: 60000,
skip: !fixedPeriods,
});
ret.totalEffieciencyOverPeriod =
totalActualAndProductive.actualTotalOverPeriod
? (totalActualAndProductive.totalOverPeriod /
totalActualAndProductive.actualTotalOverPeriod) *
100
: 0;
const calculatedData = useMemo(() => {
if (!data) return [];
const ret = {
totalThisWeek: 0,
totalLastWeek: 0,
totalThisMonth: 0,
totalLastMonth: 0,
totalOverPeriod: 0,
actualTotalOverPeriod: 0,
totalEffieciencyOverPeriod: 0,
employees: {},
};
data.fixedperiod.forEach((ticket) => {
const ticketDate = dayjs(ticket.date);
roundObject(ret);
roundObject(totals);
roundObject(ret2);
if (!ret.employees[ticket.employee.employee_number]) {
ret.employees[ticket.employee.employee_number] = {
totalThisWeek: 0,
totalLastWeek: 0,
totalThisMonth: 0,
totalLastMonth: 0,
totalOverPeriod: 0,
actualTotalOverPeriod: 0,
totalEffieciencyOverPeriod: 0,
};
}
return {
fixed: ret,
timeperiod: {
totals,
chartData: ret2,
employees: _.uniq(employees),
colors: getColorArray(employees.length),
},
};
}, [fixedPeriods, data, startDate, endDate]);
if (
ticketDate.isBetween(
fixedPeriods.startOfThisWeek,
fixedPeriods.endOfThisWeek,
undefined,
"[]"
)
) {
ret.totalThisWeek = ret.totalThisWeek + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalThisWeek =
ret.employees[ticket.employee.employee_number].totalThisWeek +
ticket.productivehrs;
} else if (
ticketDate.isBetween(
fixedPeriods.startOfLastWeek,
fixedPeriods.endOfLastWeek,
undefined,
"[]"
)
) {
ret.totalLastWeek = ret.totalLastWeek + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalLastWeek =
ret.employees[ticket.employee.employee_number].totalLastWeek +
ticket.productivehrs;
}
if (
ticketDate.isBetween(
fixedPeriods.startofthisMonth,
fixedPeriods.endOfThisMonth,
undefined,
"[]"
)
) {
ret.totalThisMonth = ret.totalThisMonth + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalThisMonth =
ret.employees[ticket.employee.employee_number].totalThisMonth +
ticket.productivehrs;
} else if (
ticketDate.isBetween(
fixedPeriods.startOfLastmonth,
fixedPeriods.endOfLastmonth,
undefined,
"[]"
)
) {
ret.totalLastMonth = ret.totalLastMonth + ticket.productivehrs;
ret.employees[ticket.employee.employee_number].totalLastMonth =
ret.employees[ticket.employee.employee_number].totalLastMonth +
ticket.productivehrs;
}
});
if (error) return <AlertComponent message={error.message} type="error" />;
if (loading) return <LoadingSpinner />;
return (
<Row gutter={[16, 16]}>
<Col span={24}>
<ScoreboardTicketsStats data={calculatedData.fixed} />
</Col>
<Col span={24}>
<ScoreboardTicketsBar
start={startDate}
end={endDate}
data={calculatedData.timeperiod}
/>
</Col>
</Row>
);
const ticketsGroupedByDate = _.groupBy(data.timetickets, "date");
const listOfDays = Utils.ListDaysBetween({
start: startDate,
end: endDate,
});
const employees = [];
const ret2 = [];
let totals = {
totalproductive: 0,
totalactual: 0,
employees: {},
};
listOfDays.forEach((day) => {
const r = {
date: dayjs(day).format("MM/DD"),
actualtotal: 0,
productivetotal: 0,
employees: {},
};
if (ticketsGroupedByDate[day]) {
ticketsGroupedByDate[day].forEach((ticket) => {
r.actualtotal = r.actualtotal + ticket.actualhrs;
r.productivetotal = r.productivetotal + ticket.productivehrs;
totals.totalactual = totals.totalactual + ticket.actualhrs;
totals.totalproductive =
totals.totalproductive + ticket.productivehrs;
employees.push(ticket.employee.employee_number);
//Add to table data.
ret.employees[ticket.employee.employee_number].totalOverPeriod =
ret.employees[ticket.employee.employee_number].totalOverPeriod +
ticket.productivehrs;
ret.employees[ticket.employee.employee_number].actualTotalOverPeriod =
ret.employees[ticket.employee.employee_number]
.actualTotalOverPeriod + (ticket.actualhrs || 0);
if (!totals.employees[ticket.employee.employee_number])
totals.employees[ticket.employee.employee_number] = {
totalactual: 0,
totalproductive: 0,
};
if (!r.employees[ticket.employee.employee_number])
r.employees[ticket.employee.employee_number] = {
actual: 0,
productive: 0,
};
//Add to totals.
totals.employees[ticket.employee.employee_number].totalproductive =
totals.employees[ticket.employee.employee_number].totalproductive +
ticket.productivehrs;
totals.employees[ticket.employee.employee_number].totalactual =
totals.employees[ticket.employee.employee_number].totalactual +
ticket.actualhrs;
//Add to dailys.
r.employees[ticket.employee.employee_number].productive =
r.employees[ticket.employee.employee_number].productive +
ticket.productivehrs;
r.employees[ticket.employee.employee_number].actual =
r.employees[ticket.employee.employee_number].actual +
ticket.actualhrs;
});
}
ret2.push(r);
});
// Add total efficiency of employees
const totalActualAndProductive = Object.keys(ret.employees)
.map((key) => {
return {employee_number: key, ...ret.employees[key]};
})
.reduce(
(acc, e) => {
return {
totalOverPeriod: acc.totalOverPeriod + e.totalOverPeriod,
actualTotalOverPeriod:
acc.actualTotalOverPeriod + e.actualTotalOverPeriod,
};
},
{totalOverPeriod: 0, actualTotalOverPeriod: 0}
);
ret.totalEffieciencyOverPeriod =
totalActualAndProductive.actualTotalOverPeriod
? (totalActualAndProductive.totalOverPeriod /
totalActualAndProductive.actualTotalOverPeriod) *
100
: 0;
roundObject(ret);
roundObject(totals);
roundObject(ret2);
return {
fixed: ret,
timeperiod: {
totals,
chartData: ret2,
employees: _.uniq(employees),
colors: getColorArray(employees.length),
},
};
}, [fixedPeriods, data, startDate, endDate]);
if (error) return <AlertComponent message={error.message} type="error"/>;
if (loading) return <LoadingSpinner/>;
return (
<Row gutter={[16, 16]}>
<Col span={24}>
<ScoreboardTicketsStats data={calculatedData.fixed}/>
</Col>
<Col span={24}>
<ScoreboardTicketsBar
start={startDate}
end={endDate}
data={calculatedData.timeperiod}
/>
</Col>
</Row>
);
}
//Include a filter by employee.
@@ -290,63 +290,63 @@ export default function ScoreboardTimeTickets() {
//Hours produced by employee by day for time period.
function getColorArray(num) {
return [
"#3366cc",
"#dc3912",
"#ff9900",
"#109618",
"#990099",
"#0099c6",
"#dd4477",
"#66aa00",
"#b82e2e",
"#316395",
"#3366cc",
"#994499",
"#22aa99",
"#aaaa11",
"#6633cc",
"#e67300",
"#8b0707",
"#651067",
"#329262",
"#5574a6",
"#3b3eac",
"#b77322",
"#16d620",
"#b91383",
"#f4359e",
"#9c5935",
"#a9c413",
"#2a778d",
"#668d1c",
"#bea413",
"#0c5922",
"#743411",
];
// var result = [];
// for (var i = 0; i < num; i += 1) {
// var letters = "0123456789ABCDEF".split("");
// var color = "#";
// for (var j = 0; j < 6; j += 1) {
// color += letters[Math.floor(Math.random() * 16)];
// }
// result.push(color);
// }
// return result;
return [
"#3366cc",
"#dc3912",
"#ff9900",
"#109618",
"#990099",
"#0099c6",
"#dd4477",
"#66aa00",
"#b82e2e",
"#316395",
"#3366cc",
"#994499",
"#22aa99",
"#aaaa11",
"#6633cc",
"#e67300",
"#8b0707",
"#651067",
"#329262",
"#5574a6",
"#3b3eac",
"#b77322",
"#16d620",
"#b91383",
"#f4359e",
"#9c5935",
"#a9c413",
"#2a778d",
"#668d1c",
"#bea413",
"#0c5922",
"#743411",
];
// var result = [];
// for (var i = 0; i < num; i += 1) {
// var letters = "0123456789ABCDEF".split("");
// var color = "#";
// for (var j = 0; j < 6; j += 1) {
// color += letters[Math.floor(Math.random() * 16)];
// }
// result.push(color);
// }
// return result;
}
function roundObject(inputObj) {
for (var key of Object.keys(inputObj)) {
if (typeof inputObj[key] === "number" && inputObj[key] !== 0) {
inputObj[key] =
inputObj[key] && inputObj[key].toFixed
? inputObj[key].toFixed(1)
: inputObj[key]; //Math.round(inputObj[key] * 100) / 100;
} else if (Array.isArray(inputObj[key])) {
inputObj[key].forEach((item) => roundObject(item));
} else if (typeof inputObj[key] === "object") {
roundObject(inputObj[key]);
for (var key of Object.keys(inputObj)) {
if (typeof inputObj[key] === "number" && inputObj[key] !== 0) {
inputObj[key] =
inputObj[key] && inputObj[key].toFixed
? inputObj[key].toFixed(1)
: inputObj[key]; //Math.round(inputObj[key] * 100) / 100;
} else if (Array.isArray(inputObj[key])) {
inputObj[key].forEach((item) => roundObject(item));
} else if (typeof inputObj[key] === "object") {
roundObject(inputObj[key]);
}
}
}
}

View File

@@ -1,139 +1,139 @@
import { Card, Col, Row, Statistic, Table, Typography } from "antd";
import {Card, Col, Row, Statistic, Table, Typography} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {selectBodyshop} from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
mapStateToProps,
mapDispatchToProps
)(ScoreboardTicketsStats);
export function ScoreboardTicketsStats({ data, bodyshop }) {
const { t } = useTranslation();
const columns = [
{
title: t("employees.fields.employee_number"),
dataIndex: "employee_number",
key: "employee_number",
sorter: (a, b) => a.employee_number - b.employee_number,
},
{
title: t("scoreboard.labels.thisweek"),
dataIndex: "totalThisWeek",
key: "totalThisWeek",
sorter: (a, b) => a.totalThisWeek - b.totalThisWeek,
},
{
title: t("scoreboard.labels.lastweek"),
dataIndex: "totalLastWeek",
key: "totalLastWeek",
sorter: (a, b) => a.totalLastWeek - b.totalLastWeek,
},
{
title: t("scoreboard.labels.thismonth"),
dataIndex: "totalThisMonth",
key: "totalThisMonth",
sorter: (a, b) => a.totalThisMonth - b.totalThisMonth,
},
{
title: t("scoreboard.labels.lastmonth"),
dataIndex: "totalLastMonth",
key: "totalLastMonth",
sorter: (a, b) => a.totalLastMonth - b.totalLastMonth,
},
{
title: t("scoreboard.labels.totaloverperiod"),
dataIndex: "totalOverPeriod",
key: "totalOverPeriod",
sorter: (a, b) => a.totalOverPeriod - b.totalOverPeriod,
},
{
title: t("scoreboard.labels.efficiencyoverperiod"),
dataIndex: "efficiencyoverperiod",
key: "efficiencyoverperiod",
render: (text, record) =>
`${(
(record.totalOverPeriod / (record.actualTotalOverPeriod || 0.1)) *
100
).toFixed(1)} %`,
},
];
export function ScoreboardTicketsStats({data, bodyshop}) {
const {t} = useTranslation();
const columns = [
{
title: t("employees.fields.employee_number"),
dataIndex: "employee_number",
key: "employee_number",
sorter: (a, b) => a.employee_number - b.employee_number,
},
{
title: t("scoreboard.labels.thisweek"),
dataIndex: "totalThisWeek",
key: "totalThisWeek",
sorter: (a, b) => a.totalThisWeek - b.totalThisWeek,
},
{
title: t("scoreboard.labels.lastweek"),
dataIndex: "totalLastWeek",
key: "totalLastWeek",
sorter: (a, b) => a.totalLastWeek - b.totalLastWeek,
},
{
title: t("scoreboard.labels.thismonth"),
dataIndex: "totalThisMonth",
key: "totalThisMonth",
sorter: (a, b) => a.totalThisMonth - b.totalThisMonth,
},
{
title: t("scoreboard.labels.lastmonth"),
dataIndex: "totalLastMonth",
key: "totalLastMonth",
sorter: (a, b) => a.totalLastMonth - b.totalLastMonth,
},
{
title: t("scoreboard.labels.totaloverperiod"),
dataIndex: "totalOverPeriod",
key: "totalOverPeriod",
sorter: (a, b) => a.totalOverPeriod - b.totalOverPeriod,
},
{
title: t("scoreboard.labels.efficiencyoverperiod"),
dataIndex: "efficiencyoverperiod",
key: "efficiencyoverperiod",
render: (text, record) =>
`${(
(record.totalOverPeriod / (record.actualTotalOverPeriod || 0.1)) *
100
).toFixed(1)} %`,
},
];
const tableData = data
? Object.keys(data.employees).map((key) => {
return { employee_number: key, ...data.employees[key] };
})
: [];
const tableData = data
? Object.keys(data.employees).map((key) => {
return {employee_number: key, ...data.employees[key]};
})
: [];
return (
<Card title={t("scoreboard.labels.productivestatistics")}>
<Row gutter={[16, 16]}>
<Col md={24} lg={4}>
<Row gutter={[16, 16]}>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.lastweek")}
value={data.totalLastWeek}
/>
</Col>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.lastmonth")}
value={data.totalLastMonth}
/>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.thisweek")}
value={data.totalThisWeek}
/>
</Col>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.thismonth")}
value={data.totalThisMonth}
/>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.totaloverperiod")}
value={data.totalOverPeriod}
/>
</Col>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.efficiencyoverperiod")}
value={`${data.totalEffieciencyOverPeriod || 0}%`}
/>
</Col>
</Row>
<Typography.Text type="secondary">
{t("scoreboard.labels.calendarperiod")}
</Typography.Text>
</Col>
<Col md={24} lg={20}>
<Table
columns={columns}
rowKey="employee_number"
dataSource={tableData}
id="employee_number"
scroll={{ y: "300px" }}
/>
</Col>
</Row>
</Card>
);
return (
<Card title={t("scoreboard.labels.productivestatistics")}>
<Row gutter={[16, 16]}>
<Col md={24} lg={4}>
<Row gutter={[16, 16]}>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.lastweek")}
value={data.totalLastWeek}
/>
</Col>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.lastmonth")}
value={data.totalLastMonth}
/>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.thisweek")}
value={data.totalThisWeek}
/>
</Col>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.thismonth")}
value={data.totalThisMonth}
/>
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.totaloverperiod")}
value={data.totalOverPeriod}
/>
</Col>
<Col span={12}>
<Statistic
title={t("scoreboard.labels.efficiencyoverperiod")}
value={`${data.totalEffieciencyOverPeriod || 0}%`}
/>
</Col>
</Row>
<Typography.Text type="secondary">
{t("scoreboard.labels.calendarperiod")}
</Typography.Text>
</Col>
<Col md={24} lg={20}>
<Table
columns={columns}
rowKey="employee_number"
dataSource={tableData}
id="employee_number"
scroll={{y: "300px"}}
/>
</Col>
</Row>
</Card>
);
}