Merged in release/2021-10-01 (pull request #228)
release/2021-10-01 Approved-by: Patrick Fic
This commit is contained in:
@@ -1,11 +1,24 @@
|
|||||||
import { useMutation } from "@apollo/client";
|
import { useMutation, useLazyQuery } from "@apollo/client";
|
||||||
import { Button, Card, Form, InputNumber, notification, Popover } from "antd";
|
import {
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Form,
|
||||||
|
InputNumber,
|
||||||
|
notification,
|
||||||
|
Popover,
|
||||||
|
Space,
|
||||||
|
} from "antd";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import { INSERT_SCOREBOARD_ENTRY } from "../../graphql/scoreboard.queries";
|
import {
|
||||||
|
INSERT_SCOREBOARD_ENTRY,
|
||||||
|
QUERY_SCOREBOARD_ENTRY,
|
||||||
|
UPDATE_SCOREBOARD_ENTRY,
|
||||||
|
} from "../../graphql/scoreboard.queries";
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
|
|
||||||
export default function ScoreboardAddButton({
|
export default function ScoreboardAddButton({
|
||||||
job,
|
job,
|
||||||
@@ -14,17 +27,46 @@ export default function ScoreboardAddButton({
|
|||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [insertScoreboardEntry] = useMutation(INSERT_SCOREBOARD_ENTRY);
|
const [insertScoreboardEntry] = useMutation(INSERT_SCOREBOARD_ENTRY);
|
||||||
|
const [updateScoreboardEntry] = useMutation(UPDATE_SCOREBOARD_ENTRY);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [visibility, setVisibility] = useState(false);
|
const [visibility, setVisibility] = useState(false);
|
||||||
|
const [callQuery, { loading: entryLoading, data: entryData }] = useLazyQuery(
|
||||||
|
QUERY_SCOREBOARD_ENTRY
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (visibility) {
|
||||||
|
callQuery({ variables: { jobid: job.id } });
|
||||||
|
}
|
||||||
|
}, [visibility, job.id, callQuery]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("UE", entryData);
|
||||||
|
if (entryData && entryData.scoreboard && entryData.scoreboard[0]) {
|
||||||
|
console.log("Setting FOrm");
|
||||||
|
form.setFieldsValue(entryData.scoreboard[0]);
|
||||||
|
}
|
||||||
|
}, [entryData, form]);
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (values) => {
|
||||||
logImEXEvent("job_close_add_to_scoreboard");
|
logImEXEvent("job_close_add_to_scoreboard");
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const result = await insertScoreboardEntry({
|
let result;
|
||||||
variables: { sbInput: [{ jobid: job.id, ...values }] },
|
|
||||||
});
|
if (entryData && entryData.scoreboard && entryData.scoreboard[0]) {
|
||||||
|
result = await updateScoreboardEntry({
|
||||||
|
variables: {
|
||||||
|
sbId: entryData.scoreboard[0].id,
|
||||||
|
sbInput: values,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
result = await insertScoreboardEntry({
|
||||||
|
variables: { sbInput: [{ jobid: job.id, ...values }] },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!!result.errors) {
|
if (!!result.errors) {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
@@ -44,53 +86,62 @@ export default function ScoreboardAddButton({
|
|||||||
const overlay = (
|
const overlay = (
|
||||||
<Card>
|
<Card>
|
||||||
<div>
|
<div>
|
||||||
<Form
|
{entryLoading ? (
|
||||||
form={form}
|
<LoadingSpinner />
|
||||||
layout="vertical"
|
) : (
|
||||||
onFinish={handleFinish}
|
<Form
|
||||||
initialValues={{}}
|
form={form}
|
||||||
>
|
layout="vertical"
|
||||||
<Form.Item
|
onFinish={handleFinish}
|
||||||
label={t("scoreboard.fields.date")}
|
initialValues={{}}
|
||||||
name="date"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<FormDatePicker />
|
<Form.Item
|
||||||
</Form.Item>
|
label={t("scoreboard.fields.date")}
|
||||||
<Form.Item
|
name="date"
|
||||||
label={t("scoreboard.fields.bodyhrs")}
|
rules={[
|
||||||
name="bodyhrs"
|
{
|
||||||
rules={[
|
required: true,
|
||||||
{
|
//message: t("general.validation.required"),
|
||||||
required: true,
|
},
|
||||||
//message: t("general.validation.required"),
|
]}
|
||||||
},
|
>
|
||||||
]}
|
<FormDatePicker />
|
||||||
>
|
</Form.Item>
|
||||||
<InputNumber precision={1} />
|
<Form.Item
|
||||||
</Form.Item>
|
label={t("scoreboard.fields.bodyhrs")}
|
||||||
<Form.Item
|
name="bodyhrs"
|
||||||
label={t("scoreboard.fields.painthrs")}
|
rules={[
|
||||||
name="painthrs"
|
{
|
||||||
rules={[
|
required: true,
|
||||||
{
|
//message: t("general.validation.required"),
|
||||||
required: true,
|
},
|
||||||
//message: t("general.validation.required"),
|
]}
|
||||||
},
|
>
|
||||||
]}
|
<InputNumber precision={1} />
|
||||||
>
|
</Form.Item>
|
||||||
<InputNumber precision={1} />
|
<Form.Item
|
||||||
</Form.Item>
|
label={t("scoreboard.fields.painthrs")}
|
||||||
|
name="painthrs"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<InputNumber precision={1} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Button type="primary" htmlType="submit">
|
<Space wrap>
|
||||||
{t("general.actions.save")}
|
<Button type="primary" htmlType="submit">
|
||||||
</Button>
|
{t("general.actions.save")}
|
||||||
</Form>
|
</Button>
|
||||||
|
<Button onClick={() => setVisibility(false)}>
|
||||||
|
{t("general.actions.cancel")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
@@ -99,7 +150,7 @@ export default function ScoreboardAddButton({
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const v = job.joblines.reduce(
|
const v = job.joblines.reduce(
|
||||||
(acc, val) => {
|
(acc, val) => {
|
||||||
if (val.mod_lbr_ty === "LAB")
|
if (val.mod_lbr_ty !== "LAR")
|
||||||
acc = { ...acc, bodyhrs: acc.bodyhrs + val.mod_lb_hrs };
|
acc = { ...acc, bodyhrs: acc.bodyhrs + val.mod_lb_hrs };
|
||||||
if (val.mod_lbr_ty === "LAR")
|
if (val.mod_lbr_ty === "LAR")
|
||||||
acc = { ...acc, painthrs: acc.painthrs + val.mod_lb_hrs };
|
acc = { ...acc, painthrs: acc.painthrs + val.mod_lb_hrs };
|
||||||
|
|||||||
@@ -140,16 +140,17 @@ export function JobsAvailableContainer({
|
|||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (selectedOwner) {
|
||||||
|
newJob.ownerid = selectedOwner;
|
||||||
|
delete newJob.owner;
|
||||||
|
}
|
||||||
|
if (newJob.vehicleid) {
|
||||||
|
delete newJob.vehicle;
|
||||||
|
}
|
||||||
|
|
||||||
insertNewJob({
|
insertNewJob({
|
||||||
variables: {
|
variables: {
|
||||||
job: selectedOwner
|
job: newJob,
|
||||||
? Object.assign(
|
|
||||||
{},
|
|
||||||
newJob,
|
|
||||||
{ owner: null },
|
|
||||||
{ ownerid: selectedOwner }
|
|
||||||
)
|
|
||||||
: newJob,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
@@ -199,11 +200,10 @@ export function JobsAvailableContainer({
|
|||||||
message: t("jobs.errors.creating", { error: "No job data present." }),
|
message: t("jobs.errors.creating", { error: "No job data present." }),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
|
||||||
await CheckTaxRates(estData, bodyshop);
|
|
||||||
|
|
||||||
//create upsert job
|
//create upsert job
|
||||||
let supp = replaceEmpty({ ...estData.est_data });
|
let supp = replaceEmpty({ ...estData.est_data });
|
||||||
|
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||||
|
await CheckTaxRates(supp, bodyshop);
|
||||||
|
|
||||||
delete supp.owner;
|
delete supp.owner;
|
||||||
delete supp.vehicle;
|
delete supp.vehicle;
|
||||||
@@ -391,101 +391,104 @@ function replaceEmpty(someObj, replaceValue = null) {
|
|||||||
value === "" ? replaceValue || null : value;
|
value === "" ? replaceValue || null : value;
|
||||||
//^ because you seem to want to replace (strings) "null" or "undefined" too
|
//^ because you seem to want to replace (strings) "null" or "undefined" too
|
||||||
const temp = JSON.stringify(someObj, replacer);
|
const temp = JSON.stringify(someObj, replacer);
|
||||||
console.log("Parsed", JSON.parse(temp));
|
|
||||||
return JSON.parse(temp);
|
return JSON.parse(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function CheckTaxRates(estData, bodyshop) {
|
async function CheckTaxRates(estData, bodyshop) {
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: jobs-available-table.container.jsx ~ line 398 ~ estData",
|
||||||
|
estData
|
||||||
|
);
|
||||||
//LKQ Check
|
//LKQ Check
|
||||||
if (
|
if (
|
||||||
!estData.est_data.parts_tax_rates?.PAL ||
|
!estData.parts_tax_rates?.PAL ||
|
||||||
estData.est_data.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
||||||
estData.est_data.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
estData.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
||||||
) {
|
) {
|
||||||
const res = await confirmDialog(
|
const res = await confirmDialog(
|
||||||
`ImEX Online has detected that there is a missing tax rate for LKQ parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
`ImEX Online has detected that there is a missing tax rate for LKQ parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||||
);
|
);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (!estData.est_data.parts_tax_rates.PAL) {
|
if (!estData.parts_tax_rates.PAL) {
|
||||||
estData.est_data.parts_tax_rates.PAL = {
|
estData.parts_tax_rates.PAL = {
|
||||||
prt_discp: 0,
|
prt_discp: 0,
|
||||||
prt_mktyp: true,
|
prt_mktyp: true,
|
||||||
prt_mkupp: 0,
|
prt_mkupp: 0,
|
||||||
prt_type: "PAL",
|
prt_type: "PAL",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
estData.est_data.parts_tax_rates.PAL.prt_tax_rt =
|
estData.parts_tax_rates.PAL.prt_tax_rt =
|
||||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
estData.est_data.parts_tax_rates.PAL.prt_tax_in = true;
|
estData.parts_tax_rates.PAL.prt_tax_in = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//PAC Check
|
//PAC Check
|
||||||
if (
|
if (
|
||||||
!estData.est_data.parts_tax_rates?.PAC ||
|
!estData.parts_tax_rates?.PAC ||
|
||||||
estData.est_data.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
||||||
estData.est_data.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
estData.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
||||||
) {
|
) {
|
||||||
const res = await confirmDialog(
|
const res = await confirmDialog(
|
||||||
`ImEX Online has detected that there is a missing tax rate for rechromed parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
`ImEX Online has detected that there is a missing tax rate for rechromed parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||||
);
|
);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (!estData.est_data.parts_tax_rates.PAC) {
|
if (!estData.parts_tax_rates.PAC) {
|
||||||
estData.est_data.parts_tax_rates.PAC = {
|
estData.parts_tax_rates.PAC = {
|
||||||
prt_discp: 0,
|
prt_discp: 0,
|
||||||
prt_mktyp: true,
|
prt_mktyp: true,
|
||||||
prt_mkupp: 0,
|
prt_mkupp: 0,
|
||||||
prt_type: "PAC",
|
prt_type: "PAC",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
estData.est_data.parts_tax_rates.PAC.prt_tax_rt =
|
estData.parts_tax_rates.PAC.prt_tax_rt =
|
||||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
estData.est_data.parts_tax_rates.PAC.prt_tax_in = true;
|
estData.parts_tax_rates.PAC.prt_tax_in = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//PAM Check
|
//PAM Check
|
||||||
if (
|
if (
|
||||||
!estData.est_data.parts_tax_rates?.PAM ||
|
!estData.parts_tax_rates?.PAM ||
|
||||||
estData.est_data.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
||||||
estData.est_data.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
estData.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
||||||
) {
|
) {
|
||||||
const res = await confirmDialog(
|
const res = await confirmDialog(
|
||||||
`ImEX Online has detected that there is a missing tax rate for remanufactured parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
`ImEX Online has detected that there is a missing tax rate for remanufactured parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||||
);
|
);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (!estData.est_data.parts_tax_rates.PAM) {
|
if (!estData.parts_tax_rates.PAM) {
|
||||||
estData.est_data.parts_tax_rates.PAM = {
|
estData.parts_tax_rates.PAM = {
|
||||||
prt_discp: 0,
|
prt_discp: 0,
|
||||||
prt_mktyp: true,
|
prt_mktyp: true,
|
||||||
prt_mkupp: 0,
|
prt_mkupp: 0,
|
||||||
prt_type: "PAM",
|
prt_type: "PAM",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
estData.est_data.parts_tax_rates.PAM.prt_tax_rt =
|
estData.parts_tax_rates.PAM.prt_tax_rt =
|
||||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
estData.est_data.parts_tax_rates.PAM.prt_tax_in = true;
|
estData.parts_tax_rates.PAM.prt_tax_in = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!estData.est_data.parts_tax_rates?.PAR ||
|
!estData.parts_tax_rates?.PAR ||
|
||||||
estData.est_data.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
||||||
estData.est_data.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
estData.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
||||||
) {
|
) {
|
||||||
const res = await confirmDialog(
|
const res = await confirmDialog(
|
||||||
`ImEX Online has detected that there is a missing tax rate for recored parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
`ImEX Online has detected that there is a missing tax rate for recored parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||||
);
|
);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (!estData.est_data.parts_tax_rates.PAR) {
|
if (!estData.parts_tax_rates.PAR) {
|
||||||
estData.est_data.parts_tax_rates.PAR = {
|
estData.parts_tax_rates.PAR = {
|
||||||
prt_discp: 0,
|
prt_discp: 0,
|
||||||
prt_mktyp: true,
|
prt_mktyp: true,
|
||||||
prt_mkupp: 0,
|
prt_mkupp: 0,
|
||||||
prt_type: "PAR",
|
prt_type: "PAR",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
estData.est_data.parts_tax_rates.PAR.prt_tax_rt =
|
estData.parts_tax_rates.PAR.prt_tax_rt =
|
||||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
estData.est_data.parts_tax_rates.PAR.prt_tax_in = true;
|
estData.parts_tax_rates.PAR.prt_tax_in = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
|
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
|
||||||
|
const graphProps = {
|
||||||
|
strokeWidth: 3,
|
||||||
|
};
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
@@ -51,7 +56,7 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const theValue = {
|
const theValue = {
|
||||||
date: moment(val).format("D dd"),
|
date: moment(val).format("D ddd"),
|
||||||
paintHrs: _.round(dayhrs.painthrs, 1),
|
paintHrs: _.round(dayhrs.painthrs, 1),
|
||||||
bodyHrs: _.round(dayhrs.bodyhrs, 1),
|
bodyHrs: _.round(dayhrs.bodyhrs, 1),
|
||||||
accTargetHrs: _.round(
|
accTargetHrs: _.round(
|
||||||
@@ -81,36 +86,37 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
|
|||||||
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
|
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
|
||||||
>
|
>
|
||||||
<CartesianGrid stroke="#f5f5f5" />
|
<CartesianGrid stroke="#f5f5f5" />
|
||||||
<XAxis dataKey="date" />
|
<XAxis dataKey="date" strokeWidth={graphProps.strokeWidth} />
|
||||||
<YAxis />
|
<YAxis strokeWidth={graphProps.strokeWidth} />
|
||||||
<Tooltip />
|
<Tooltip />
|
||||||
<Legend />
|
<Legend />
|
||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
name="Accumulated Hours"
|
name="Accumulated Hours"
|
||||||
dataKey="accHrs"
|
dataKey="accHrs"
|
||||||
fill="#8884d8"
|
fill="lightgreen"
|
||||||
stroke="#8884d8"
|
stroke="green"
|
||||||
/>
|
/>
|
||||||
<Bar
|
<Bar
|
||||||
name="Body Hours"
|
name="Body Hours"
|
||||||
dataKey="bodyHrs"
|
dataKey="bodyHrs"
|
||||||
stackId="day"
|
stackId="day"
|
||||||
barSize={20}
|
barSize={20}
|
||||||
fill="#cecece"
|
fill="darkblue"
|
||||||
/>
|
/>
|
||||||
<Bar
|
<Bar
|
||||||
name="Paint Hours"
|
name="Paint Hours"
|
||||||
dataKey="paintHrs"
|
dataKey="paintHrs"
|
||||||
stackId="day"
|
stackId="day"
|
||||||
barSize={20}
|
barSize={20}
|
||||||
fill="#413ea0"
|
fill="darkred"
|
||||||
/>
|
/>
|
||||||
<Line
|
<Line
|
||||||
name="Target Hours"
|
name="Target Hours"
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="accTargetHrs"
|
dataKey="accTargetHrs"
|
||||||
stroke="#ff7300"
|
stroke="#ff7300"
|
||||||
|
strokeWidth={graphProps.strokeWidth}
|
||||||
/>
|
/>
|
||||||
</ComposedChart>
|
</ComposedChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
|
|||||||
@@ -1,12 +1,33 @@
|
|||||||
import { Col, Row } from "antd";
|
import { Col, Row } from "antd";
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import ScoreboardChart from "../scoreboard-chart/scoreboard-chart.component";
|
import ScoreboardChart from "../scoreboard-chart/scoreboard-chart.component";
|
||||||
import ScoreboardLastDays from "../scoreboard-last-days/scoreboard-last-days.component";
|
import ScoreboardLastDays from "../scoreboard-last-days/scoreboard-last-days.component";
|
||||||
import ScoreboardTargetsTable from "../scoreboard-targets-table/scoreboard-targets-table.component";
|
import ScoreboardTargetsTable from "../scoreboard-targets-table/scoreboard-targets-table.component";
|
||||||
|
|
||||||
export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
|
import { connect } from "react-redux";
|
||||||
const { data } = scoreboardSubscription;
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import moment from "moment";
|
||||||
|
import { useApolloClient } from "@apollo/client";
|
||||||
|
import { GET_BLOCKED_DAYS } from "../../graphql/scoreboard.queries";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
//currentUser: selectCurrentUser
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ScoreboardDisplayComponent);
|
||||||
|
|
||||||
|
export function ScoreboardDisplayComponent({
|
||||||
|
bodyshop,
|
||||||
|
scoreboardSubscription,
|
||||||
|
}) {
|
||||||
|
const { data } = scoreboardSubscription;
|
||||||
|
const client = useApolloClient();
|
||||||
const scoreBoardlist = (data && data.scoreboard) || [];
|
const scoreBoardlist = (data && data.scoreboard) || [];
|
||||||
|
|
||||||
const sbEntriesByDate = {};
|
const sbEntriesByDate = {};
|
||||||
@@ -19,6 +40,29 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
|
|||||||
sbEntriesByDate[entryDate].push(i);
|
sbEntriesByDate[entryDate].push(i);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//Update the locals.
|
||||||
|
async function setMomentSettings() {
|
||||||
|
const {
|
||||||
|
data: { appointments },
|
||||||
|
} = await client.query({
|
||||||
|
query: GET_BLOCKED_DAYS,
|
||||||
|
variables: {
|
||||||
|
start: moment().startOf("month"),
|
||||||
|
end: moment().endOf("month"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
moment.updateLocale("ca", {
|
||||||
|
workingWeekdays: translateSettingsToWorkingDays(bodyshop.workingdays),
|
||||||
|
holidays: appointments.map((h) => moment(h.start).format("MM-DD-YYYY")),
|
||||||
|
holidayFormat: "MM-DD-YYYY",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setMomentSettings();
|
||||||
|
}, [client, bodyshop]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
@@ -35,3 +79,30 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
|
|||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function translateSettingsToWorkingDays(workingdays) {
|
||||||
|
const days = [];
|
||||||
|
|
||||||
|
if (workingdays.monday) {
|
||||||
|
days.push(1);
|
||||||
|
}
|
||||||
|
if (workingdays.tuesday) {
|
||||||
|
days.push(2);
|
||||||
|
}
|
||||||
|
if (workingdays.wednesday) {
|
||||||
|
days.push(3);
|
||||||
|
}
|
||||||
|
if (workingdays.thursday) {
|
||||||
|
days.push(4);
|
||||||
|
}
|
||||||
|
if (workingdays.friday) {
|
||||||
|
days.push(5);
|
||||||
|
}
|
||||||
|
if (workingdays.saturday) {
|
||||||
|
days.push(6);
|
||||||
|
}
|
||||||
|
if (workingdays.sunday) {
|
||||||
|
days.push(0);
|
||||||
|
}
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import moment from "moment-business-days";
|
import moment from "moment-business-days";
|
||||||
|
|
||||||
moment.updateLocale("ca", {
|
// moment.updateLocale("ca", {
|
||||||
workingWeekdays: [1, 2, 3, 4, 5],
|
// workingWeekdays: [1, 2, 3, 4, 5, 6],
|
||||||
});
|
// });
|
||||||
|
|
||||||
export const CalculateWorkingDaysThisMonth = () => {
|
export const CalculateWorkingDaysThisMonth = () => {
|
||||||
return moment().endOf("month").businessDaysIntoMonth();
|
return moment().endOf("month").businessDaysIntoMonth();
|
||||||
|
|||||||
@@ -51,3 +51,34 @@ export const UPDATE_SCOREBOARD_ENTRY = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const QUERY_SCOREBOARD_ENTRY = gql`
|
||||||
|
query QUERY_SCOREBOARD_ENTRY($jobid: uuid!) {
|
||||||
|
scoreboard(where: { jobid: { _eq: $jobid } }) {
|
||||||
|
bodyhrs
|
||||||
|
date
|
||||||
|
id
|
||||||
|
painthrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET_BLOCKED_DAYS = gql`
|
||||||
|
query GET_BLOCKED_DAYS($start: timestamptz, $end: timestamptz) {
|
||||||
|
appointments(
|
||||||
|
where: {
|
||||||
|
_and: [
|
||||||
|
{ block: { _eq: true } }
|
||||||
|
{ canceled: { _eq: false } }
|
||||||
|
{ start: { _gte: $start } }
|
||||||
|
{ end: { _lte: $end } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
block
|
||||||
|
start
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user