From cbb6c43ec34648203f380824fded7a1a65dcc7d7 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 23 Jun 2025 14:00:25 -0700 Subject: [PATCH] IO-3255 Clean up front end components for pm. --- .../global-footer/global-footer.component.jsx | 73 +++++++ .../job-detail-lines/job-lines.component.jsx | 183 ++++++++-------- .../jobs-lines-expander-simple.component.jsx | 83 ++++++++ .../jobs-detail-header.component.jsx | 199 +++++++++--------- .../jobs-detail-pli.component.jsx | 71 +++++-- ...arts-order-list-table-drawer.component.jsx | 109 +++++----- .../parts-order-list-table.component.jsx | 113 +++++----- client/src/graphql/jobs.queries.js | 1 + .../pages/manage/manage.page.component.jsx | 50 +---- ...simplified-parts-jobs-detail.component.jsx | 23 +- ...simplified-parts-jobs-detail.container.jsx | 4 +- .../simplified-parts.page.component.jsx | 54 +---- client/src/redux/user/user.actions.js | 5 + client/src/redux/user/user.reducer.js | 7 +- client/src/redux/user/user.sagas.js | 19 +- client/src/redux/user/user.selectors.js | 5 + client/src/redux/user/user.types.js | 3 +- 17 files changed, 588 insertions(+), 414 deletions(-) create mode 100644 client/src/components/global-footer/global-footer.component.jsx create mode 100644 client/src/components/job-detail-lines/jobs-lines-expander-simple.component.jsx diff --git a/client/src/components/global-footer/global-footer.component.jsx b/client/src/components/global-footer/global-footer.component.jsx new file mode 100644 index 000000000..7a5cefa62 --- /dev/null +++ b/client/src/components/global-footer/global-footer.component.jsx @@ -0,0 +1,73 @@ +import { AlertOutlined, BulbOutlined } from "@ant-design/icons"; +import { Button, Layout, Space } from "antd"; +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { Link } from "react-router-dom"; +import { createStructuredSelector } from "reselect"; +import WssStatusDisplayComponent from "../../components/wss-status-display/wss-status-display.component.jsx"; +import { addAlerts } from "../../redux/application/application.actions.js"; +import { selectAlerts } from "../../redux/application/application.selectors.js"; +import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors"; +import InstanceRenderManager from "../../utils/instanceRenderMgr.js"; +const { Footer } = Layout; + +const mapStateToProps = createStructuredSelector({ + conflict: selectInstanceConflict, + bodyshop: selectBodyshop, + alerts: selectAlerts +}); + +const mapDispatchToProps = (dispatch) => ({ + setAlerts: (alerts) => dispatch(addAlerts(alerts)) +}); + +export function GlobalFooter() { + const { t } = useTranslation(); + + useEffect(() => { + window.Canny("initChangelog", { + appID: "680bd2c7ee501290377f6686", + position: "top", + align: "left", + theme: "light" // options: light [default], dark, auto + }); + }, []); + + return ( + + ); +} + +export default connect(mapStateToProps, mapDispatchToProps)(GlobalFooter); diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index 41eb5f21a..29bbea71d 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -12,7 +12,7 @@ import { PageHeader } from "@ant-design/pro-layout"; import { useMutation } from "@apollo/client"; import { Button, Dropdown, Input, Space, Table, Tag } from "antd"; import axios from "axios"; -import React, { useState } from "react"; +import { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -32,7 +32,7 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re import { useSplitTreatments } from "@splitsoftware/splitio-react"; import _ from "lodash"; import { FaTasks } from "react-icons/fa"; -import { selectBodyshop } from "../../redux/user/user.selectors"; +import { selectBodyshop, selectPartsManagementOnly } from "../../redux/user/user.selectors"; import dayjs from "../../utils/day"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component"; @@ -45,11 +45,13 @@ import PartsOrderDrawer from "../parts-order-list-table/parts-order-list-table-d import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; import JobLinesExpander from "./job-lines-expander.component"; import JobLinesPartPriceChange from "./job-lines-part-price-change.component"; +import JobLinesExpanderSimple from "./jobs-lines-expander-simple.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, jobRO: selectJobReadOnly, - technician: selectTechnician + technician: selectTechnician, + partsManagementOnly: selectPartsManagementOnly }); const mapDispatchToProps = (dispatch) => ({ @@ -79,7 +81,7 @@ export function JobLinesComponent({ handleBillOnRowClick, handlePartsOrderOnRowClick, handlePartsDispatchOnRowClick, - simple + partsManagementOnly }) { const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK); const { @@ -93,7 +95,13 @@ export function JobLinesComponent({ const [selectedLines, setSelectedLines] = useState([]); const [state, setState] = useState({ sortedInfo: {}, - filteredInfo: {} + filteredInfo: { + ...(partsManagementOnly + ? { + part_type: ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"] + } + : {}) + } }); const { t } = useTranslation(); const jobIsPrivate = bodyshop.md_ins_cos.find((c) => c.name === job.ins_co_nm)?.private; @@ -221,7 +229,7 @@ export function JobLinesComponent({ sorter: (a, b) => a.part_qty - b.part_qty, sortOrder: state.sortedInfo.columnKey === "part_qty" && state.sortedInfo.order }, - ...(!simple + ...(!partsManagementOnly ? [ { title: t("joblines.fields.mod_lbr_ty"), @@ -273,7 +281,7 @@ export function JobLinesComponent({ key: "location", render: (text, record) => }, - ...(!simple && HasFeatureAccess({ featureName: "bills", bodyshop }) + ...(!partsManagementOnly && HasFeatureAccess({ featureName: "bills", bodyshop }) ? [ { title: t("joblines.labels.billref"), @@ -307,70 +315,74 @@ export function JobLinesComponent({ onFilter: (value, record) => value.includes(record.status), render: (text, record) => }, - { - title: t("general.labels.actions"), - dataIndex: "actions", - key: "actions", - render: (text, record) => ( - - {(record.manual_line || jobIsPrivate) && !technician && ( - <> - - - )} - - {(record.manual_line || jobIsPrivate) && !technician && ( - <> - + + )} + + {(record.manual_line || jobIsPrivate) && !technician && ( + <> + - - )} - - ) - } + }); + await axios.post("/job/totalsssu", { + id: job.id + }); + refetch && refetch(); + }} + > + + + + )} + + ) + } + ] + : [] ]; const handleTableChange = (pagination, filters, sorter) => { @@ -543,17 +555,19 @@ export function JobLinesComponent({ - + {!partsManagementOnly && ( + + )} {InstanceRenderManager({ rome: })} , + expandedRowRender: (record) => + partsManagementOnly ? ( + + ) : ( + + ), rowExpandable: (record) => true, //expandRowByClick: true, expandIcon: ({ expanded, onExpand, record }) => diff --git a/client/src/components/job-detail-lines/jobs-lines-expander-simple.component.jsx b/client/src/components/job-detail-lines/jobs-lines-expander-simple.component.jsx new file mode 100644 index 000000000..4fa50c9fa --- /dev/null +++ b/client/src/components/job-detail-lines/jobs-lines-expander-simple.component.jsx @@ -0,0 +1,83 @@ +import { useQuery } from "@apollo/client"; +import { Col, Row, Skeleton, Timeline, Typography } from "antd"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { Link } from "react-router-dom"; +import { createStructuredSelector } from "reselect"; +import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries"; +import { selectTechnician } from "../../redux/tech/tech.selectors.js"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import { DateFormatter } from "../../utils/DateFormatter"; +import AlertComponent from "../alert/alert.component"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop, + technician: selectTechnician +}); + +const mapDispatchToProps = (dispatch) => ({}); + +export default connect(mapStateToProps, mapDispatchToProps)(JobLinesExpanderSimple); + +export function JobLinesExpanderSimple({ jobline, jobid, bodyshop, technician }) { + const { t } = useTranslation(); + const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, { + fetchPolicy: "network-only", + nextFetchPolicy: "network-only", + variables: { + joblineid: jobline.id + } + }); + + if (loading) return ; + if (error) return ; + + return ( + + + {t("parts_orders.labels.parts_orders")} + 0 + ? data.parts_order_lines.map((line) => ({ + key: line.id, + children: ( + + + {!technician ? ( + <> + + {line.parts_order.order_number} + + + ) : ( + `${line.parts_order.order_number}` + )} + + + {line.parts_order.order_date} + + {line.parts_order.vendor.name} + {line.backordered_eta ? ( + + + {`${t("parts_orders.fields.backordered_eta")}: `} + {line.backordered_eta} + + + ) : null} + + ) + })) + : [ + { + key: "no-orders", + children: t("parts_orders.labels.notyetordered") + } + ] + } + /> + + + ); +} diff --git a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx index 141cab456..b3d49dfdc 100644 --- a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx +++ b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx @@ -11,7 +11,7 @@ import { UPDATE_JOB } from "../../graphql/jobs.queries"; import { insertAuditTrail } from "../../redux/application/application.actions.js"; import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { setModalContext } from "../../redux/modals/modals.actions"; -import { selectBodyshop } from "../../redux/user/user.selectors"; +import { selectBodyshop, selectPartsManagementOnly } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings.js"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateTimeFormatter, DateTimeFormatterFunction } from "../../utils/DateFormatter"; @@ -30,7 +30,8 @@ import "./jobs-detail-header.styles.scss"; const mapStateToProps = createStructuredSelector({ jobRO: selectJobReadOnly, - bodyshop: selectBodyshop + bodyshop: selectBodyshop, + partsManagementOnly: selectPartsManagementOnly }); const mapDispatchToProps = (dispatch) => ({ @@ -51,19 +52,20 @@ const mapDispatchToProps = (dispatch) => ({ ) }); -const colSpan = { - xs: { span: 24 }, - sm: { span: 24 }, - md: { span: 12 }, - lg: { span: 6 }, - xl: { span: 6 } -}; - -export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail }) { +export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail, partsManagementOnly }) { const { t } = useTranslation(); const { notification } = useNotification(); const [notesClamped, setNotesClamped] = useState(true); const [updateJob] = useMutation(UPDATE_JOB); + + const colSpan = { + xs: { span: 24 }, + sm: { span: 24 }, + md: { span: partsManagementOnly ? 8 : 12 }, + lg: { span: partsManagementOnly ? 8 : 6 }, + xl: { span: partsManagementOnly ? 8 : 6 } + }; + 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); @@ -143,81 +145,86 @@ export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail }) / {job.owner_owing} - - {job.alt_transport} - - - {job?.cccontracts?.length > 0 && ( - - {job.cccontracts.map((c, index) => ( - - - {`${c.agreementnumber} - ${c.courtesycar.fleetnumber} ${c.courtesycar.year} ${c.courtesycar.make} ${c.courtesycar.model}`} - {index !== job.cccontracts.length - 1 ? "," : null} - + + {!partsManagementOnly && ( + <> + + {job.alt_transport} + + + {job?.cccontracts?.length > 0 && ( + + {job.cccontracts.map((c, index) => ( + + + {`${c.agreementnumber} - ${c.courtesycar.fleetnumber} ${c.courtesycar.year} ${c.courtesycar.make} ${c.courtesycar.model}`} + {index !== job.cccontracts.length - 1 ? "," : null} + + + ))} + + )} + + + + + + handleCheckboxChange("estimate_sent_approval", e.target.checked)} + disabled={disabled} + > + {job.estimate_sent_approval && ( + + {job.estimate_sent_approval} + + )} + - ))} - + + + + handleCheckboxChange("estimate_approved", e.target.checked)} + disabled={disabled} + > + {job.estimate_approved && ( + + {job.estimate_approved} + + )} + + + + + {job.special_coverage_policy && ( + + + + {t("jobs.labels.specialcoveragepolicy")} + + + )} + {job.ca_gst_registrant && ( + + + + {t("jobs.fields.ca_gst_registrant")} + + + )} + {job.hit_and_run && ( + + + + {t("jobs.fields.hit_and_run")} + + + )} + + )} - - - - - - handleCheckboxChange("estimate_sent_approval", e.target.checked)} - disabled={disabled} - > - {job.estimate_sent_approval && ( - - {job.estimate_sent_approval} - - )} - - - - - - handleCheckboxChange("estimate_approved", e.target.checked)} - disabled={disabled} - > - {job.estimate_approved && ( - - {job.estimate_approved} - - )} - - - - - {job.special_coverage_policy && ( - - - - {t("jobs.labels.specialcoveragepolicy")} - - - )} - {job.ca_gst_registrant && ( - - - - {t("jobs.fields.ca_gst_registrant")} - - - )} - {job.hit_and_run && ( - - - - {t("jobs.fields.hit_and_run")} - - - )} - @@ -334,17 +341,19 @@ export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail }) - - -
- - - - {bodyHrs.toFixed(1)} / {refinishHrs.toFixed(1)} / {(bodyHrs + refinishHrs).toFixed(1)} - -
-
- + {!partsManagementOnly && ( + + +
+ + + + {bodyHrs.toFixed(1)} / {refinishHrs.toFixed(1)} / {(bodyHrs + refinishHrs).toFixed(1)} + +
+
+ + )} ); } diff --git a/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx b/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx index 704ed9d10..f207bb8af 100644 --- a/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx +++ b/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx @@ -8,27 +8,27 @@ import PartsDispatchTable from "../parts-dispatch-table/parts-dispatch-table.com import PartsOrderListTableComponent from "../parts-order-list-table/parts-order-list-table.component"; import PartsOrderModal from "../parts-order-modal/parts-order-modal.container"; -export default function JobsDetailPliComponent({ +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectPartsManagementOnly } from "../../redux/user/user.selectors"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser + partsManagementOnly: selectPartsManagementOnly +}); +const mapDispatchToProps = (dispatch) => ({}); +export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailPliComponent); + +export function JobsDetailPliComponent({ job, billsQuery, handleBillOnRowClick, handlePartsOrderOnRowClick, - handlePartsDispatchOnRowClick + handlePartsDispatchOnRowClick, + partsManagementOnly }) { - return ( -
- - {billsQuery.error ? : null} - + if (partsManagementOnly) { + return ( - - - - - - - - - -
- ); + ); + } else { + return ( +
+ + {billsQuery.error ? : null} + + + + + + + + + + + + + + + +
+ ); + } } diff --git a/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx b/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx index 3fe23ca4c..0b551fcb6 100644 --- a/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx +++ b/client/src/components/parts-order-list-table/parts-order-list-table-drawer.component.jsx @@ -14,7 +14,7 @@ import { QUERY_BILL_BY_PK } from "../../graphql/bills.queries"; import { DELETE_PARTS_ORDER } from "../../graphql/parts-orders.queries"; import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { setModalContext } from "../../redux/modals/modals.actions"; -import { selectBodyshop } from "../../redux/user/user.selectors"; +import { selectBodyshop, selectPartsManagementOnly } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter } from "../../utils/DateFormatter"; import { TemplateList } from "../../utils/TemplateConstants"; @@ -31,7 +31,8 @@ import PrintWrapper from "../print-wrapper/print-wrapper.component"; const mapStateToProps = createStructuredSelector({ jobRO: selectJobReadOnly, - bodyshop: selectBodyshop + bodyshop: selectBodyshop, + partsManagementOnly: selectPartsManagementOnly }); const mapDispatchToProps = (dispatch) => ({ @@ -60,7 +61,8 @@ export function PartsOrderListTableDrawerComponent({ billsQuery, handleOnRowClick, setPartsReceiveContext, - setTaskUpsertContext + setTaskUpsertContext, + partsManagementOnly }) { const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) .filter((screen) => !!screen[1]) @@ -134,19 +136,21 @@ export function PartsOrderListTableDrawerComponent({ > {t("parts_orders.actions.receive")} - + {!partsManagementOnly && ( + + )} - - + }); + }} + > + {t("parts_orders.actions.receivebill")} + + )} ({ @@ -52,7 +53,8 @@ export function PartsOrderListTableComponent({ billsQuery, handleOnRowClick, setPartsReceiveContext, - setTaskUpsertContext + setTaskUpsertContext, + partsManagementOnly }) { const responsibilityCenters = bodyshop.md_responsibility_centers; const Templates = TemplateList("partsorder", { job }); @@ -106,18 +108,23 @@ export function PartsOrderListTableComponent({ > {t("parts_orders.actions.receive")} - + }); + }} + > + {t("parts_orders.actions.receivebill")} + + )} import("../jobs/jobs.page")); @@ -658,38 +657,7 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) { -
-
- - - - - -
- {`${InstanceRenderManager({ - imex: t("titles.imexonline"), - rome: t("titles.romeonline") - })} - ${import.meta.env.VITE_APP_GIT_SHA_DATE}`} -
- -
- - Disclaimer & Notices - -
-
+ ); diff --git a/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.component.jsx b/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.component.jsx index 195f1da18..4b5cca325 100644 --- a/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.component.jsx +++ b/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.component.jsx @@ -22,11 +22,12 @@ import { QUERY_PARTS_BILLS_BY_JOBID } from "../../graphql/bills.queries.js"; import { insertAuditTrail } from "../../redux/application/application.actions.js"; import { selectJobReadOnly } from "../../redux/application/application.selectors.js"; import { setModalContext } from "../../redux/modals/modals.actions.js"; -import { selectBodyshop } from "../../redux/user/user.selectors.js"; +import { selectBodyshop, selectPartsManagementOnly } from "../../redux/user/user.selectors.js"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, - jobRO: selectJobReadOnly + jobRO: selectJobReadOnly, + partsManagementOnly: selectPartsManagementOnly }); const mapDispatchToProps = (dispatch) => ({ setPrintCenterContext: (context) => @@ -53,7 +54,8 @@ export function SimplifiedPartsJobDetailComponent({ job, mutationUpdateJob, insertAuditTrail, - refetch + refetch, + partsManagementOnly }) { const { t } = useTranslation(); const [form] = Form.useForm(); @@ -141,10 +143,14 @@ export function SimplifiedPartsJobDetailComponent({ {t("jobs.actions.printCenter")} - - + {!partsManagementOnly && ( + <> + + + + )} ); @@ -153,7 +159,7 @@ export function SimplifiedPartsJobDetailComponent({ {job.ro_number || t("general.labels.na")}} extra={menuExtra} /> - + @@ -178,7 +184,6 @@ export function SimplifiedPartsJobDetailComponent({ handlePartsDispatchOnRowClick={handlePartsDispatchOnRowClick} refetch={refetch} form={form} - simple /> ) }, diff --git a/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.container.jsx b/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.container.jsx index 2728118d0..12bb15473 100644 --- a/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.container.jsx +++ b/client/src/pages/simplified-parts-jobs-detail/simplified-parts-jobs-detail.container.jsx @@ -63,7 +63,7 @@ function SimplifiedPartsJobsDetailContainer({ setBreadcrumbs, addRecentItem, set ro_number: (data.jobs_by_pk && data.jobs_by_pk.ro_number) || t("general.labels.na") }); setBreadcrumbs([ - { link: "/parts/jobs", label: t("titles.bc.jobs") }, + { link: "/parts/", label: t("titles.bc.jobs") }, { link: `/parts/jobs/${jobId}`, label: t("titles.bc.jobs-detail", { @@ -81,7 +81,7 @@ function SimplifiedPartsJobsDetailContainer({ setBreadcrumbs, addRecentItem, set "job", `${data.jobs_by_pk.ro_number || t("general.labels.na")} | ${OwnerNameDisplayFunction(data.jobs_by_pk)}`, - `/manage/jobs/${jobId}` + `/parts/jobs/${jobId}` ) ); } diff --git a/client/src/pages/simplified-parts/simplified-parts.page.component.jsx b/client/src/pages/simplified-parts/simplified-parts.page.component.jsx index 5180feaff..aa906834f 100644 --- a/client/src/pages/simplified-parts/simplified-parts.page.component.jsx +++ b/client/src/pages/simplified-parts/simplified-parts.page.component.jsx @@ -1,26 +1,24 @@ -import { AlertOutlined, BulbOutlined } from "@ant-design/icons"; import * as Sentry from "@sentry/react"; -import { Button, FloatButton, Layout, Space, Spin } from "antd"; +import { FloatButton, Layout, Spin } from "antd"; import { lazy, Suspense, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; -import { Link, Route, Routes } from "react-router-dom"; +import { Route, Routes } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import BreadCrumbs from "../../components/breadcrumbs/breadcrumbs.component.jsx"; import ConflictComponent from "../../components/conflict/conflict.component.jsx"; import ErrorBoundary from "../../components/error-boundary/error-boundary.component.jsx"; +import GlobalFooter from "../../components/global-footer/global-footer.component.jsx"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component.jsx"; import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container.jsx"; import ShopSubStatusComponent from "../../components/shop-sub-status/shop-sub-status.component.jsx"; import UpdateAlert from "../../components/update-alert/update-alert.component.jsx"; -import WssStatusDisplayComponent from "../../components/wss-status-display/wss-status-display.component.jsx"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import { addAlerts } from "../../redux/application/application.actions.js"; import { selectAlerts } from "../../redux/application/application.selectors.js"; import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors.js"; import InstanceRenderManager from "../../utils/instanceRenderMgr.js"; - const SimplifiedPartsJobsPage = lazy(() => import("../simplified-parts-jobs/simplified-parts-jobs.page.jsx")); const SimplifiedPartsJobsDetailPage = lazy( () => import("../simplified-parts-jobs-detail/simplified-parts-jobs-detail.container.jsx") @@ -29,12 +27,10 @@ const ShopPage = lazy(() => import("../shop/shop.page.component.jsx")); const ShopVendorPageContainer = lazy(() => import("../shop-vendor/shop-vendor.page.container.jsx")); const EmailOverlayContainer = lazy(() => import("../../components/email-overlay/email-overlay.container.jsx")); const FeatureRequestPage = lazy(() => import("../feature-request/feature-request.page.jsx")); -const JobCostingModal = lazy(() => import("../../components/job-costing-modal/job-costing-modal.container.jsx")); const ReportCenterModal = lazy(() => import("../../components/report-center-modal/report-center-modal.container.jsx")); -const BillEnterModalContainer = lazy(() => import("../../components/bill-enter-modal/bill-enter-modal.container.jsx")); const Help = lazy(() => import("../help/help.page.jsx")); -const { Content, Footer } = Layout; +const { Content } = Layout; const mapStateToProps = createStructuredSelector({ conflict: selectInstanceConflict, @@ -141,8 +137,6 @@ export function SimplifiedPartsPage({ conflict, bodyshop, alerts, setAlerts }) { } > - - @@ -199,13 +193,6 @@ export function SimplifiedPartsPage({ conflict, bodyshop, alerts, setAlerts }) { else if (bodyshop && bodyshop.sub_status !== "active") PageContent = ; else PageContent = AppRouteTable; - const broadcastMessage = () => { - if (socket && bodyshop && bodyshop.id) { - console.log(`Broadcasting message to bodyshop ${bodyshop.id}:`); - socket.emit("broadcast-to-bodyshop", bodyshop.id, `Hello from ${clientId}`); - } - }; - return ( @@ -216,38 +203,7 @@ export function SimplifiedPartsPage({ conflict, bodyshop, alerts, setAlerts }) { -
-
- - - - - -
- {`${InstanceRenderManager({ - imex: t("titles.imexonline"), - rome: t("titles.romeonline") - })} - ${import.meta.env.VITE_APP_GIT_SHA_DATE}`} -
- -
- - Disclaimer & Notices - -
-
+
); } diff --git a/client/src/redux/user/user.actions.js b/client/src/redux/user/user.actions.js index 01ba22534..3d1d6fb9e 100644 --- a/client/src/redux/user/user.actions.js +++ b/client/src/redux/user/user.actions.js @@ -123,3 +123,8 @@ export const setImexShopId = (imexshopid) => ({ type: UserActionTypes.SET_IMEX_SHOP_ID, payload: imexshopid }); + +export const setPartsManagementOnly = (partsManagementOnly) => ({ + type: UserActionTypes.SET_PARTS_MANAGEMENT_ONLY, + payload: partsManagementOnly +}); \ No newline at end of file diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js index eebb32433..89d489f3a 100644 --- a/client/src/redux/user/user.reducer.js +++ b/client/src/redux/user/user.reducer.js @@ -7,6 +7,7 @@ const INITIAL_STATE = { //language: "en-US" }, bodyshop: null, + partsManagementOnly: null, loginLoading: false, fingerprint: null, error: null, @@ -125,7 +126,11 @@ const userReducer = (state = INITIAL_STATE, action) => { ...state, imexshopid: action.payload }; - + case UserActionTypes.SET_PARTS_MANAGEMENT_ONLY: + return { + ...state, + partsManagementOnly: action.payload + }; default: return state; } diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js index 79e3926f7..649551ff6 100644 --- a/client/src/redux/user/user.sagas.js +++ b/client/src/redux/user/user.sagas.js @@ -38,6 +38,7 @@ import { setInstanceConflict, setInstanceId, setLocalFingerprint, + setPartsManagementOnly, signInFailure, signInSuccess, signOutFailure, @@ -344,13 +345,13 @@ export function* SetAuthLevelFromShopDetails({ payload }) { payload.features?.allAccess === true ? window.$crisp.push(["set", "session:segments", [["allAccess"]]]) : (() => { - const featureKeys = Object.keys(payload.features).filter( - (key) => - payload.features[key] === true || - (typeof payload.features[key] === "string" && !isNaN(Date.parse(payload.features[key]))) - ); - window.$crisp.push(["set", "session:segments", [["basic", ...featureKeys]]]); - })(); + const featureKeys = Object.keys(payload.features).filter( + (key) => + payload.features[key] === true || + (typeof payload.features[key] === "string" && !isNaN(Date.parse(payload.features[key]))) + ); + window.$crisp.push(["set", "session:segments", [["basic", ...featureKeys]]]); + })(); InstanceRenderManager({ executeFunction: true, @@ -359,6 +360,10 @@ export function* SetAuthLevelFromShopDetails({ payload }) { window.$zoho.salesiq.visitor.info({ "Shop Name": payload.shopname }); } }); + + //Set whether it is for parts management only. + + yield put(setPartsManagementOnly(true || payload.features.partsManagementOnly)); } catch (error) { console.warn("Couldnt find $crisp.", error.message); } diff --git a/client/src/redux/user/user.selectors.js b/client/src/redux/user/user.selectors.js index a2afd47a8..b08b12931 100644 --- a/client/src/redux/user/user.selectors.js +++ b/client/src/redux/user/user.selectors.js @@ -1,3 +1,4 @@ +import { create } from "lodash"; import { createSelector } from "reselect"; const selectUser = (state) => state.user; @@ -17,3 +18,7 @@ export const selectAuthLevel = createSelector([selectUser], (user) => user.authL export const selectLoginLoading = createSelector([selectUser], (user) => user.loginLoading); export const selectCurrentEula = createSelector([selectUser], (user) => user.currentEula); +export const selectPartsManagementOnly = createSelector( + [selectUser], + (user) => user.partsManagementOnly +); \ No newline at end of file diff --git a/client/src/redux/user/user.types.js b/client/src/redux/user/user.types.js index d9cd6fe62..e6c9ca7fc 100644 --- a/client/src/redux/user/user.types.js +++ b/client/src/redux/user/user.types.js @@ -33,6 +33,7 @@ const UserActionTypes = { CHECK_ACTION_CODE_FAILURE: "CHECK_ACTION_CODE_FAILURE", SET_CURRENT_EULA: "SET_CURRENT_EULA", EULA_ACCEPTED: "EULA_ACCEPTED", - SET_IMEX_SHOP_ID: "SET_IMEX_SHOP_ID" + SET_IMEX_SHOP_ID: "SET_IMEX_SHOP_ID", + SET_PARTS_MANAGEMENT_ONLY: "SET_PARTS_MANAGEMENT_ONLY", }; export default UserActionTypes;