Files
bodyshop/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.component.jsx

193 lines
6.2 KiB
JavaScript

import { BarsOutlined, PrinterFilled, SyncOutlined, ToolFilled } from "@ant-design/icons";
import { PageHeader } from "@ant-design/pro-layout";
import { useQuery } from "@apollo/client/react";
import { Button, Divider, Form, Space, Tabs } from "antd";
import queryString from "query-string";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import FormFieldsChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component.jsx";
import JobsLinesContainer from "../../components/job-detail-lines/job-lines.container.jsx";
import JobLineUpsertModalContainer from "../../components/job-lines-upsert-modal/job-lines-upsert-modal.container.jsx";
import JobsChangeStatus from "../../components/jobs-change-status/jobs-change-status.component.jsx";
import JobsDetailHeaderActions from "../../components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx";
import JobsDetailHeader from "../../components/jobs-detail-header/jobs-detail-header.component.jsx";
import JobsDetailPliContainer from "../../components/jobs-detail-pli/jobs-detail-pli.container.jsx";
import { QUERY_PARTS_BILLS_BY_JOBID } from "../../graphql/bills.queries.js";
import { selectIsPartsEntry, selectJobReadOnly } from "../../redux/application/application.selectors.js";
import { setModalContext } from "../../redux/modals/modals.actions.js";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
isPartsEntry: selectIsPartsEntry
});
const mapDispatchToProps = (dispatch) => ({
setPrintCenterContext: (context) =>
dispatch(
setModalContext({
context: context,
modal: "printCenter"
})
)
});
export function SimplifiedPartsJobDetailComponent({ setPrintCenterContext, jobRO, job, refetch, isPartsEntry }) {
const { t } = useTranslation();
const [form] = Form.useForm();
const navigate = useNavigate();
const location = useLocation();
const [loading] = useState(false);
// Parse once per render; do not mutate this object.
const search = queryString.parse(location.search);
const billsQuery = useQuery(QUERY_PARTS_BILLS_BY_JOBID, {
variables: { jobid: job.id },
fetchPolicy: "network-only",
nextFetchPolicy: "network-only"
});
useEffect(() => {
form.resetFields();
}, [form, job]);
const navigateWithSearch = (nextSearchObj) => {
navigate({ search: queryString.stringify(nextSearchObj) });
};
const omitKey = (obj, key) => {
if (!obj) return {};
// immutable omit
// eslint-disable-next-line no-unused-vars
const { [key]: _omit, ...rest } = obj;
return rest;
};
const handleBillOnRowClick = (record) => {
if (record?.id) {
navigateWithSearch({ ...search, billid: record.id });
return;
}
navigateWithSearch(omitKey(search, "billid"));
};
const handlePartsOrderOnRowClick = (record) => {
if (record?.id) {
navigateWithSearch({ ...search, partsorderid: record.id });
return;
}
navigateWithSearch(omitKey(search, "partsorderid"));
};
const handlePartsDispatchOnRowClick = (record) => {
if (record?.id) {
navigateWithSearch({ ...search, partsdispatchid: record.id });
return;
}
navigateWithSearch(omitKey(search, "partsdispatchid"));
};
const menuExtra = (
<Space wrap>
<Button
onClick={() => {
refetch();
}}
key="refresh"
>
<SyncOutlined />
{t("general.labels.refresh")}
</Button>
<JobsChangeStatus job={job} />
<Button
onClick={() => {
setPrintCenterContext({
actions: { refetch: refetch },
context: {
id: job.id,
job: job,
type: "job"
}
});
}}
key="printing"
>
<PrinterFilled />
{t("jobs.actions.printCenter")}
</Button>
{!isPartsEntry && (
<>
<JobsDetailHeaderActions key="actions" job={job} refetch={refetch} />
<Button type="primary" loading={loading} disabled={jobRO} onClick={() => form.submit()}>
{t("general.actions.save")}
</Button>
</>
)}
</Space>
);
const activeTabKey = (search?.tab && String(search.tab)) || "repairdata";
return (
<div>
<JobLineUpsertModalContainer />
<PageHeader title={<Space>{job.ro_number || t("general.labels.na")}</Space>} extra={menuExtra} />
<JobsDetailHeader job={job} />
<Divider orientation="horizontal" />
<FormFieldsChanged form={form} />
<Tabs
defaultActiveKey={activeTabKey}
onChange={(key) => navigateWithSearch({ ...search, tab: key })}
tabBarStyle={{ fontWeight: "bold", borderBottom: "10px" }}
items={[
{
key: "repairdata",
icon: <BarsOutlined />,
id: "job-details-repairdata",
label: t("menus.jobsdetail.repairdata"),
forceRender: true,
children: (
<JobsLinesContainer
job={job}
joblines={job.joblines}
billsQuery={billsQuery}
handleBillOnRowClick={handleBillOnRowClick}
handlePartsOrderOnRowClick={handlePartsOrderOnRowClick}
handlePartsDispatchOnRowClick={handlePartsDispatchOnRowClick}
refetch={refetch}
form={form}
/>
)
},
{
key: "partssublet",
id: "job-details-partssublet",
icon: <ToolFilled />,
label: t("menus.jobsdetail.partssublet"),
children: (
<JobsDetailPliContainer
job={job}
billsQuery={billsQuery}
handleBillOnRowClick={handleBillOnRowClick}
handlePartsOrderOnRowClick={handlePartsOrderOnRowClick}
handlePartsDispatchOnRowClick={handlePartsDispatchOnRowClick}
/>
)
}
]}
/>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(SimplifiedPartsJobDetailComponent);