From 81d642fcd357a00227078a01d5edc29a2759b5ed Mon Sep 17 00:00:00 2001 From: Dave Date: Wed, 13 Aug 2025 18:10:57 -0400 Subject: [PATCH] feature/IO-3255-simplified-parts-management - dumb down print center --- .../print-center-jobs-parts.component.jsx | 183 ++++++++++++++++++ .../print-center-modal.component.jsx | 14 +- 2 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 client/src/components/print-center-jobs/print-center-jobs-parts.component.jsx diff --git a/client/src/components/print-center-jobs/print-center-jobs-parts.component.jsx b/client/src/components/print-center-jobs/print-center-jobs-parts.component.jsx new file mode 100644 index 000000000..ffacc7913 --- /dev/null +++ b/client/src/components/print-center-jobs/print-center-jobs-parts.component.jsx @@ -0,0 +1,183 @@ +import { useSplitTreatments } from "@splitsoftware/splitio-react"; +import { Button, Card, Col, Row, Space, Tooltip, Typography } from "antd"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectPrintCenter } from "../../redux/modals/modals.selectors"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import { selectTechnician } from "../../redux/tech/tech.selectors"; +import { TemplateList } from "../../utils/TemplateConstants"; +import { GenerateDocument } from "../../utils/RenderTemplate"; +import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; +import { HistoryOutlined, MailOutlined, PrinterOutlined, UnorderedListOutlined } from "@ant-design/icons"; + +const mapStateToProps = createStructuredSelector({ + printCenterModal: selectPrintCenter, + bodyshop: selectBodyshop, + technician: selectTechnician +}); + +const mapDispatchToProps = () => ({}); + +export function PrintCenterJobsPartsComponent({ printCenterModal, bodyshop, technician }) { + const { id: jobId, job } = printCenterModal.context; + const tempList = TemplateList("job", {}); + const notification = useNotification(); + const { + treatments: { Enhanced_Payroll } + } = useSplitTreatments({ + attributes: {}, + names: ["Enhanced_Payroll"], + splitKey: bodyshop.imexshopid + }); + + const Templates = + bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null + ? Object.keys(tempList) + .map((key) => tempList[key]) + .filter( + (temp) => + (!temp.regions || + (temp.regions && temp.regions[bodyshop.region_config]) || + (temp.regions && bodyshop.region_config.includes(Object.keys(temp.regions)) === true)) && + (!temp.dms || temp.dms === false) + ) + : Object.keys(tempList) + .map((key) => tempList[key]) + .filter( + (temp) => + !temp.regions || + (temp.regions && temp.regions[bodyshop.region_config]) || + (temp.regions && bodyshop.region_config.includes(Object.keys(temp.regions)) === true) + ); + + const JobsReportsList = + Enhanced_Payroll.treatment === "on" + ? Object.keys(Templates) + .map((key) => Templates[key]) + .filter((temp) => temp.enhanced_payroll === undefined || temp.enhanced_payroll === true) + : Object.keys(Templates) + .map((key) => Templates[key]) + .filter((temp) => temp.enhanced_payroll === undefined || temp.enhanced_payroll === false); + + const orderedKeys = ["parts_list", "parts_order_history"]; // explicit order + const cards = orderedKeys.map((k) => JobsReportsList.find((t) => t.key === k)).filter(Boolean); + + const handlePrint = async (key) => { + await GenerateDocument( + { + name: key, + variables: { id: jobId } + }, + {}, + "p", + jobId, + notification + ); + }; + + const handleEmail = async (key) => { + await GenerateDocument( + { + name: key, + variables: { id: jobId } + }, + { + to: job && job.ownr_ea, + subject: cards.find((c) => c.key === key)?.subject + }, + "e", + jobId, + notification + ); + }; + + const iconForKey = (key) => { + switch (key) { + case "parts_list": + return ; + case "parts_order_history": + return ; + default: + return ; + } + }; + + return ( +
+ + {cards.map((item) => { + const actions = [ + { + key: "print", + icon: , + onClick: () => handlePrint(item.key), + title: "Print", + disabled: item.disabled + }, + ...(!technician + ? [ + { + key: "email", + icon: , + onClick: () => handleEmail(item.key), + title: "Email", + disabled: item.disabled + } + ] + : []) + ]; + const columns = `repeat(${actions.length}, 1fr)`; + + return ( + + +
+
+ +
{iconForKey(item.key)}
+ + {item.title} + +
+
+
+
+ {actions.map((action) => ( + +
+
+
+
+ + ); + })} +
+
+ ); +} + +export default connect(mapStateToProps, mapDispatchToProps)(PrintCenterJobsPartsComponent); diff --git a/client/src/components/print-center-modal/print-center-modal.component.jsx b/client/src/components/print-center-modal/print-center-modal.component.jsx index b22c3b38f..8a0b1993b 100644 --- a/client/src/components/print-center-modal/print-center-modal.component.jsx +++ b/client/src/components/print-center-modal/print-center-modal.component.jsx @@ -1,7 +1,15 @@ import { useTranslation } from "react-i18next"; import PrintCenterJobs from "../print-center-jobs/print-center-jobs.component"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectIsPartsEntry } from "../../redux/application/application.selectors"; +import PrintCenterJobsParts from "../print-center-jobs/print-center-jobs-parts.component"; -export default function PrintCenterModalComponent({ context }) { +const mapStateToProps = createStructuredSelector({ + isPartsEntry: selectIsPartsEntry +}); + +export function PrintCenterModalComponent({ context, isPartsEntry }) { const { t } = useTranslation(); const { type } = context; @@ -9,10 +17,12 @@ export default function PrintCenterModalComponent({ context }) { switch (type) { case "job": - ModalContent = PrintCenterJobs; + ModalContent = isPartsEntry ? PrintCenterJobsParts : PrintCenterJobs; break; default: break; } return
{ModalContent ? : t("printcenter.errors.nocontexttype")}
; } + +export default connect(mapStateToProps)(PrintCenterModalComponent);