feature/IO-3214-Job-Status-Card-Extension - Complete
This commit is contained in:
@@ -106,7 +106,12 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
|
||||
<Form.Item label={t("jobs.fields.date_open")} name="date_open">
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={t("jobs.fields.estimate_sent_approval")} name="estimate_sent_approval">
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.estimate_approved")} name="estimate_approved">
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.date_scheduled")} name="date_scheduled">
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { selectJobReadOnly } from "../../redux/application/application.selectors
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||
import dayjs from "../../utils/day";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
@@ -40,6 +41,20 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
||||
<Form.Item label={t("jobs.fields.date_rentalresp")} name="date_rentalresp">
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.estimate_sent_approval")} name="estimate_sent_approval">
|
||||
<DateTimePicker
|
||||
disabled={true}
|
||||
value={job.estimate_sent_approval ? dayjs(job.estimate_sent_approval) : null}
|
||||
placeholder={t("general.labels.na")}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.estimate_approved")} name="estimate_approved">
|
||||
<DateTimePicker
|
||||
disabled={true}
|
||||
value={job.estimate_approved ? dayjs(job.estimate_approved) : null}
|
||||
placeholder={t("general.labels.na")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
|
||||
<FormRow header={t("jobs.forms.scheddates")}>
|
||||
@@ -76,21 +91,15 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate>
|
||||
{() => {
|
||||
return (
|
||||
<Form.Item
|
||||
label={t("jobs.fields.actual_completion")}
|
||||
name="actual_completion"
|
||||
rules={[
|
||||
{
|
||||
required: jobInPostProduction
|
||||
}
|
||||
]}
|
||||
>
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
);
|
||||
}}
|
||||
{() => (
|
||||
<Form.Item
|
||||
label={t("jobs.fields.actual_completion")}
|
||||
name="actual_completion"
|
||||
rules={[{ required: jobInPostProduction }]}
|
||||
>
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.scheduled_delivery")} name="scheduled_delivery">
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
@@ -103,15 +112,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
||||
<Form.Item label={t("jobs.fields.date_invoiced")} name="date_invoiced">
|
||||
<DateTimePicker disabled={true || jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={t("jobs.fields.date_exported")} name="date_exported">
|
||||
<DateTimePicker disabled={true || jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={t("jobs.fields.date_void")} name="date_void">
|
||||
<DateTimePicker disabled={true || jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={t("jobs.fields.date_lost_sale")} name="date_lost_sale">
|
||||
<DateTimePicker disabled={true || jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, WarningFilled } from "@ant-design/icons";
|
||||
import { Card, Col, Divider, Row, Space, Tag, Tooltip } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { Card, Checkbox, Col, Divider, Row, Space, Tag, Tooltip } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import dayjs from "../../utils/day";
|
||||
@@ -22,6 +24,7 @@ import ProductionListColumnComment from "../production-list-columns/production-l
|
||||
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
||||
import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component";
|
||||
import "./jobs-detail-header.styles.scss";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
@@ -29,41 +32,55 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" }))
|
||||
setPrintCenterContext: (context) =>
|
||||
dispatch(
|
||||
setModalContext({
|
||||
context: context,
|
||||
modal: "printCenter"
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
const colSpan = {
|
||||
xs: {
|
||||
span: 24
|
||||
},
|
||||
sm: {
|
||||
span: 24
|
||||
},
|
||||
md: {
|
||||
span: 12
|
||||
},
|
||||
lg: {
|
||||
span: 6
|
||||
},
|
||||
xl: {
|
||||
span: 6
|
||||
}
|
||||
xs: { span: 24 },
|
||||
sm: { span: 24 },
|
||||
md: { span: 12 },
|
||||
lg: { span: 6 },
|
||||
xl: { span: 6 }
|
||||
};
|
||||
|
||||
export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||
const { t } = useTranslation();
|
||||
const { notification } = useNotification();
|
||||
const [notesClamped, setNotesClamped] = useState(true);
|
||||
const vehicleTitle = `${job.v_model_yr || ""} ${job.v_color || ""}
|
||||
${job.v_make_desc || ""}
|
||||
${job.v_model_desc || ""}`.trim();
|
||||
|
||||
const [updateJob] = useMutation(UPDATE_JOB);
|
||||
const vehicleTitle =
|
||||
`${job.v_model_yr || ""} ${job.v_color || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim();
|
||||
const bodyHrs = job.joblines.filter((j) => j.mod_lbr_ty !== "LAR").reduce((acc, val) => acc + val.mod_lb_hrs, 0);
|
||||
const refinishHrs = job.joblines
|
||||
.filter((line) => line.mod_lbr_ty === "LAR")
|
||||
.reduce((acc, val) => acc + val.mod_lb_hrs, 0);
|
||||
|
||||
const ownerTitle = OwnerNameDisplayFunction(job).trim();
|
||||
|
||||
// Handle checkbox changes
|
||||
const handleCheckboxChange = async (field, checked) => {
|
||||
const value = checked ? dayjs().toISOString() : null;
|
||||
try {
|
||||
await updateJob({
|
||||
variables: {
|
||||
jobId: job.id,
|
||||
job: { [field]: value }
|
||||
},
|
||||
refetchQueries: ["GET_JOB_BY_PK"],
|
||||
awaitRefetchQueries: true
|
||||
});
|
||||
} catch (error) {
|
||||
notification.error({
|
||||
message: t("jobs.errors.saving", { error: error.message })
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]} style={{ alignItems: "stretch" }}>
|
||||
<Col {...colSpan}>
|
||||
@@ -72,11 +89,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||
<DataLabel label={t("jobs.fields.status")}>
|
||||
<Space wrap>
|
||||
{job.status}
|
||||
{job.inproduction && (
|
||||
<Tag color="#f50" key="production">
|
||||
{t("jobs.labels.inproduction")}
|
||||
</Tag>
|
||||
)}
|
||||
{job.inproduction && <Tag color="#f50">{t("jobs.labels.inproduction")}</Tag>}
|
||||
{job.suspended && <PauseCircleOutlined style={{ color: "orangered" }} />}
|
||||
{job.iouparent && (
|
||||
<Link to={`/manage/jobs/${job.iouparent}`}>
|
||||
@@ -110,7 +123,6 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||
<span style={{ margin: "0rem .5rem" }}>/</span>
|
||||
<CurrencyFormatter>{job.owner_owing}</CurrencyFormatter>
|
||||
</DataLabel>
|
||||
|
||||
<DataLabel label={t("jobs.fields.alt_transport")}>
|
||||
{job.alt_transport}
|
||||
<JobAltTransportChange job={job} />
|
||||
@@ -127,11 +139,27 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||
))}
|
||||
</DataLabel>
|
||||
)}
|
||||
|
||||
<DataLabel label={t("jobs.fields.production_vars.note")}>
|
||||
<ProductionListColumnProductionNote record={job} />
|
||||
</DataLabel>
|
||||
|
||||
<DataLabel label={t("jobs.fields.estimate_sent_approval")}>
|
||||
<Checkbox
|
||||
checked={!!job.estimate_sent_approval}
|
||||
onChange={(e) => handleCheckboxChange("estimate_sent_approval", e.target.checked)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t("jobs.labels.sent")}
|
||||
</Checkbox>
|
||||
</DataLabel>
|
||||
<DataLabel label={t("jobs.fields.estimate_approved")}>
|
||||
<Checkbox
|
||||
checked={!!job.estimate_approved}
|
||||
onChange={(e) => handleCheckboxChange("estimate_approved", e.target.checked)}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t("jobs.labels.approved")}
|
||||
</Checkbox>
|
||||
</DataLabel>
|
||||
<Space wrap>
|
||||
{job.special_coverage_policy && (
|
||||
<Tag color="tomato">
|
||||
|
||||
@@ -685,6 +685,8 @@ export const GET_JOB_BY_PK = gql`
|
||||
scheduled_delivery
|
||||
scheduled_in
|
||||
selling_dealer
|
||||
estimate_approved
|
||||
estimate_sent_approval
|
||||
selling_dealer_contact
|
||||
servicing_dealer
|
||||
servicing_dealer_contact
|
||||
@@ -929,6 +931,8 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
||||
date_exported
|
||||
date_repairstarted
|
||||
date_scheduled
|
||||
estimate_sent_approval
|
||||
estimate_approved
|
||||
date_estimated
|
||||
employee_body_rel {
|
||||
id
|
||||
@@ -1077,6 +1081,8 @@ export const UPDATE_JOB = gql`
|
||||
date_repairstarted
|
||||
date_void
|
||||
date_lost_sale
|
||||
estimate_sent_approval
|
||||
estimate_approved
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2431,6 +2437,8 @@ export const QUERY_PARTS_QUEUE_CARD_DETAILS = gql`
|
||||
plate_st
|
||||
po_number
|
||||
production_vars
|
||||
estimate_sent_approval
|
||||
estimate_approved
|
||||
ro_number
|
||||
scheduled_completion
|
||||
scheduled_delivery
|
||||
|
||||
@@ -1650,6 +1650,8 @@
|
||||
"adjustment_bottom_line": "Adjustments",
|
||||
"adjustmenthours": "Adjustment Hours",
|
||||
"alt_transport": "Alt. Trans.",
|
||||
"estimate_sent_approval": "Estimate Sent for Approval",
|
||||
"estimate_approved": "Estimate Approved",
|
||||
"area_of_damage_impact": {
|
||||
"10": "Left Front Side",
|
||||
"11": "Left Front Corner",
|
||||
@@ -1955,6 +1957,8 @@
|
||||
"scheddates": "Schedule Dates"
|
||||
},
|
||||
"labels": {
|
||||
"sent": "",
|
||||
"approved": "",
|
||||
"accountsreceivable": "Accounts Receivable",
|
||||
"act_price_ppc": "New Part Price",
|
||||
"actual_completion_inferred": "$t(jobs.fields.actual_completion) inferred using $t(jobs.fields.scheduled_completion).",
|
||||
|
||||
@@ -1642,6 +1642,8 @@
|
||||
"voiding": ""
|
||||
},
|
||||
"fields": {
|
||||
"estimate_sent_approval": "",
|
||||
"estimate_approved": "",
|
||||
"active_tasks": "",
|
||||
"actual_completion": "Realización real",
|
||||
"actual_delivery": "Entrega real",
|
||||
@@ -1955,6 +1957,8 @@
|
||||
"scheddates": ""
|
||||
},
|
||||
"labels": {
|
||||
"sent": "",
|
||||
"approved": "",
|
||||
"accountsreceivable": "",
|
||||
"act_price_ppc": "",
|
||||
"actual_completion_inferred": "",
|
||||
|
||||
@@ -1642,6 +1642,8 @@
|
||||
"voiding": ""
|
||||
},
|
||||
"fields": {
|
||||
"estimate_sent_approval": "",
|
||||
"estimate_approved": "",
|
||||
"active_tasks": "",
|
||||
"actual_completion": "Achèvement réel",
|
||||
"actual_delivery": "Livraison réelle",
|
||||
@@ -1955,6 +1957,8 @@
|
||||
"scheddates": ""
|
||||
},
|
||||
"labels": {
|
||||
"sent": "",
|
||||
"approved": "",
|
||||
"accountsreceivable": "",
|
||||
"act_price_ppc": "",
|
||||
"actual_completion_inferred": "",
|
||||
|
||||
@@ -3702,6 +3702,8 @@
|
||||
- est_ph1
|
||||
- est_st
|
||||
- est_zip
|
||||
- estimate_approved
|
||||
- estimate_sent_approval
|
||||
- federal_tax_rate
|
||||
- flat_rate_ats
|
||||
- g_bett_amt
|
||||
@@ -3976,6 +3978,8 @@
|
||||
- est_ph1
|
||||
- est_st
|
||||
- est_zip
|
||||
- estimate_approved
|
||||
- estimate_sent_approval
|
||||
- federal_tax_rate
|
||||
- flat_rate_ats
|
||||
- g_bett_amt
|
||||
@@ -4262,6 +4266,8 @@
|
||||
- est_ph1
|
||||
- est_st
|
||||
- est_zip
|
||||
- estimate_approved
|
||||
- estimate_sent_approval
|
||||
- federal_tax_rate
|
||||
- flat_rate_ats
|
||||
- g_bett_amt
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "estimate_sent_approval" timestamptz
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "estimate_sent_approval" timestamptz
|
||||
null;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "estimate_approved" timestamptz
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "estimate_approved" timestamptz
|
||||
null;
|
||||
Reference in New Issue
Block a user