312 lines
11 KiB
JavaScript
312 lines
11 KiB
JavaScript
import { useLazyQuery, useMutation } from "@apollo/client/react";
|
|
import { Form } from "antd";
|
|
import _ from "lodash";
|
|
import { useEffect, useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { connect } from "react-redux";
|
|
import { createStructuredSelector } from "reselect";
|
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
|
import { INSERT_NEW_JOB } from "../../graphql/jobs.queries";
|
|
import { QUERY_OWNER_FOR_JOB_CREATION } from "../../graphql/owners.queries";
|
|
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
|
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
|
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
|
import JobsCreateComponent from "./jobs-create.component";
|
|
import JobCreateContext from "./jobs-create.context";
|
|
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
|
|
const mapStateToProps = createStructuredSelector({
|
|
bodyshop: selectBodyshop,
|
|
currentUser: selectCurrentUser
|
|
});
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
|
setSelectedHeader: (key) => dispatch(setSelectedHeader(key))
|
|
});
|
|
|
|
function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, currentUser }) {
|
|
const { t } = useTranslation();
|
|
const notification = useNotification();
|
|
|
|
const contextState = useState({
|
|
vehicle: {
|
|
new: false,
|
|
search: "",
|
|
selectedid: null,
|
|
vehicleObj: null,
|
|
none: false
|
|
},
|
|
owner: { new: false, search: "", selectedid: null },
|
|
job: null,
|
|
created: false,
|
|
error: null,
|
|
newJobId: null,
|
|
newJobEstNum: null
|
|
});
|
|
const [form] = Form.useForm();
|
|
const [state, setState] = contextState;
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [insertJob] = useMutation(INSERT_NEW_JOB);
|
|
const [loadOwner, remoteOwnerData] = useLazyQuery(QUERY_OWNER_FOR_JOB_CREATION);
|
|
|
|
useEffect(() => {
|
|
if (state.owner.selectedid) {
|
|
loadOwner({ variables: { id: state.owner.selectedid } });
|
|
}
|
|
}, [state.owner.selectedid, loadOwner]);
|
|
|
|
useEffect(() => {
|
|
document.title = t("titles.jobs-create", {
|
|
app: InstanceRenderManager({
|
|
imex: "$t(titles.imexonline)",
|
|
rome: "$t(titles.romeonline)"
|
|
})
|
|
});
|
|
setSelectedHeader("newjob");
|
|
setBreadcrumbs([
|
|
{ link: "/manage/available", label: t("titles.bc.availablejobs") },
|
|
{
|
|
link: "/manage/jobs/new",
|
|
label: t("titles.bc.jobs-new")
|
|
}
|
|
]);
|
|
logImEXEvent("manual_job_create_start", {});
|
|
}, [t, setBreadcrumbs, setSelectedHeader]);
|
|
|
|
const runInsertJob = (job) => {
|
|
insertJob({ variables: { job } })
|
|
.then((resp) => {
|
|
setState({
|
|
...state,
|
|
created: true,
|
|
error: null,
|
|
newJobId: resp.data.insert_jobs.returning[0].id
|
|
});
|
|
logImEXEvent("manual_job_create_completed", {});
|
|
setIsSubmitting(false);
|
|
})
|
|
.catch((error) => {
|
|
notification.error({
|
|
title: t("jobs.errors.creating", { error: error })
|
|
});
|
|
setState({ ...state, error: error });
|
|
setIsSubmitting(false);
|
|
});
|
|
};
|
|
|
|
const handleFinish = (values) => {
|
|
setIsSubmitting(true);
|
|
let job = Object.assign(
|
|
{},
|
|
values,
|
|
{ date_open: new Date() },
|
|
{ date_estimated: new Date() },
|
|
{
|
|
vehicle: state.vehicle.selectedid || state.vehicle.none ? null : values.vehicle,
|
|
vehicleid: state.vehicle.selectedid || null
|
|
},
|
|
{
|
|
owner: state.owner.selectedid ? null : values.owner,
|
|
ownerid: state.owner.selectedid || null
|
|
},
|
|
{
|
|
status: bodyshop.md_ro_statuses.default_imported || "Open*",
|
|
shopid: bodyshop.id
|
|
}
|
|
);
|
|
|
|
let ownerData;
|
|
if (!job.ownerid) {
|
|
// Keep preferred_contact for the nested owner insert...
|
|
job.owner.data.shopid = bodyshop.id;
|
|
|
|
// ...but do NOT flatten preferred_contact into the job row.
|
|
ownerData = _.cloneDeep(job.owner.data);
|
|
delete ownerData.preferred_contact;
|
|
|
|
delete job.ownerid;
|
|
} else {
|
|
ownerData = _.cloneDeep(remoteOwnerData.data.owners_by_pk);
|
|
delete ownerData.id;
|
|
delete ownerData.__typename;
|
|
}
|
|
|
|
if (!state.vehicle.none) {
|
|
if (!job.vehicleid) {
|
|
delete job.vehicleid;
|
|
job.vehicle.data.shopid = bodyshop.id;
|
|
job.plate_no = job.vehicle.data.plate_no;
|
|
job.plate_st = job.vehicle.data.plate_st;
|
|
job.v_vin = job.vehicle.data.v_vin;
|
|
job.v_model_yr = job.vehicle.data.v_model_yr;
|
|
job.v_model_desc = job.vehicle.data.v_model_desc;
|
|
job.v_make_desc = job.vehicle.data.v_make_desc;
|
|
job.v_color = job.vehicle.data.v_color;
|
|
} else {
|
|
job.plate_no = state.vehicle.vehicleObj.plate_no;
|
|
job.plate_st = state.vehicle.vehicleObj.plate_st;
|
|
job.v_vin = state.vehicle.vehicleObj.v_vin;
|
|
job.v_model_yr = state.vehicle.vehicleObj.v_model_yr;
|
|
job.v_model_desc = state.vehicle.vehicleObj.v_model_desc;
|
|
job.v_make_desc = state.vehicle.vehicleObj.v_make_desc;
|
|
job.v_color = state.vehicle.vehicleObj.v_color;
|
|
}
|
|
}
|
|
|
|
job = { ...job, ...ownerData };
|
|
|
|
if (job.owner === null) delete job.owner;
|
|
if (job.vehicle === null) delete job.vehicle;
|
|
|
|
// Associate to the current user if one exists
|
|
if (currentUser?.email) {
|
|
job.created_user_email = currentUser.email;
|
|
}
|
|
|
|
runInsertJob(job);
|
|
};
|
|
|
|
return (
|
|
<JobCreateContext.Provider value={contextState}>
|
|
<RbacWrapper action="jobs:create">
|
|
<Form
|
|
form={form}
|
|
onFinish={handleFinish}
|
|
layout="vertical"
|
|
autoComplete={"off"}
|
|
initialValues={{
|
|
federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate / 100,
|
|
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate / 100,
|
|
...InstanceRenderManager({
|
|
imex: {
|
|
parts_tax_rates: {
|
|
PAA: {
|
|
prt_type: "PAA",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAC: {
|
|
prt_type: "PAC",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAG: {
|
|
prt_type: "PAG",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAL: {
|
|
prt_type: "PAL",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAM: {
|
|
prt_type: "PAM",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAN: {
|
|
prt_type: "PAN",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAR: {
|
|
prt_type: "PAR",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAS: {
|
|
prt_type: "PAS",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PASL: {
|
|
prt_type: "PASL",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAP: {
|
|
prt_type: "PAP",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
PAO: {
|
|
prt_type: "PAO",
|
|
prt_discp: 0,
|
|
prt_mktyp: false,
|
|
prt_mkupp: 0,
|
|
prt_tax_in: true,
|
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
}
|
|
},
|
|
tax_tow_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
tax_str_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
tax_paint_mat_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
tax_shop_mat_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
tax_sub_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
tax_lbr_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
|
tax_levies_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
|
},
|
|
rome: {
|
|
cieca_pft: {
|
|
...bodyshop.md_responsibility_centers.taxes.tax_ty1,
|
|
...bodyshop.md_responsibility_centers.taxes.tax_ty2,
|
|
...bodyshop.md_responsibility_centers.taxes.tax_ty3,
|
|
...bodyshop.md_responsibility_centers.taxes.tax_ty4,
|
|
...bodyshop.md_responsibility_centers.taxes.tax_ty5
|
|
},
|
|
materials: bodyshop.md_responsibility_centers.cieca_pfm,
|
|
cieca_pfl: bodyshop.md_responsibility_centers.cieca_pfl,
|
|
parts_tax_rates: bodyshop.md_responsibility_centers.parts_tax_rates,
|
|
tax_tow_rt: bodyshop.md_responsibility_centers.tax_tow_rt,
|
|
tax_str_rt: bodyshop.md_responsibility_centers.tax_str_rt,
|
|
tax_paint_mat_rt: bodyshop.md_responsibility_centers.tax_paint_mat_rt,
|
|
tax_shop_mat_rt: bodyshop.md_responsibility_centers.tax_shop_mat_rt,
|
|
tax_sub_rt: bodyshop.md_responsibility_centers.tax_sub_rt,
|
|
tax_lbr_rt: bodyshop.md_responsibility_centers.tax_lbr_rt,
|
|
tax_levies_rt: bodyshop.md_responsibility_centers.tax_levies_rt
|
|
}
|
|
})
|
|
}}
|
|
>
|
|
<JobsCreateComponent form={form} isSubmitting={isSubmitting} />
|
|
</Form>
|
|
</RbacWrapper>
|
|
</JobCreateContext.Provider>
|
|
);
|
|
}
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(JobsCreateContainer);
|