Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2023-12-14 13:20:43 -05:00
parent a67fb3576c
commit 83e4fb3dc4
19 changed files with 623 additions and 594 deletions

View File

@@ -1,17 +1,7 @@
import Icon, {UploadOutlined} from "@ant-design/icons"; import Icon, {UploadOutlined} from "@ant-design/icons";
import {useApolloClient} from "@apollo/client"; import {useApolloClient} from "@apollo/client";
import {useTreatments} from "@splitsoftware/splitio-react"; import {useTreatments} from "@splitsoftware/splitio-react";
import { import {Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload,} from "antd";
Alert,
Divider,
Form,
Input,
Select,
Space,
Statistic,
Switch,
Upload,
} from "antd";
import dayjs from "../../utils/day"; import dayjs from "../../utils/day";
import React, {useEffect, useState} from "react"; import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";

View File

@@ -14,10 +14,10 @@ export function getRange(dateParam, viewParam) {
start = dayjs(date).startOf("week"); start = dayjs(date).startOf("week");
end = dayjs(date).endOf("week"); end = dayjs(date).endOf("week");
} }
//if view is month: from dayjs(date).startOf('month').subtract(7, 'days') to dayjs(date).endOf('month').add(7, 'days'); i do additional 7 days math because you can see adjacent weeks on month view (that is the way how i generate my recurrent events for the Big Calendar, but if you need only start-end of month - just remove that math); //if view is month: from dayjs(date).startOf('month').subtract(7, 'day') to dayjs(date).endOf('month').add(7, 'day'); i do additional 7 days math because you can see adjacent weeks on month view (that is the way how i generate my recurrent events for the Big Calendar, but if you need only start-end of month - just remove that math);
else if (view === "month") { else if (view === "month") {
start = dayjs(date).startOf("month").subtract(7, "days"); start = dayjs(date).startOf("month").subtract(7, "day");
end = dayjs(date).endOf("month").add(7, "days"); end = dayjs(date).endOf("month").add(7, "day");
} }
// if view is agenda: from dayjs(date).startOf('day') to dayjs(date).endOf('day').add(1, 'month'); // if view is agenda: from dayjs(date).startOf('day') to dayjs(date).endOf('day').add(1, 'month');
else if (view === "agenda") { else if (view === "agenda") {

View File

@@ -201,7 +201,7 @@ export function ScheduleJobModalComponent({
{() => { {() => {
const values = form.getFieldsValue(); const values = form.getFieldsValue();
if (values.start) { if (values.start) {
calculateScheduleLoad(dayjs(values.start).add(3, "days")); calculateScheduleLoad(dayjs(values.start).add(3, "day"));
} }
return ( return (
<div className="schedule-job-modal"> <div className="schedule-job-modal">

View File

@@ -27,7 +27,7 @@ export function ScheduleVerifyIntegrity({ currentUser }) {
data: { arrJobs, compJobs, prodJobs }, data: { arrJobs, compJobs, prodJobs },
} = await client.query({ } = await client.query({
query: QUERY_SCHEDULE_LOAD_DATA, query: QUERY_SCHEDULE_LOAD_DATA,
variables: { start: dayjs(), end: dayjs().add(180, "days") }, variables: { start: dayjs(), end: dayjs().add(180, "day") },
}); });
//check that the leaving jobs are either in the arriving list, or in production. //check that the leaving jobs are either in the arriving list, or in production.

View File

@@ -17,7 +17,7 @@ const mapDispatchToProps = (dispatch) => ({
const rowGutter = [16, 16]; const rowGutter = [16, 16];
const statSpans = { xs: 24, sm: 3 }; const statSpans = { xs: 24, sm: 3 };
export function ScoreboardTimeticketsTargetsTable({ bodyshop }) { export function ScoreboardTimeTicketsTargetsTable({ bodyshop }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
@@ -282,4 +282,4 @@ export function ScoreboardTimeticketsTargetsTable({ bodyshop }) {
export default connect( export default connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(ScoreboardTimeticketsTargetsTable); )(ScoreboardTimeTicketsTargetsTable);

View File

@@ -17,7 +17,7 @@ export default function ScoreboardTimeTickets() {
const { start, end } = searchParams; const { start, end } = searchParams;
const startDate = start const startDate = start
? dayjs(start) ? dayjs(start)
: dayjs().startOf("week").subtract(7, "days"); : dayjs().startOf("week").subtract(7, "day");
const endDate = end ? dayjs(end) : dayjs().endOf("week"); const endDate = end ? dayjs(end) : dayjs().endOf("week");
const fixedPeriods = useMemo(() => { const fixedPeriods = useMemo(() => {

View File

@@ -16,7 +16,9 @@ const mapStateToProps = createStructuredSelector({
export function TechClockInComponent({ form, bodyshop, technician }) { export function TechClockInComponent({ form, bodyshop, technician }) {
const { t } = useTranslation(); const { t } = useTranslation();
const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0]; const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0];
return ( return (
<div> <div>
<LayoutFormRow grow noDivider> <LayoutFormRow grow noDivider>

View File

@@ -46,6 +46,16 @@ export function TechClockInContainer({
(e) => e.id === (technician && technician.id) (e) => e.id === (technician && technician.id)
)[0]; )[0];
const TechForm = () => {
if (technician) {
return <Form form={form} layout="vertical" onFinish={handleFinish} >
<TechClockInComponent form={form} />
</Form>
} else {
return <div />
}
}
const handleFinish = async (values) => { const handleFinish = async (values) => {
setLoading(true); setLoading(true);
const theTime = (await axios.post("/utils/time")).data; const theTime = (await axios.post("/utils/time")).data;
@@ -146,9 +156,7 @@ export function TechClockInContainer({
</Space> </Space>
} }
> >
<Form form={form} layout="vertical" onFinish={handleFinish}> <TechForm />
<TechClockInComponent form={form} />
</Form>
</Card> </Card>
); );
} }

View File

@@ -26,21 +26,21 @@ export function TechClockedInList({ technician }) {
QUERY_ACTIVE_TIME_TICKETS, QUERY_ACTIVE_TIME_TICKETS,
{ {
variables: { variables: {
employeeId: technician.id, employeeId: technician?.id,
}, },
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
skip: !technician,
} }
); );
const {t} = useTranslation(); const {t} = useTranslation();
if (loading) return <LoadingSpinner/>; if (loading) return <LoadingSpinner/>;
if (error) return <AlertComponent message={error.message} type="error"/>; if (error) return <AlertComponent message={error.message} type="error"/>;
return ( return (
<div> <div>
{data.timetickets.length > 0 ? ( {data?.timetickets?.length > 0 ? (
<div> <div>
<Typography.Title level={2}> <Typography.Title level={2}>
{t("timetickets.labels.alreadyclockedon")} {t("timetickets.labels.alreadyclockedon")}
@@ -97,4 +97,5 @@ export function TechClockedInList({ technician }) {
</div> </div>
); );
} }
export default connect(mapStateToProps, mapDispatchToProps)(TechClockedInList); export default connect(mapStateToProps, mapDispatchToProps)(TechClockedInList);

View File

@@ -30,8 +30,9 @@ const TechJobStatistics = ({ technician }) => {
end: endDate.format("YYYY-MM-DD"), end: endDate.format("YYYY-MM-DD"),
fixedStart: dayjs().startOf("month").format("YYYY-MM-DD"), fixedStart: dayjs().startOf("month").format("YYYY-MM-DD"),
fixedEnd: dayjs().endOf("month").format("YYYY-MM-DD"), fixedEnd: dayjs().endOf("month").format("YYYY-MM-DD"),
employeeid: technician.id, employeeid: technician?.id,
}, },
skip: !technician,
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
} }

View File

@@ -33,7 +33,8 @@ export function TechLogin({
const navigate = useNavigate(); const navigate = useNavigate();
const handleFinish = (values) => { const handleFinish = (values) => {
techLoginStart(values); // Remap these because EmployeeID form name has previously been used in the project
techLoginStart({pin: values.pin, employeeid: values.techEmployeeId});
}; };
useEffect(() => { useEffect(() => {
@@ -49,7 +50,8 @@ export function TechLogin({
> >
<Form.Item <Form.Item
label={t("tech.fields.employeeid")} label={t("tech.fields.employeeid")}
name="employeeid" name="techEmployeeId"
rules={[ rules={[
{ {
required: true, required: true,

View File

@@ -37,7 +37,7 @@ export default function TimeTicketsDatesSelector() {
return ( return (
<DatePicker.RangePicker <DatePicker.RangePicker
defaultValue={[ defaultValue={[
start ? dayjs(start) : dayjs().startOf("week").subtract(7, "days"), start ? dayjs(start) : dayjs().startOf("week").subtract(7, "day"),
end ? dayjs(end) : dayjs().endOf("week"), end ? dayjs(end) : dayjs().endOf("week"),
]} ]}
format="MM/DD/YYYY" format="MM/DD/YYYY"

View File

@@ -23,7 +23,7 @@ export default function TimeTicketsAttendanceTable() {
variables: { variables: {
start: start start: start
? start ? start
: dayjs().startOf("week").subtract(7, "days").format("YYYY-MM-DD"), : dayjs().startOf("week").subtract(7, "day").format("YYYY-MM-DD"),
end: end ? end : dayjs().endOf("week").format("YYYY-MM-DD"), end: end ? end : dayjs().endOf("week").format("YYYY-MM-DD"),
}, },
}, },

View File

@@ -22,7 +22,7 @@ export default function TimeTicketsPayrollTable() {
variables: { variables: {
start: start start: start
? start ? start
: dayjs().startOf("week").subtract(7, "days").format("YYYY-MM-DD"), : dayjs().startOf("week").subtract(7, "day").format("YYYY-MM-DD"),
end: end ? end : dayjs().endOf("week").format("YYYY-MM-DD"), end: end ? end : dayjs().endOf("week").format("YYYY-MM-DD"),
}, },
}, },

View File

@@ -18,20 +18,36 @@ import {
} from "../../redux/application/application.actions"; } from "../../redux/application/application.actions";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
/**
* Mapping state to props
*/
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
/**
* Mapping dispatch to props
*/
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)), setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
}); });
/**
* ScoreboardContainer component
* @param {Object} props - The props that were defined by the caller of this component.
* @param {Function} props.setBreadcrumbs - Function to set breadcrumbs.
* @param {Function} props.setSelectedHeader - Function to set selected header.
*/
export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) { export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) {
const { t } = useTranslation(); const { t } = useTranslation();
const searchParams = queryString.parse(useLocation().search); const searchParams = queryString.parse(useLocation().search);
const { tab } = searchParams; const { tab } = searchParams;
const history = useNavigate(); const history = useNavigate();
/**
* useEffect hook to set document title, selected header and breadcrumbs
*/
useEffect(() => { useEffect(() => {
document.title = t("titles.scoreboard"); document.title = t("titles.scoreboard");
setSelectedHeader("scoreboard"); setSelectedHeader("scoreboard");
@@ -43,6 +59,9 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) {
]); ]);
}, [t, setBreadcrumbs, setSelectedHeader]); }, [t, setBreadcrumbs, setSelectedHeader]);
/**
* Render the component
*/
return ( return (
<FeatureWrapper featureName="scoreboard"> <FeatureWrapper featureName="scoreboard">
<RbacWrapper action="scoreboard:view"> <RbacWrapper action="scoreboard:view">
@@ -97,6 +116,10 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) {
</FeatureWrapper> </FeatureWrapper>
); );
} }
/**
* Connecting the component to Redux store
*/
export default connect( export default connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps

View File

@@ -37,7 +37,7 @@ export function TimeTicketsContainer({
const startDate = start const startDate = start
? dayjs(start) ? dayjs(start)
: dayjs().startOf("week").subtract(7, "days"); : dayjs().startOf("week").subtract(7, "day");
const endDate = end ? dayjs(end) : dayjs().endOf("week"); const endDate = end ? dayjs(end) : dayjs().endOf("week");
const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE, { const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE, {

View File

@@ -209,9 +209,9 @@ export function* calculateScheduleLoad({ payload: end }) {
const range = Math.round(dayjs.duration(end.diff(today)).asDays()) + 1; const range = Math.round(dayjs.duration(end.diff(today)).asDays()) + 1;
for (var day = 0; day < range; day++) { for (var day = 0; day < range; day++) {
const current = dayjs(today).add(day, "days").format("yyyy-MM-DD"); const current = dayjs(today).add(day, "day").format("yyyy-MM-DD");
const prev = dayjs(today) const prev = dayjs(today)
.add(day - 1, "days") .add(day - 1, "day")
.format("yyyy-MM-DD"); .format("yyyy-MM-DD");
if (!!!load[current]) { if (!!!load[current]) {
load[current] = {}; load[current] = {};

View File

@@ -1,10 +1,10 @@
import dayjs from "./day"; import dayjs from "./day";
const range = { const range = {
Today: [dayjs(), dayjs()], Today: [dayjs(), dayjs()],
"Last 14 days": [dayjs().subtract(14, "days"), dayjs()], "Last 14 days": [dayjs().subtract(14, "day"), dayjs()],
"Last 7 days": [dayjs().subtract(7, "days"), dayjs()], "Last 7 days": [dayjs().subtract(7, "day"), dayjs()],
"Next 7 days": [dayjs(), dayjs().add(7, "days")], "Next 7 days": [dayjs(), dayjs().add(7, "day")],
"Next 14 days": [dayjs(), dayjs().add(14, "days")], "Next 14 days": [dayjs(), dayjs().add(14, "day")],
"Last Month": [ "Last Month": [
dayjs().startOf("month").subtract(1, "month"), dayjs().startOf("month").subtract(1, "month"),
dayjs().startOf("month").subtract(1, "month").endOf("month"), dayjs().startOf("month").subtract(1, "month").endOf("month"),
@@ -15,13 +15,13 @@ const range = {
dayjs().startOf("month").add(1, "month").endOf("month"), dayjs().startOf("month").add(1, "month").endOf("month"),
], ],
"Last Quarter": [ "Last Quarter": [
dayjs().startOf("quarter").subtract(1, "quarters"), dayjs().startOf("quarter").subtract(1, "quarter"),
dayjs().startOf("quarter").subtract(1, "day"), dayjs().startOf("quarter").subtract(1, "day"),
], ],
"This Quarter": [ "This Quarter": [
dayjs().startOf("quarter"), dayjs().startOf("quarter"),
dayjs().startOf("quarter").add(1, "quarter").subtract(1, "day"), dayjs().startOf("quarter").add(1, "quarter").subtract(1, "day"),
], ],
"Last 90 Days": [dayjs().add(-90, "days"), dayjs()], "Last 90 Days": [dayjs().add(-90, "day"), dayjs()],
}; };
export default range; export default range;

View File

@@ -1,4 +1,5 @@
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import dayjsBusinessDays from "dayjs-business-days2"; import dayjsBusinessDays from "dayjs-business-days2";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter";
import updateLocale from 'dayjs/plugin/updateLocale'; import updateLocale from 'dayjs/plugin/updateLocale';
@@ -30,6 +31,7 @@ import isYesterday from 'dayjs/plugin/isYesterday';
import objectSupport from 'dayjs/plugin/objectSupport'; import objectSupport from 'dayjs/plugin/objectSupport';
import toArray from 'dayjs/plugin/toArray'; import toArray from 'dayjs/plugin/toArray';
import toObject from 'dayjs/plugin/toObject'; import toObject from 'dayjs/plugin/toObject';
// import badMutable from 'dayjs/plugin/badMutable'; // import badMutable from 'dayjs/plugin/badMutable';
// import preParsePostFormat from 'dayjs/plugin/preParsePostFormat'; // import preParsePostFormat from 'dayjs/plugin/preParsePostFormat';
@@ -42,7 +44,6 @@ dayjs.extend(isYesterday);
dayjs.extend(isTomorrow); dayjs.extend(isTomorrow);
dayjs.extend(isToday); dayjs.extend(isToday);
dayjs.extend(localeData); dayjs.extend(localeData);
dayjs.extend(relativeTime);
dayjs.extend(quarterOfYear); dayjs.extend(quarterOfYear);
dayjs.extend(localizedFormat); dayjs.extend(localizedFormat);
// dayjs.extend(preParsePostFormat); // TODO: This should not be needed // dayjs.extend(preParsePostFormat); // TODO: This should not be needed
@@ -57,6 +58,7 @@ dayjs.extend(calendar);
dayjs.extend(arraySupport); dayjs.extend(arraySupport);
dayjs.extend(advancedFormat); dayjs.extend(advancedFormat);
dayjs.extend(duration); dayjs.extend(duration);
dayjs.extend(relativeTime);
dayjs.extend(pluralGetSet); dayjs.extend(pluralGetSet);
dayjs.extend(customParseFormat); dayjs.extend(customParseFormat);
dayjs.extend(utc); dayjs.extend(utc);