Merged in feature/IO-2857-Tech-Job-Drawer-PartsOrderDrawer-Component (pull request #1557)

Feature/IO-2857 Tech Job Drawer PartsOrderDrawer Component
This commit is contained in:
Allan Carr
2024-08-01 21:58:49 +00:00
6 changed files with 54 additions and 28 deletions

View File

@@ -7,6 +7,7 @@ import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries"; import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries";
import { QUERY_JOBLINE_TASKS_PAGINATED } from "../../graphql/tasks.queries.js"; import { QUERY_JOBLINE_TASKS_PAGINATED } from "../../graphql/tasks.queries.js";
import { selectTechnician } from "../../redux/tech/tech.selectors.js";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter"; import { DateFormatter } from "../../utils/DateFormatter";
@@ -16,14 +17,15 @@ import FeatureWrapper from "../feature-wrapper/feature-wrapper.component.jsx";
import TaskListContainer from "../task-list/task-list.container.jsx"; import TaskListContainer from "../task-list/task-list.container.jsx";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop,
technician: selectTechnician
}); });
const mapDispatchToProps = (dispatch) => ({}); const mapDispatchToProps = (dispatch) => ({});
export default connect(mapStateToProps, mapDispatchToProps)(JobLinesExpander); export default connect(mapStateToProps, mapDispatchToProps)(JobLinesExpander);
export function JobLinesExpander({ jobline, jobid, bodyshop }) { export function JobLinesExpander({ jobline, jobid, bodyshop, technician }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, { const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
@@ -48,9 +50,15 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) {
children: ( children: (
<Row wrap> <Row wrap>
<Col span={4}> <Col span={4}>
<Link to={`/manage/jobs/${jobid}?partsorderid=${line.parts_order.id}`}> {!technician ? (
{line.parts_order.order_number} <>
</Link> <Link to={`/manage/jobs/${jobid}?partsorderid=${line.parts_order.id}`}>
{line.parts_order.order_number}
</Link>
</>
) : (
`${line.parts_order.order_number}`
)}
</Col> </Col>
<Col span={4}> <Col span={4}>
<DateFormatter>{line.parts_order.order_date}</DateFormatter> <DateFormatter>{line.parts_order.order_date}</DateFormatter>
@@ -121,9 +129,15 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) {
children: ( children: (
<Row wrap> <Row wrap>
<Col span={4}> <Col span={4}>
<Link to={`/manage/jobs/${jobid}?tab=partssublet&billid=${line.bill.id}`}> {!technician ? (
{line.bill.invoice_number} <>
</Link> <Link to={`/manage/jobs/${jobid}?tab=partssublet&billid=${line.bill.id}`}>
{line.bill.invoice_number}
</Link>
</>
) : (
`${line.bill.invoice_number}`
)}
</Col> </Col>
<Col span={4}> <Col span={4}>
<span> <span>

View File

@@ -3,13 +3,21 @@ import { Button, Form, notification, Popover, Tooltip } from "antd";
import axios from "axios"; import axios from "axios";
import { t } from "i18next"; import { t } from "i18next";
import React, { useState } from "react"; import React, { useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { UPDATE_LINE_PPC } from "../../graphql/jobs-lines.queries"; import { UPDATE_LINE_PPC } from "../../graphql/jobs-lines.queries";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
import InstanceRenderManager from "../../utils/instanceRenderMgr"; import InstanceRenderManager from "../../utils/instanceRenderMgr";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component"; import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component"; import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component";
export default function JobLinesPartPriceChange({ job, line, refetch }) { const mapStateToProps = createStructuredSelector({
technician: selectTechnician
});
const mapDispatchToProps = (dispatch) => ({});
export function JobLinesPartPriceChange({ job, line, refetch, technician }) {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [updatePartPrice] = useMutation(UPDATE_LINE_PPC); const [updatePartPrice] = useMutation(UPDATE_LINE_PPC);
@@ -52,7 +60,7 @@ export default function JobLinesPartPriceChange({ job, line, refetch }) {
} }
}; };
const popcontent = InstanceRenderManager({ const popcontent = !technician && InstanceRenderManager({
imex: null, imex: null,
rome: ( rome: (
<Form layout="vertical" onFinish={handleFinish} initialValues={{ act_price: line.act_price }}> <Form layout="vertical" onFinish={handleFinish} initialValues={{ act_price: line.act_price }}>
@@ -95,3 +103,4 @@ export default function JobLinesPartPriceChange({ job, line, refetch }) {
</JobLineConvertToLabor> </JobLineConvertToLabor>
); );
} }
export default connect(mapStateToProps, mapDispatchToProps)(JobLinesPartPriceChange);

View File

@@ -205,7 +205,6 @@ export function JobLinesComponent({
onFilter: (value, record) => value.includes(record.part_type), onFilter: (value, record) => value.includes(record.part_type),
render: (text, record) => (record.part_type ? t(`joblines.fields.part_types.${record.part_type}`) : null) render: (text, record) => (record.part_type ? t(`joblines.fields.part_types.${record.part_type}`) : null)
}, },
{ {
title: t("joblines.fields.act_price"), title: t("joblines.fields.act_price"),
dataIndex: "act_price", dataIndex: "act_price",
@@ -220,7 +219,6 @@ export function JobLinesComponent({
dataIndex: "part_qty", dataIndex: "part_qty",
key: "part_qty" key: "part_qty"
}, },
// { // {
// title: t('joblines.fields.tax_part'), // title: t('joblines.fields.tax_part'),
// dataIndex: 'tax_part', // dataIndex: 'tax_part',
@@ -329,7 +327,7 @@ export function JobLinesComponent({
key: "actions", key: "actions",
render: (text, record) => ( render: (text, record) => (
<Space> <Space>
{(record.manual_line || jobIsPrivate) && ( {(record.manual_line || jobIsPrivate) && !technician && (
<> <>
<Button <Button
disabled={jobRO} disabled={jobRO}
@@ -344,7 +342,6 @@ export function JobLinesComponent({
</Button> </Button>
</> </>
)} )}
<Button <Button
title={t("tasks.buttons.create")} title={t("tasks.buttons.create")}
onClick={() => { onClick={() => {
@@ -358,7 +355,7 @@ export function JobLinesComponent({
> >
<FaTasks /> <FaTasks />
</Button> </Button>
{(record.manual_line || jobIsPrivate) && ( {(record.manual_line || jobIsPrivate) && !technician && (
<> <>
<Button <Button
disabled={jobRO} disabled={jobRO}
@@ -444,13 +441,15 @@ export function JobLinesComponent({
return ( return (
<div> <div>
<PartsOrderModalContainer /> <PartsOrderModalContainer />
<PartsOrderDrawer {!technician && (
job={job} <PartsOrderDrawer
billsQuery={billsQuery} job={job}
handleOnRowClick={handlePartsOrderOnRowClick} billsQuery={billsQuery}
setPartsReceiveContext={setPartsReceiveContext} handleOnRowClick={handlePartsOrderOnRowClick}
setTaskUpsertContext={setTaskUpsertContext} setPartsReceiveContext={setPartsReceiveContext}
/> setTaskUpsertContext={setTaskUpsertContext}
/>
)}
<PageHeader <PageHeader
title={t("jobs.labels.estimatelines")} title={t("jobs.labels.estimatelines")}
extra={ extra={
@@ -567,7 +566,7 @@ export function JobLinesComponent({
> >
{t("joblines.actions.new")} {t("joblines.actions.new")}
</Button> </Button>
{InstanceRenderManager({ rome: <JobSendPartPriceChangeComponent job={job} /> })} {InstanceRenderManager({ rome: <JobSendPartPriceChangeComponent job={job} disabled={technician} /> })}
<JobCreateIOU job={job} selectedJobLines={selectedLines} /> <JobCreateIOU job={job} selectedJobLines={selectedLines} />
<Input.Search <Input.Search
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}

View File

@@ -11,17 +11,18 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries"; import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
import { insertAuditTrail } from "../../redux/application/application.actions"; import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings"; import AuditTrailMapping from "../../utils/AuditTrailMappings";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser technician: selectTechnician
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type })) insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
}); });
export default connect(mapStateToProps, mapDispatchToProps)(JobLineConvertToLabor); export default connect(mapStateToProps, mapDispatchToProps)(JobLineConvertToLabor);
export function JobLineConvertToLabor({ children, jobline, job, insertAuditTrail, ...otherBtnProps }) { export function JobLineConvertToLabor({ children, jobline, job, insertAuditTrail, technician, ...otherBtnProps }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -165,7 +166,7 @@ export function JobLineConvertToLabor({ children, jobline, job, insertAuditTrail
return ( return (
<> <>
{children} {children}
{jobline.act_price !== 0 && ( {jobline.act_price !== 0 && !technician && (
<Popover disabled={jobline.convertedtolbr} content={overlay} open={visibility} placement="bottom"> <Popover disabled={jobline.convertedtolbr} content={overlay} open={visibility} placement="bottom">
<Tooltip title={t("joblines.actions.converttolabor")}> <Tooltip title={t("joblines.actions.converttolabor")}>
<Button <Button

View File

@@ -3,7 +3,7 @@ import axios from "axios";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function JobSendPartPriceChangeComponent({ job }) { export default function JobSendPartPriceChangeComponent({ job, disabled }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const handleClick = async () => { const handleClick = async () => {
@@ -24,7 +24,7 @@ export default function JobSendPartPriceChangeComponent({ job }) {
}; };
return ( return (
<Button onClick={handleClick} loading={loading}> <Button onClick={handleClick} loading={loading} disabled={disabled}>
{t("jobs.actions.sendpartspricechange")} {t("jobs.actions.sendpartspricechange")}
</Button> </Button>
); );

View File

@@ -33,6 +33,8 @@ const TimeTicketModalTask = lazy(
const TechAssignedProdJobs = lazy(() => import("../tech-assigned-prod-jobs/tech-assigned-prod-jobs.component")); const TechAssignedProdJobs = lazy(() => import("../tech-assigned-prod-jobs/tech-assigned-prod-jobs.component"));
const TechDispatchedParts = lazy(() => import("../tech-dispatched-parts/tech-dispatched-parts.page")); const TechDispatchedParts = lazy(() => import("../tech-dispatched-parts/tech-dispatched-parts.page"));
const TaskUpsertModalContainer = lazy(() => import("../../components/task-upsert-modal/task-upsert-modal.container"));
const { Content } = Layout; const { Content } = Layout;
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
@@ -67,6 +69,7 @@ export function TechPage({ technician }) {
<UpdateAlert /> <UpdateAlert />
<TechHeader /> <TechHeader />
<TechLookupJobsDrawer /> <TechLookupJobsDrawer />
<TaskUpsertModalContainer />
<Content className="tech-content-container"> <Content className="tech-content-container">
<ErrorBoundary> <ErrorBoundary>
<Suspense <Suspense