From 83e4fb3dc46b10302ba940556b776e4316664804 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Thu, 14 Dec 2023 13:20:43 -0500 Subject: [PATCH] Updates Signed-off-by: Dave Richer --- .../bill-form/bill-form.component.jsx | 958 +++++++++--------- .../schedule-calendar-util.js | 6 +- .../schedule-job-modal.component.jsx | 2 +- .../schedule-verify-integrity.component.jsx | 2 +- ...rd-timetickets.targets-table.component.jsx | 4 +- .../scoreboard-timetickets.component.jsx | 2 +- .../tech-job-clock-in-form.component.jsx | 2 + .../tech-job-clock-in-form.container.jsx | 14 +- .../tech-job-clocked-in-list.component.jsx | 165 +-- .../tech-job-statistics.component.jsx | 3 +- .../tech-login/tech-login.component.jsx | 6 +- .../time-tickets-dates-selector.component.jsx | 2 +- ...ime-tickets-attendance-table.component.jsx | 2 +- .../time-tickets-payroll-table.component.jsx | 2 +- .../scoreboard/scoreboard.page.container.jsx | 25 +- .../time-tickets/time-tickets.container.jsx | 2 +- .../redux/application/application.sagas.js | 4 +- client/src/utils/DatePickerRanges.js | 12 +- client/src/utils/day.js | 4 +- 19 files changed, 623 insertions(+), 594 deletions(-) diff --git a/client/src/components/bill-form/bill-form.component.jsx b/client/src/components/bill-form/bill-form.component.jsx index 3d805fe11..320d6ed74 100644 --- a/client/src/components/bill-form/bill-form.component.jsx +++ b/client/src/components/bill-form/bill-form.component.jsx @@ -1,26 +1,16 @@ -import Icon, { UploadOutlined } from "@ant-design/icons"; -import { useApolloClient } from "@apollo/client"; -import { useTreatments } from "@splitsoftware/splitio-react"; -import { - Alert, - Divider, - Form, - Input, - Select, - Space, - Statistic, - Switch, - Upload, -} from "antd"; +import Icon, {UploadOutlined} from "@ant-design/icons"; +import {useApolloClient} from "@apollo/client"; +import {useTreatments} from "@splitsoftware/splitio-react"; +import {Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload,} from "antd"; import dayjs from "../../utils/day"; -import React, { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { MdOpenInNew } from "react-icons/md"; -import { connect } from "react-redux"; -import { Link } from "react-router-dom"; -import { createStructuredSelector } from "reselect"; -import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries"; -import { selectBodyshop } from "../../redux/user/user.selectors"; +import React, {useEffect, useState} from "react"; +import {useTranslation} from "react-i18next"; +import {MdOpenInNew} from "react-icons/md"; +import {connect} from "react-redux"; +import {Link} from "react-router-dom"; +import {createStructuredSelector} from "reselect"; +import {CHECK_BILL_INVOICE_NUMBER} from "../../graphql/bills.queries"; +import {selectBodyshop} from "../../redux/user/user.selectors"; import AlertComponent from "../alert/alert.component"; import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component"; import FormDatePicker from "../form-date-picker/form-date-picker.component"; @@ -30,488 +20,488 @@ import JobSearchSelect from "../job-search-select/job-search-select.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component"; import BillFormLines from "./bill-form.lines.component"; -import { CalculateBillTotal } from "./bill-form.totals.utility"; +import {CalculateBillTotal} from "./bill-form.totals.utility"; const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, + bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({}); export function BillFormComponent({ - bodyshop, - disabled, - form, - vendorAutoCompleteOptions, - lineData, - responsibilityCenters, - loadLines, - billEdit, - disableInvNumber, - job, - loadOutstandingReturns, - loadInventory, - preferredMake, -}) { - const { t } = useTranslation(); - const client = useApolloClient(); - const [discount, setDiscount] = useState(0); - const { Extended_Bill_Posting } = useTreatments( - ["Extended_Bill_Posting"], - {}, - bodyshop.imexshopid - ); - const { ClosingPeriod } = useTreatments( - ["ClosingPeriod"], - {}, - bodyshop.imexshopid - ); + bodyshop, + disabled, + form, + vendorAutoCompleteOptions, + lineData, + responsibilityCenters, + loadLines, + billEdit, + disableInvNumber, + job, + loadOutstandingReturns, + loadInventory, + preferredMake, + }) { + const {t} = useTranslation(); + const client = useApolloClient(); + const [discount, setDiscount] = useState(0); + const {Extended_Bill_Posting} = useTreatments( + ["Extended_Bill_Posting"], + {}, + bodyshop.imexshopid + ); + const {ClosingPeriod} = useTreatments( + ["ClosingPeriod"], + {}, + bodyshop.imexshopid + ); - const handleVendorSelect = (props, opt) => { - setDiscount(opt.discount); + const handleVendorSelect = (props, opt) => { + setDiscount(opt.discount); - opt && - !billEdit && - loadOutstandingReturns({ - variables: { - jobId: form.getFieldValue("jobid"), - vendorId: opt.value, - }, - }); - }; - - useEffect(() => { - if (job) form.validateFields(["is_credit_memo"]); - }, [job, form]); - - useEffect(() => { - const vendorId = form.getFieldValue("vendorid"); - if (vendorId && vendorAutoCompleteOptions) { - const matchingVendors = vendorAutoCompleteOptions.filter( - (v) => v.id === vendorId - ); - if (matchingVendors.length === 1) { - setDiscount(matchingVendors[0].discount); - } - } - const jobId = form.getFieldValue("jobid"); - if (jobId) { - loadLines({ variables: { id: jobId } }); - if (form.getFieldValue("is_credit_memo") && vendorId && !billEdit) { + opt && + !billEdit && loadOutstandingReturns({ - variables: { - jobId: jobId, - vendorId: vendorId, - }, + variables: { + jobId: form.getFieldValue("jobid"), + vendorId: opt.value, + }, }); - } - } + }; - if (vendorId === bodyshop.inhousevendorid && !billEdit) { - loadInventory(); - } - }, [ - form, - billEdit, - loadOutstandingReturns, - loadInventory, - setDiscount, - vendorAutoCompleteOptions, - loadLines, - bodyshop.inhousevendorid, - ]); + useEffect(() => { + if (job) form.validateFields(["is_credit_memo"]); + }, [job, form]); - return ( -
- - - - - - - { - if (form.getFieldValue("jobid") !== null) { - loadLines({ variables: { id: form.getFieldValue("jobid") } }); - if (form.getFieldValue("vendorid") !== null) { - loadOutstandingReturns({ - variables: { - jobId: form.getFieldValue("jobid"), - vendorId: form.getFieldValue("vendorid"), - }, - }); - } - } - }} - /> - - ({ - validator(rule, value) { - if ( - value && - !getFieldValue(["isinhouse"]) && - value === bodyshop.inhousevendorid - ) { - return Promise.reject(t("bills.validation.manualinhouse")); - } - return Promise.resolve(); - }, - }), - ]} - > - - - - {job && - job.ious && - job.ious.length > 0 && - job.ious.map((iou) => ( - - {t("bills.labels.iouexists")} - - - {iou.ro_number} - - - - + useEffect(() => { + const vendorId = form.getFieldValue("vendorid"); + if (vendorId && vendorAutoCompleteOptions) { + const matchingVendors = vendorAutoCompleteOptions.filter( + (v) => v.id === vendorId + ); + if (matchingVendors.length === 1) { + setDiscount(matchingVendors[0].discount); } - /> - ))} - - ({ - async validator(rule, value) { - const vendorid = getFieldValue("vendorid"); - if (vendorid && value) { - const response = await client.query({ - query: CHECK_BILL_INVOICE_NUMBER, + } + const jobId = form.getFieldValue("jobid"); + if (jobId) { + loadLines({variables: {id: jobId}}); + if (form.getFieldValue("is_credit_memo") && vendorId && !billEdit) { + loadOutstandingReturns({ variables: { - invoice_number: value, - vendorid: vendorid, + jobId: jobId, + vendorId: vendorId, }, - }); + }); + } + } - if (response.data.bills_aggregate.aggregate.count === 0) { - return Promise.resolve(); - } else if ( - response.data.bills_aggregate.nodes.length === 1 && - response.data.bills_aggregate.nodes[0].id === - form.getFieldValue("id") - ) { - return Promise.resolve(); - } - return Promise.reject( - t("bills.validation.unique_invoice_number") - ); - } else { - return Promise.resolve(); - } - }, - }), - ]} - > - - - ({ - validator(rule, value) { - if ( - ClosingPeriod.treatment === "on" && - bodyshop.accountingconfig.ClosingPeriod - ) { - if ( - dayjs(value) - .startOf("day") - .isSameOrAfter( - dayjs( - bodyshop.accountingconfig.ClosingPeriod[0] - ).startOf("day") - ) && - dayjs(value) - .startOf("day") - .isSameOrBefore( - dayjs( - bodyshop.accountingconfig.ClosingPeriod[1] - ).endOf("day") - ) - ) { - return Promise.resolve(); - } else { - return Promise.reject(t("bills.validation.closingperiod")); - } - } else { - return Promise.resolve(); - } - }, - }), - ]} - > - - - ({ - validator(rule, value) { - if ( - value === true && - getFieldValue("jobid") && - getFieldValue("vendorid") - ) { - //Removed as this would cause an additional reload when validating the form on submit and clear the values. - // loadOutstandingReturns({ - // variables: { - // jobId: form.getFieldValue("jobid"), - // vendorId: form.getFieldValue("vendorid"), - // }, - // }); - } + if (vendorId === bodyshop.inhousevendorid && !billEdit) { + loadInventory(); + } + }, [ + form, + billEdit, + loadOutstandingReturns, + loadInventory, + setDiscount, + vendorAutoCompleteOptions, + loadLines, + bodyshop.inhousevendorid, + ]); - if ( - !bodyshop.bill_allow_post_to_closed && - job && - (job.status === bodyshop.md_ro_statuses.default_invoiced || - job.status === bodyshop.md_ro_statuses.default_exported || - job.status === bodyshop.md_ro_statuses.default_void) && - (value === false || !value) - ) { - return Promise.reject(t("bills.labels.onlycmforinvoiced")); - } + return ( +
+ + + + + + + { + if (form.getFieldValue("jobid") !== null) { + loadLines({variables: {id: form.getFieldValue("jobid")}}); + if (form.getFieldValue("vendorid") !== null) { + loadOutstandingReturns({ + variables: { + jobId: form.getFieldValue("jobid"), + vendorId: form.getFieldValue("vendorid"), + }, + }); + } + } + }} + /> + + ({ + validator(rule, value) { + if ( + value && + !getFieldValue(["isinhouse"]) && + value === bodyshop.inhousevendorid + ) { + return Promise.reject(t("bills.validation.manualinhouse")); + } + return Promise.resolve(); + }, + }), + ]} + > + + + + {job && + job.ious && + job.ious.length > 0 && + job.ious.map((iou) => ( + + {t("bills.labels.iouexists")} + + + {iou.ro_number} + + + + + } + /> + ))} + + ({ + async validator(rule, value) { + const vendorid = getFieldValue("vendorid"); + if (vendorid && value) { + const response = await client.query({ + query: CHECK_BILL_INVOICE_NUMBER, + variables: { + invoice_number: value, + vendorid: vendorid, + }, + }); - return Promise.resolve(); - }, - }), - ]} - > - - - - - - {!billEdit && ( - - - - )} - - - - - - - - - - - - - {() => { - const values = form.getFieldsValue([ - "billlines", - "total", - "federal_tax_rate", - "state_tax_rate", - "local_tax_rate", - ]); - let totals; - if ( - !!values.total && - !!values.billlines && - values.billlines.length > 0 - ) - totals = CalculateBillTotal(values); - if (!!totals) - return ( -
- - - - - - - - - - {form.getFieldValue("is_credit_memo") ? ( - - ) : null} -
- ); - return null; - }} -
-
- {t("bills.labels.bill_lines")} + if (response.data.bills_aggregate.aggregate.count === 0) { + return Promise.resolve(); + } else if ( + response.data.bills_aggregate.nodes.length === 1 && + response.data.bills_aggregate.nodes[0].id === + form.getFieldValue("id") + ) { + return Promise.resolve(); + } + return Promise.reject( + t("bills.validation.unique_invoice_number") + ); + } else { + return Promise.resolve(); + } + }, + }), + ]} + > + + + ({ + validator(rule, value) { + if ( + ClosingPeriod.treatment === "on" && + bodyshop.accountingconfig.ClosingPeriod + ) { + if ( + dayjs(value) + .startOf("day") + .isSameOrAfter( + dayjs( + bodyshop.accountingconfig.ClosingPeriod[0] + ).startOf("day") + ) && + dayjs(value) + .startOf("day") + .isSameOrBefore( + dayjs( + bodyshop.accountingconfig.ClosingPeriod[1] + ).endOf("day") + ) + ) { + return Promise.resolve(); + } else { + return Promise.reject(t("bills.validation.closingperiod")); + } + } else { + return Promise.resolve(); + } + }, + }), + ]} + > + + + ({ + validator(rule, value) { + if ( + value === true && + getFieldValue("jobid") && + getFieldValue("vendorid") + ) { + //Removed as this would cause an additional reload when validating the form on submit and clear the values. + // loadOutstandingReturns({ + // variables: { + // jobId: form.getFieldValue("jobid"), + // vendorId: form.getFieldValue("vendorid"), + // }, + // }); + } - {Extended_Bill_Posting.treatment === "on" ? ( - - ) : ( - - )} + if ( + !bodyshop.bill_allow_post_to_closed && + job && + (job.status === bodyshop.md_ro_statuses.default_invoiced || + job.status === bodyshop.md_ro_statuses.default_exported || + job.status === bodyshop.md_ro_statuses.default_void) && + (value === false || !value) + ) { + return Promise.reject(t("bills.labels.onlycmforinvoiced")); + } - { - if (Array.isArray(e)) { - return e; - } - return e && e.fileList; - }} - > - false} - listType="picture" - > - <> -

- -

-

- Click or drag files to this area to upload. -

- -
-
-
- ); + return Promise.resolve(); + }, + }), + ]} + > + +
+ + + + {!billEdit && ( + + + + )} +
+ + + + + + + + + + + + {() => { + const values = form.getFieldsValue([ + "billlines", + "total", + "federal_tax_rate", + "state_tax_rate", + "local_tax_rate", + ]); + let totals; + if ( + !!values.total && + !!values.billlines && + values.billlines.length > 0 + ) + totals = CalculateBillTotal(values); + if (!!totals) + return ( +
+ + + + + + + + + + {form.getFieldValue("is_credit_memo") ? ( + + ) : null} +
+ ); + return null; + }} +
+
+ {t("bills.labels.bill_lines")} + + {Extended_Bill_Posting.treatment === "on" ? ( + + ) : ( + + )} + + { + if (Array.isArray(e)) { + return e; + } + return e && e.fileList; + }} + > + false} + listType="picture" + > + <> +

+ +

+

+ Click or drag files to this area to upload. +

+ +
+
+
+ ); } export default connect(mapStateToProps, mapDispatchToProps)(BillFormComponent); diff --git a/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js b/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js index 1f2fbadea..554c837db 100644 --- a/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js +++ b/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js @@ -14,10 +14,10 @@ export function getRange(dateParam, viewParam) { start = dayjs(date).startOf("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") { - start = dayjs(date).startOf("month").subtract(7, "days"); - end = dayjs(date).endOf("month").add(7, "days"); + start = dayjs(date).startOf("month").subtract(7, "day"); + 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'); else if (view === "agenda") { diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx index 1e60264ff..573c19ba2 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx @@ -201,7 +201,7 @@ export function ScheduleJobModalComponent({ {() => { const values = form.getFieldsValue(); if (values.start) { - calculateScheduleLoad(dayjs(values.start).add(3, "days")); + calculateScheduleLoad(dayjs(values.start).add(3, "day")); } return (
diff --git a/client/src/components/schedule-verify-integrity/schedule-verify-integrity.component.jsx b/client/src/components/schedule-verify-integrity/schedule-verify-integrity.component.jsx index 6e390d09f..445624d8a 100644 --- a/client/src/components/schedule-verify-integrity/schedule-verify-integrity.component.jsx +++ b/client/src/components/schedule-verify-integrity/schedule-verify-integrity.component.jsx @@ -27,7 +27,7 @@ export function ScheduleVerifyIntegrity({ currentUser }) { data: { arrJobs, compJobs, prodJobs }, } = await client.query({ 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. diff --git a/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.targets-table.component.jsx b/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.targets-table.component.jsx index e9dc3b991..906069c62 100644 --- a/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.targets-table.component.jsx +++ b/client/src/components/scoreboard-timetickets-stats/scoreboard-timetickets.targets-table.component.jsx @@ -17,7 +17,7 @@ const mapDispatchToProps = (dispatch) => ({ const rowGutter = [16, 16]; const statSpans = { xs: 24, sm: 3 }; -export function ScoreboardTimeticketsTargetsTable({ bodyshop }) { +export function ScoreboardTimeTicketsTargetsTable({ bodyshop }) { const { t } = useTranslation(); return ( @@ -282,4 +282,4 @@ export function ScoreboardTimeticketsTargetsTable({ bodyshop }) { export default connect( mapStateToProps, mapDispatchToProps -)(ScoreboardTimeticketsTargetsTable); +)(ScoreboardTimeTicketsTargetsTable); diff --git a/client/src/components/scoreboard-timetickets/scoreboard-timetickets.component.jsx b/client/src/components/scoreboard-timetickets/scoreboard-timetickets.component.jsx index b764e2bc7..f5e12f818 100644 --- a/client/src/components/scoreboard-timetickets/scoreboard-timetickets.component.jsx +++ b/client/src/components/scoreboard-timetickets/scoreboard-timetickets.component.jsx @@ -17,7 +17,7 @@ export default function ScoreboardTimeTickets() { const { start, end } = searchParams; const startDate = start ? dayjs(start) - : dayjs().startOf("week").subtract(7, "days"); + : dayjs().startOf("week").subtract(7, "day"); const endDate = end ? dayjs(end) : dayjs().endOf("week"); const fixedPeriods = useMemo(() => { diff --git a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx index 77bc795a8..92ee772d4 100644 --- a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx +++ b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.component.jsx @@ -16,7 +16,9 @@ const mapStateToProps = createStructuredSelector({ export function TechClockInComponent({ form, bodyshop, technician }) { const { t } = useTranslation(); + const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0]; + return (
diff --git a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx index e500c1f8d..13308efd5 100644 --- a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx +++ b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx @@ -46,6 +46,16 @@ export function TechClockInContainer({ (e) => e.id === (technician && technician.id) )[0]; + const TechForm = () => { + if (technician) { + return
+ + + } else { + return
+ } + } + const handleFinish = async (values) => { setLoading(true); const theTime = (await axios.post("/utils/time")).data; @@ -146,9 +156,7 @@ export function TechClockInContainer({ } > -
- - + ); } diff --git a/client/src/components/tech-job-clocked-in-list/tech-job-clocked-in-list.component.jsx b/client/src/components/tech-job-clocked-in-list/tech-job-clocked-in-list.component.jsx index 7572fa9b9..aa16bcd41 100644 --- a/client/src/components/tech-job-clocked-in-list/tech-job-clocked-in-list.component.jsx +++ b/client/src/components/tech-job-clocked-in-list/tech-job-clocked-in-list.component.jsx @@ -1,100 +1,101 @@ -import { Card, List, Typography } from "antd"; +import {Card, List, Typography} from "antd"; import React from "react"; -import { useQuery } from "@apollo/client"; -import { useTranslation } from "react-i18next"; -import { connect } from "react-redux"; -import { Link } from "react-router-dom"; -import { createStructuredSelector } from "reselect"; -import { QUERY_ACTIVE_TIME_TICKETS } from "../../graphql/timetickets.queries"; -import { selectTechnician } from "../../redux/tech/tech.selectors"; -import { DateTimeFormatter } from "../../utils/DateFormatter"; +import {useQuery} from "@apollo/client"; +import {useTranslation} from "react-i18next"; +import {connect} from "react-redux"; +import {Link} from "react-router-dom"; +import {createStructuredSelector} from "reselect"; +import {QUERY_ACTIVE_TIME_TICKETS} from "../../graphql/timetickets.queries"; +import {selectTechnician} from "../../redux/tech/tech.selectors"; +import {DateTimeFormatter} from "../../utils/DateFormatter"; import AlertComponent from "../alert/alert.component"; import DataLabel from "../data-label/data-label.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import TechClockOffButton from "../tech-job-clock-out-button/tech-job-clock-out-button.component"; -import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; +import {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ - technician: selectTechnician, + technician: selectTechnician, }); const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) + //setUserLanguage: language => dispatch(setUserLanguage(language)) }); -export function TechClockedInList({ technician }) { - const { loading, error, data, refetch } = useQuery( - QUERY_ACTIVE_TIME_TICKETS, - { - variables: { - employeeId: technician.id, - }, - fetchPolicy: "network-only", - nextFetchPolicy: "network-only", - } - ); +export function TechClockedInList({technician}) { + const {loading, error, data, refetch} = useQuery( + QUERY_ACTIVE_TIME_TICKETS, + { + variables: { + employeeId: technician?.id, + }, + fetchPolicy: "network-only", + nextFetchPolicy: "network-only", + skip: !technician, + } + ); - const { t } = useTranslation(); + const {t} = useTranslation(); + if (loading) return ; + if (error) return ; - if (loading) return ; - if (error) return ; - - return ( -
- {data.timetickets.length > 0 ? ( + return (
- - {t("timetickets.labels.alreadyclockedon")} - - ( - - - {`${ - ticket.job.ro_number || t("general.labels.na") - } ${OwnerNameDisplayFunction(ticket.job)}`} - - } - actions={[ - , - ]} - > -
- {` + {data?.timetickets?.length > 0 ? ( +
+ + {t("timetickets.labels.alreadyclockedon")} + + ( + + + {`${ + ticket.job.ro_number || t("general.labels.na") + } ${OwnerNameDisplayFunction(ticket.job)}`} + + } + actions={[ + , + ]} + > +
+ {` ${ticket.job.v_model_yr || ""} ${ - ticket.job.v_make_desc || "" - } ${ticket.job.v_model_desc || ""}`} -
- - {ticket.clockon} - - - {ticket.cost_center === "timetickets.labels.shift" - ? t(ticket.cost_center) - : ticket.cost_center} - -
-
- )} - >
+ ticket.job.v_make_desc || "" + } ${ticket.job.v_model_desc || ""}`} +
+ + {ticket.clockon} + + + {ticket.cost_center === "timetickets.labels.shift" + ? t(ticket.cost_center) + : ticket.cost_center} + + + + )} + > +
+ ) : null}
- ) : null} -
- ); + ); } + export default connect(mapStateToProps, mapDispatchToProps)(TechClockedInList); diff --git a/client/src/components/tech-job-statistics/tech-job-statistics.component.jsx b/client/src/components/tech-job-statistics/tech-job-statistics.component.jsx index 479aacb33..8305bb512 100644 --- a/client/src/components/tech-job-statistics/tech-job-statistics.component.jsx +++ b/client/src/components/tech-job-statistics/tech-job-statistics.component.jsx @@ -30,8 +30,9 @@ const TechJobStatistics = ({ technician }) => { end: endDate.format("YYYY-MM-DD"), fixedStart: dayjs().startOf("month").format("YYYY-MM-DD"), fixedEnd: dayjs().endOf("month").format("YYYY-MM-DD"), - employeeid: technician.id, + employeeid: technician?.id, }, + skip: !technician, fetchPolicy: "network-only", nextFetchPolicy: "network-only", } diff --git a/client/src/components/tech-login/tech-login.component.jsx b/client/src/components/tech-login/tech-login.component.jsx index 9de429142..61b85e365 100644 --- a/client/src/components/tech-login/tech-login.component.jsx +++ b/client/src/components/tech-login/tech-login.component.jsx @@ -33,7 +33,8 @@ export function TechLogin({ const navigate = useNavigate(); 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(() => { @@ -49,7 +50,8 @@ export function TechLogin({ > ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), 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 }) { const { t } = useTranslation(); const searchParams = queryString.parse(useLocation().search); const { tab } = searchParams; const history = useNavigate(); + + /** + * useEffect hook to set document title, selected header and breadcrumbs + */ useEffect(() => { document.title = t("titles.scoreboard"); setSelectedHeader("scoreboard"); @@ -43,6 +59,9 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) { ]); }, [t, setBreadcrumbs, setSelectedHeader]); + /** + * Render the component + */ return ( @@ -97,7 +116,11 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) { ); } + +/** + * Connecting the component to Redux store + */ export default connect( mapStateToProps, mapDispatchToProps -)(ScoreboardContainer); +)(ScoreboardContainer); \ No newline at end of file diff --git a/client/src/pages/time-tickets/time-tickets.container.jsx b/client/src/pages/time-tickets/time-tickets.container.jsx index e07289ea8..5b970ad88 100644 --- a/client/src/pages/time-tickets/time-tickets.container.jsx +++ b/client/src/pages/time-tickets/time-tickets.container.jsx @@ -37,7 +37,7 @@ export function TimeTicketsContainer({ const startDate = start ? dayjs(start) - : dayjs().startOf("week").subtract(7, "days"); + : dayjs().startOf("week").subtract(7, "day"); const endDate = end ? dayjs(end) : dayjs().endOf("week"); const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE, { diff --git a/client/src/redux/application/application.sagas.js b/client/src/redux/application/application.sagas.js index 4c5f6c426..7300dcba6 100644 --- a/client/src/redux/application/application.sagas.js +++ b/client/src/redux/application/application.sagas.js @@ -209,9 +209,9 @@ export function* calculateScheduleLoad({ payload: end }) { const range = Math.round(dayjs.duration(end.diff(today)).asDays()) + 1; 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) - .add(day - 1, "days") + .add(day - 1, "day") .format("yyyy-MM-DD"); if (!!!load[current]) { load[current] = {}; diff --git a/client/src/utils/DatePickerRanges.js b/client/src/utils/DatePickerRanges.js index e86287686..43cf6980e 100644 --- a/client/src/utils/DatePickerRanges.js +++ b/client/src/utils/DatePickerRanges.js @@ -1,10 +1,10 @@ import dayjs from "./day"; const range = { Today: [dayjs(), dayjs()], - "Last 14 days": [dayjs().subtract(14, "days"), dayjs()], - "Last 7 days": [dayjs().subtract(7, "days"), dayjs()], - "Next 7 days": [dayjs(), dayjs().add(7, "days")], - "Next 14 days": [dayjs(), dayjs().add(14, "days")], + "Last 14 days": [dayjs().subtract(14, "day"), dayjs()], + "Last 7 days": [dayjs().subtract(7, "day"), dayjs()], + "Next 7 days": [dayjs(), dayjs().add(7, "day")], + "Next 14 days": [dayjs(), dayjs().add(14, "day")], "Last Month": [ dayjs().startOf("month").subtract(1, "month"), dayjs().startOf("month").subtract(1, "month").endOf("month"), @@ -15,13 +15,13 @@ const range = { dayjs().startOf("month").add(1, "month").endOf("month"), ], "Last Quarter": [ - dayjs().startOf("quarter").subtract(1, "quarters"), + dayjs().startOf("quarter").subtract(1, "quarter"), dayjs().startOf("quarter").subtract(1, "day"), ], "This Quarter": [ dayjs().startOf("quarter"), 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; diff --git a/client/src/utils/day.js b/client/src/utils/day.js index 1b6bda2a6..b16e16262 100644 --- a/client/src/utils/day.js +++ b/client/src/utils/day.js @@ -1,4 +1,5 @@ import dayjs from 'dayjs'; + import dayjsBusinessDays from "dayjs-business-days2"; import isSameOrAfter from "dayjs/plugin/isSameOrAfter"; import updateLocale from 'dayjs/plugin/updateLocale'; @@ -30,6 +31,7 @@ import isYesterday from 'dayjs/plugin/isYesterday'; import objectSupport from 'dayjs/plugin/objectSupport'; import toArray from 'dayjs/plugin/toArray'; import toObject from 'dayjs/plugin/toObject'; + // import badMutable from 'dayjs/plugin/badMutable'; // import preParsePostFormat from 'dayjs/plugin/preParsePostFormat'; @@ -42,7 +44,6 @@ dayjs.extend(isYesterday); dayjs.extend(isTomorrow); dayjs.extend(isToday); dayjs.extend(localeData); -dayjs.extend(relativeTime); dayjs.extend(quarterOfYear); dayjs.extend(localizedFormat); // dayjs.extend(preParsePostFormat); // TODO: This should not be needed @@ -57,6 +58,7 @@ dayjs.extend(calendar); dayjs.extend(arraySupport); dayjs.extend(advancedFormat); dayjs.extend(duration); +dayjs.extend(relativeTime); dayjs.extend(pluralGetSet); dayjs.extend(customParseFormat); dayjs.extend(utc);