@@ -1,26 +1,16 @@
|
|||||||
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";
|
||||||
import { MdOpenInNew } from "react-icons/md";
|
import {MdOpenInNew} from "react-icons/md";
|
||||||
import { connect } from "react-redux";
|
import {connect} from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import {createStructuredSelector} from "reselect";
|
||||||
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
|
import {CHECK_BILL_INVOICE_NUMBER} from "../../graphql/bills.queries";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";
|
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
@@ -30,7 +20,7 @@ import JobSearchSelect from "../job-search-select/job-search-select.component";
|
|||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
||||||
import BillFormLines from "./bill-form.lines.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({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -51,16 +41,16 @@ export function BillFormComponent({
|
|||||||
loadOutstandingReturns,
|
loadOutstandingReturns,
|
||||||
loadInventory,
|
loadInventory,
|
||||||
preferredMake,
|
preferredMake,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const {t} = useTranslation();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
const [discount, setDiscount] = useState(0);
|
const [discount, setDiscount] = useState(0);
|
||||||
const { Extended_Bill_Posting } = useTreatments(
|
const {Extended_Bill_Posting} = useTreatments(
|
||||||
["Extended_Bill_Posting"],
|
["Extended_Bill_Posting"],
|
||||||
{},
|
{},
|
||||||
bodyshop.imexshopid
|
bodyshop.imexshopid
|
||||||
);
|
);
|
||||||
const { ClosingPeriod } = useTreatments(
|
const {ClosingPeriod} = useTreatments(
|
||||||
["ClosingPeriod"],
|
["ClosingPeriod"],
|
||||||
{},
|
{},
|
||||||
bodyshop.imexshopid
|
bodyshop.imexshopid
|
||||||
@@ -95,7 +85,7 @@ export function BillFormComponent({
|
|||||||
}
|
}
|
||||||
const jobId = form.getFieldValue("jobid");
|
const jobId = form.getFieldValue("jobid");
|
||||||
if (jobId) {
|
if (jobId) {
|
||||||
loadLines({ variables: { id: jobId } });
|
loadLines({variables: {id: jobId}});
|
||||||
if (form.getFieldValue("is_credit_memo") && vendorId && !billEdit) {
|
if (form.getFieldValue("is_credit_memo") && vendorId && !billEdit) {
|
||||||
loadOutstandingReturns({
|
loadOutstandingReturns({
|
||||||
variables: {
|
variables: {
|
||||||
@@ -122,13 +112,13 @@ export function BillFormComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormFieldsChanged form={form} />
|
<FormFieldsChanged form={form}/>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
style={{ display: "none" }}
|
style={{display: "none"}}
|
||||||
name="isinhouse"
|
name="isinhouse"
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
>
|
>
|
||||||
<Switch />
|
<Switch/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<LayoutFormRow grow>
|
<LayoutFormRow grow>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -147,7 +137,7 @@ export function BillFormComponent({
|
|||||||
notExported={false}
|
notExported={false}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
if (form.getFieldValue("jobid") !== null) {
|
if (form.getFieldValue("jobid") !== null) {
|
||||||
loadLines({ variables: { id: form.getFieldValue("jobid") } });
|
loadLines({variables: {id: form.getFieldValue("jobid")}});
|
||||||
if (form.getFieldValue("vendorid") !== null) {
|
if (form.getFieldValue("vendorid") !== null) {
|
||||||
loadOutstandingReturns({
|
loadOutstandingReturns({
|
||||||
variables: {
|
variables: {
|
||||||
@@ -169,7 +159,7 @@ export function BillFormComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
({ getFieldValue }) => ({
|
({getFieldValue}) => ({
|
||||||
validator(rule, value) {
|
validator(rule, value) {
|
||||||
if (
|
if (
|
||||||
value &&
|
value &&
|
||||||
@@ -208,7 +198,7 @@ export function BillFormComponent({
|
|||||||
>
|
>
|
||||||
<Space>
|
<Space>
|
||||||
{iou.ro_number}
|
{iou.ro_number}
|
||||||
<Icon component={MdOpenInNew} />
|
<Icon component={MdOpenInNew}/>
|
||||||
</Space>
|
</Space>
|
||||||
</Link>
|
</Link>
|
||||||
</Space>
|
</Space>
|
||||||
@@ -226,7 +216,7 @@ export function BillFormComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
({ getFieldValue }) => ({
|
({getFieldValue}) => ({
|
||||||
async validator(rule, value) {
|
async validator(rule, value) {
|
||||||
const vendorid = getFieldValue("vendorid");
|
const vendorid = getFieldValue("vendorid");
|
||||||
if (vendorid && value) {
|
if (vendorid && value) {
|
||||||
@@ -257,7 +247,7 @@ export function BillFormComponent({
|
|||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input disabled={disabled || disableInvNumber} />
|
<Input disabled={disabled || disableInvNumber}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bills.fields.date")}
|
label={t("bills.fields.date")}
|
||||||
@@ -267,7 +257,7 @@ export function BillFormComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
({ getFieldValue }) => ({
|
({getFieldValue}) => ({
|
||||||
validator(rule, value) {
|
validator(rule, value) {
|
||||||
if (
|
if (
|
||||||
ClosingPeriod.treatment === "on" &&
|
ClosingPeriod.treatment === "on" &&
|
||||||
@@ -300,14 +290,14 @@ export function BillFormComponent({
|
|||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<FormDatePicker disabled={disabled} />
|
<FormDatePicker disabled={disabled}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bills.fields.is_credit_memo")}
|
label={t("bills.fields.is_credit_memo")}
|
||||||
name="is_credit_memo"
|
name="is_credit_memo"
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
rules={[
|
rules={[
|
||||||
({ getFieldValue }) => ({
|
({getFieldValue}) => ({
|
||||||
validator(rule, value) {
|
validator(rule, value) {
|
||||||
if (
|
if (
|
||||||
value === true &&
|
value === true &&
|
||||||
@@ -339,7 +329,7 @@ export function BillFormComponent({
|
|||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Switch />
|
<Switch/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bills.fields.total")}
|
label={t("bills.fields.total")}
|
||||||
@@ -351,11 +341,11 @@ export function BillFormComponent({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<CurrencyInput min={0} disabled={disabled} />
|
<CurrencyInput min={0} disabled={disabled}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{!billEdit && (
|
{!billEdit && (
|
||||||
<Form.Item label={t("bills.fields.allpartslocation")} name="location">
|
<Form.Item label={t("bills.fields.allpartslocation")} name="location">
|
||||||
<Select style={{ width: "10rem" }} disabled={disabled} allowClear>
|
<Select style={{width: "10rem"}} disabled={disabled} allowClear>
|
||||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||||
<Select.Option key={idx} value={loc}>
|
<Select.Option key={idx} value={loc}>
|
||||||
{loc}
|
{loc}
|
||||||
@@ -371,21 +361,21 @@ export function BillFormComponent({
|
|||||||
label={t("bills.fields.federal_tax_rate")}
|
label={t("bills.fields.federal_tax_rate")}
|
||||||
name="federal_tax_rate"
|
name="federal_tax_rate"
|
||||||
>
|
>
|
||||||
<CurrencyInput min={0} disabled={disabled} />
|
<CurrencyInput min={0} disabled={disabled}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
span={3}
|
span={3}
|
||||||
label={t("bills.fields.state_tax_rate")}
|
label={t("bills.fields.state_tax_rate")}
|
||||||
name="state_tax_rate"
|
name="state_tax_rate"
|
||||||
>
|
>
|
||||||
<CurrencyInput min={0} disabled={disabled} />
|
<CurrencyInput min={0} disabled={disabled}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
span={3}
|
span={3}
|
||||||
label={t("bills.fields.local_tax_rate")}
|
label={t("bills.fields.local_tax_rate")}
|
||||||
name="local_tax_rate"
|
name="local_tax_rate"
|
||||||
>
|
>
|
||||||
<CurrencyInput min={0} />
|
<CurrencyInput min={0}/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item shouldUpdate span={15}>
|
<Form.Item shouldUpdate span={15}>
|
||||||
{() => {
|
{() => {
|
||||||
@@ -485,7 +475,7 @@ export function BillFormComponent({
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
name="upload"
|
name="upload"
|
||||||
label="Upload"
|
label="Upload"
|
||||||
style={{ display: billEdit ? "none" : null }}
|
style={{display: billEdit ? "none" : null}}
|
||||||
valuePropName="fileList"
|
valuePropName="fileList"
|
||||||
getValueFromEvent={(e) => {
|
getValueFromEvent={(e) => {
|
||||||
if (Array.isArray(e)) {
|
if (Array.isArray(e)) {
|
||||||
@@ -502,7 +492,7 @@ export function BillFormComponent({
|
|||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<p className="ant-upload-drag-icon">
|
<p className="ant-upload-drag-icon">
|
||||||
<UploadOutlined />
|
<UploadOutlined/>
|
||||||
</p>
|
</p>
|
||||||
<p className="ant-upload-text">
|
<p className="ant-upload-text">
|
||||||
Click or drag files to this area to upload.
|
Click or drag files to this area to upload.
|
||||||
|
|||||||
@@ -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") {
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { Card, List, Typography } from "antd";
|
import {Card, List, Typography} from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useQuery } from "@apollo/client";
|
import {useQuery} from "@apollo/client";
|
||||||
import { useTranslation } from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import {connect} from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import {createStructuredSelector} from "reselect";
|
||||||
import { QUERY_ACTIVE_TIME_TICKETS } from "../../graphql/timetickets.queries";
|
import {QUERY_ACTIVE_TIME_TICKETS} from "../../graphql/timetickets.queries";
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
import {selectTechnician} from "../../redux/tech/tech.selectors";
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
import {DateTimeFormatter} from "../../utils/DateFormatter";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import DataLabel from "../data-label/data-label.component";
|
import DataLabel from "../data-label/data-label.component";
|
||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
import TechClockOffButton from "../tech-job-clock-out-button/tech-job-clock-out-button.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({
|
const mapStateToProps = createStructuredSelector({
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
@@ -21,26 +21,26 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
});
|
});
|
||||||
|
|
||||||
export function TechClockedInList({ technician }) {
|
export function TechClockedInList({technician}) {
|
||||||
const { loading, error, data, refetch } = useQuery(
|
const {loading, error, data, refetch} = useQuery(
|
||||||
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);
|
||||||
|
|||||||
@@ -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",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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, {
|
||||||
|
|||||||
@@ -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] = {};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user