diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index ff279e491..8bc43fc67 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -4388,6 +4388,27 @@ + + last_name_first + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + lastnumberworkingdays false @@ -29965,6 +29986,27 @@ + + cancelallappointments + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + closejob false @@ -32672,6 +32714,27 @@ + + notyetordered + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + oec false diff --git a/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx b/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx index 9830b4f4b..30ac03db3 100644 --- a/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx +++ b/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx @@ -12,6 +12,7 @@ import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -76,14 +77,12 @@ export function AccountingPayablesTableComponent({ render: (text, record) => { return record.job.owner ? ( - {`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${ - record.job.ownr_co_nm || "" - }`} + ) : ( - {`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${ - record.job.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx b/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx index a4c255f7d..d49edecf7 100644 --- a/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx +++ b/client/src/components/accounting-receivables-table/accounting-receivables-table.component.jsx @@ -13,6 +13,8 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import { DateFormatter } from "../../utils/DateFormatter"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; + const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); @@ -85,14 +87,12 @@ export function AccountingReceivablesTableComponent({ render: (text, record) => { return record.owner ? ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + ) : ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index fa899a89b..cb020ed26 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -7,6 +7,7 @@ import { selectSelectedConversation } from "../../redux/messaging/messaging.sele import { TimeAgoFormatter } from "../../utils/DateFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; import "./chat-conversation-list.styles.scss"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ selectedConversation: selectSelectedConversation, @@ -40,9 +41,9 @@ export function ChatConversationListComponent({ {item.job_conversations.length > 0 ? (
{item.job_conversations.map((j, idx) => ( -
{`${j.job.ownr_fn || ""} ${ - j.job.ownr_ln || "" - } ${j.job.ownr_co_nm || ""} `}
+
+ +
))}
) : ( diff --git a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx index fc3971a82..a7eb66c4f 100644 --- a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx +++ b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx @@ -4,6 +4,7 @@ import React from "react"; import { Link } from "react-router-dom"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function ChatConversationTitleTags({ jobConversations }) { const [removeJobConversation] = useMutation(REMOVE_CONVERSATION_TAG); @@ -45,9 +46,8 @@ export default function ChatConversationTitleTags({ jobConversations }) { onClose={() => handleRemoveTag(item.job.id)} > - {`${item.job.ro_number || "?"} | ${item.job.ownr_fn || ""} ${ - item.job.ownr_ln || "" - } ${item.job.ownr_co_nm || ""}`} + {`${item.job.ro_number || "?"} | `} + ))} diff --git a/client/src/components/chat-tag-ro/chat-tag-ro.component.jsx b/client/src/components/chat-tag-ro/chat-tag-ro.component.jsx index fef423b69..ad9f64e02 100644 --- a/client/src/components/chat-tag-ro/chat-tag-ro.component.jsx +++ b/client/src/components/chat-tag-ro/chat-tag-ro.component.jsx @@ -1,7 +1,8 @@ import { CloseCircleOutlined, LoadingOutlined } from "@ant-design/icons"; -import { Select, Empty, Space } from "antd"; +import { Empty, Select, Space } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; +import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; export default function ChatTagRoComponent({ roOptions, @@ -27,9 +28,7 @@ export default function ChatTagRoComponent({ > {roOptions.map((item, idx) => ( - {` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${ - item.ownr_ln || "" - } ${item.ownr_co_nm || ""}`} + {` ${item.ro_number || ""} | ${OwnerNameDisplayFunction(item)}`} ))} diff --git a/client/src/components/contract-job-block/contract-job-block.component.jsx b/client/src/components/contract-job-block/contract-job-block.component.jsx index 64732a1f0..b0ee45401 100644 --- a/client/src/components/contract-job-block/contract-job-block.component.jsx +++ b/client/src/components/contract-job-block/contract-job-block.component.jsx @@ -3,7 +3,7 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import DataLabel from "../data-label/data-label.component"; - +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function ContractJobBlock({ job }) { const { t } = useTranslation(); return ( @@ -23,9 +23,7 @@ export default function ContractJobBlock({ job }) { } ${(job && job.v_model_desc) || ""}`} - {`${(job && job.ownr_fn) || ""} ${(job && job.ownr_ln) || ""} ${ - (job && job.ownr_co_nm) || "" - }`} + diff --git a/client/src/components/contract-jobs/contract-jobs.component.jsx b/client/src/components/contract-jobs/contract-jobs.component.jsx index 416274989..10abd5b22 100644 --- a/client/src/components/contract-jobs/contract-jobs.component.jsx +++ b/client/src/components/contract-jobs/contract-jobs.component.jsx @@ -3,6 +3,7 @@ import React, { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { alphaSort } from "../../utils/sorters"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function ContractsJobsComponent({ loading, @@ -43,17 +44,7 @@ export default function ContractsJobsComponent({ width: "25%", sortOrder: state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, - render: (text, record) => { - return record.owner ? ( - - {record.ownr_fn} {record.ownr_ln} {record.ownr_co_nm || ""} - - ) : ( - {`${record.ownr_fn} ${record.ownr_ln} ${ - record.ownr_co_nm || "" - }`} - ); - }, + render: (text, record) => , }, { title: t("jobs.fields.status"), diff --git a/client/src/components/contracts-list/contracts-list.component.jsx b/client/src/components/contracts-list/contracts-list.component.jsx index 063b0dbb9..2d5576565 100644 --- a/client/src/components/contracts-list/contracts-list.component.jsx +++ b/client/src/components/contracts-list/contracts-list.component.jsx @@ -12,17 +12,22 @@ import { setModalContext } from "../../redux/modals/modals.actions"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import moment from "moment"; +import { selectBodyshop } from "../../redux/user/user.selectors"; + const mapStateToProps = createStructuredSelector({ - //currentUser: selectCurrentUser + bodyshop: selectBodyshop, }); + const mapDispatchToProps = (dispatch) => ({ //setUserLanguage: language => dispatch(setUserLanguage(language)) setContractFinderContext: (context) => dispatch(setModalContext({ context: context, modal: "contractFinder" })), }); + export default connect(mapStateToProps, mapDispatchToProps)(ContractsList); export function ContractsList({ + bodyshop, loading, contracts, refetch, @@ -72,7 +77,9 @@ export function ContractsList({ sortOrder: state.sortedInfo.columnKey === "driver_ln" && state.sortedInfo.order, render: (text, record) => - `${record.driver_fn || ""} ${record.driver_ln || ""}`, + bodyshop.last_name_first + ? `${record.driver_ln || ""}, ${record.driver_fn || ""}` + : `${record.driver_fn || ""} ${record.driver_ln || ""}`, }, { title: t("contracts.labels.vehicle"), diff --git a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx index a720968b9..9e725514b 100644 --- a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx +++ b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx @@ -1,9 +1,11 @@ -import { Table, Button, Input, Card, Space } from "antd"; +import { SyncOutlined } from "@ant-design/icons"; +import { Button, Card, Input, Space, Table } from "antd"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import { alphaSort } from "../../utils/sorters"; -import { SyncOutlined } from "@ant-design/icons"; +import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; + export default function CourtesyCarsList({ loading, courtesycars, refetch }) { const [state, setState] = useState({ sortedInfo: {}, @@ -97,9 +99,9 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { render: (text, record) => record.cccontracts.length === 1 ? ( - {`${record.cccontracts[0].job.ro_number} - ${ - record.cccontracts[0].job.ownr_fn || "" - } ${record.cccontracts[0].job.ownr_ln || ""} ${record.cccontracts[0].job.ownr_co_nm || ""}`} + {`${ + record.cccontracts[0].job.ro_number + } - ${OwnerNameDisplayFunction(record.cccontracts[0].job)}`} ) : null, }, diff --git a/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx b/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx index 9e522bc52..e512cca20 100644 --- a/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx +++ b/client/src/components/csi-response-list-paginated/csi-response-list-paginated.component.jsx @@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"; import { Link, useHistory, useLocation } from "react-router-dom"; import { DateFormatter } from "../../utils/DateFormatter"; import { alphaSort } from "../../utils/sorters"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function CsiResponseListPaginated({ refetch, @@ -48,14 +49,12 @@ export default function CsiResponseListPaginated({ render: (text, record) => { return record.job.owner ? ( - {`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${ - record.job.ownr_co_nm || "" - }`} + ) : ( - {`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${ - record.job.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/global-search/global-search.component.jsx b/client/src/components/global-search/global-search.component.jsx index 4806c7ab6..76c664b0a 100644 --- a/client/src/components/global-search/global-search.component.jsx +++ b/client/src/components/global-search/global-search.component.jsx @@ -7,7 +7,9 @@ import { Link } from "react-router-dom"; import { GLOBAL_SEARCH_QUERY } from "../../graphql/search.queries"; import PhoneNumberFormatter from "../../utils/PhoneFormatter"; import AlertComponent from "../alert/alert.component"; - +import OwnerNameDisplay, { + OwnerNameDisplayFunction, +} from "../owner-name-display/owner-name-display.component"; export default function GlobalSearch() { const { t } = useTranslation(); @@ -39,9 +41,9 @@ export default function GlobalSearch() { }> {job.ro_number || t("general.labels.na")} {`${job.status || ""}`} - {`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${ - job.ownr_co_nm || "" - }`} + + + {`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${ job.v_model_desc || "" }`} @@ -57,15 +59,13 @@ export default function GlobalSearch() { options: data.search_owners.map((owner) => { return { key: owner.id, - value: `${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${ - owner.ownr_co_nm || "" - }`, + value: OwnerNameDisplayFunction(owner), label: ( } wrap> - {`${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${ - owner.ownr_co_nm || "" - }`} + + + {owner.ownr_ph1} diff --git a/client/src/components/job-at-change/schedule-event.component.jsx b/client/src/components/job-at-change/schedule-event.component.jsx index 933cb067b..78d4c3040 100644 --- a/client/src/components/job-at-change/schedule-event.component.jsx +++ b/client/src/components/job-at-change/schedule-event.component.jsx @@ -31,6 +31,7 @@ import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event. import ScheduleAtChange from "./job-at-change.component"; import ScheduleEventColor from "./schedule-event.color.component"; import ScheduleEventNote from "./schedule-event.note.component"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -73,9 +74,9 @@ export function ScheduleEventComponent({ ) : ( - {`${(event.job && event.job.ownr_fn) || ""} ${ - (event.job && event.job.ownr_ln) || "" - }`} + + + {`${(event.job && event.job.v_model_yr) || ""} ${ (event.job && event.job.v_make_desc) || "" @@ -256,9 +257,9 @@ export function ScheduleEventComponent({ {event.note && } {`${event.job.ro_number || t("general.labels.na")}`} - {`${(event.job && event.job.ownr_fn) || ""} ${ - (event.job && event.job.ownr_ln) || "" - } ${(event.job && event.job.ownr_co_nm) || ""}`} + + + diff --git a/client/src/components/job-detail-lines/job-lines-expander.component.jsx b/client/src/components/job-detail-lines/job-lines-expander.component.jsx new file mode 100644 index 000000000..b875a61b1 --- /dev/null +++ b/client/src/components/job-detail-lines/job-lines-expander.component.jsx @@ -0,0 +1,54 @@ +import { useQuery } from "@apollo/client"; +import { Row, Col, Timeline, Typography, Space, Divider, Skeleton } from "antd"; +import React from "react"; +import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries"; +import { useTranslation } from "react-i18next"; +import AlertComponent from "../alert/alert.component"; +import { DateFormatter } from "../../utils/DateFormatter"; +import { Link } from "react-router-dom"; + +export default function JobLinesExpander({ jobline, jobid }) { + 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")} + + + {data.parts_order_lines.length > 0 ? ( + data.parts_order_lines.map((line) => ( + + } wrap> + + {line.parts_order.order_number} + + {line.parts_order.order_date} + {line.parts_order.vendor.name} + + + )) + ) : ( + + {t("parts_orders.labels.notyetordered")} + + )} + + + + + ); +} 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 e00fa21c3..f811752df 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -4,6 +4,8 @@ import { SyncOutlined, WarningFilled, EditFilled, + PlusCircleTwoTone, + MinusCircleTwoTone, } from "@ant-design/icons"; import { useMutation } from "@apollo/client"; import { @@ -38,6 +40,7 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; import _ from "lodash"; import JobCreateIOU from "../job-create-iou/job-create-iou.component"; +import JobLinesExpander from "./job-lines-expander.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -449,6 +452,19 @@ export function JobLinesComponent({ scroll={{ x: true, }} + expandable={{ + expandedRowRender: (record) => ( + + ), + rowExpandable: (record) => true, + expandRowByClick: true, + expandIcon: ({ expanded, onExpand, record }) => + expanded ? ( + onExpand(record, e)} /> + ) : ( + onExpand(record, e)} /> + ), + }} onRow={(record, rowIndex) => { return { onDoubleClick: (event) => { diff --git a/client/src/components/job-search-select/job-search-select.component.jsx b/client/src/components/job-search-select/job-search-select.component.jsx index 11dcafcb4..8065a65cc 100644 --- a/client/src/components/job-search-select/job-search-select.component.jsx +++ b/client/src/components/job-search-select/job-search-select.component.jsx @@ -9,6 +9,7 @@ import { SEARCH_JOBS_FOR_AUTOCOMPLETE, } from "../../graphql/jobs.queries"; import AlertComponent from "../alert/alert.component"; +import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; const { Option } = Select; const JobSearchSelect = ( @@ -86,11 +87,9 @@ const JobSearchSelect = ( {`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${ o.ro_number || t("general.labels.na") - } | ${o.ownr_ln || ""} ${o.ownr_fn || ""} ${ - o.ownr_co_nm ? ` ${o.ownr_co_num}` : "" - }| ${o.v_model_yr || ""} ${o.v_make_desc || ""} ${ - o.v_model_desc || "" - }`} + } | ${OwnerNameDisplayFunction(o)} | ${ + o.v_model_yr || "" + } ${o.v_make_desc || ""} ${o.v_model_desc || ""}`} {o.status} diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index 4222addc2..7cac639e9 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -7,6 +7,7 @@ import { connect } from "react-redux"; import { Link, useHistory } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; +import { CANCEL_APPOINTMENTS_BY_JOB_ID } from "../../graphql/appointments.queries"; import { DELETE_JOB, UPDATE_JOB, VOID_JOB } from "../../graphql/jobs.queries"; import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { setModalContext } from "../../redux/modals/modals.actions"; @@ -56,6 +57,7 @@ export function JobsDetailHeaderActions({ const [deleteJob] = useMutation(DELETE_JOB); const [updateJob] = useMutation(UPDATE_JOB); const [voidJob] = useMutation(VOID_JOB); + const [cancelAllAppointments] = useMutation(CANCEL_APPOINTMENTS_BY_JOB_ID); const jobInProduction = useMemo(() => { return bodyshop.md_ro_statuses.production_statuses.includes(job.status); }, [job, bodyshop.md_ro_statuses.production_statuses]); @@ -121,6 +123,39 @@ export function JobsDetailHeaderActions({ > {t("jobs.actions.schedule")} + + e.stopPropagation()} + disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled} + onConfirm={async () => { + const jobUpdate = await cancelAllAppointments({ + variables: { + jobid: job.id, + job: { + date_scheduled: null, + scheduled_in: null, + scheduled_completion: null, + status: bodyshop.md_ro_statuses.default_imported, + }, + }, + }); + if (!jobUpdate.errors) { + notification["success"]({ + message: t("appointments.successes.canceled"), + }); + return; + } + }} + getPopupContainer={(trigger) => trigger.parentNode} + > + {t("menus.jobsactions.cancelallappointments")} + + diff --git a/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx b/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx index 0ad3cae94..330c0e5db 100644 --- a/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx +++ b/client/src/components/jobs-find-modal/jobs-find-modal.component.jsx @@ -4,6 +4,7 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import PhoneFormatter from "../../utils/PhoneFormatter"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function JobsFindModalComponent({ selectedJob, @@ -43,15 +44,12 @@ export default function JobsFindModalComponent({ render: (text, record) => { return record.owner ? ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + ) : ( - // t("jobs.errors.noowner") - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx index 2a6ea300b..68aa1b3c0 100644 --- a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx +++ b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx @@ -10,7 +10,7 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import StartChatButton from "../chat-open-button/chat-open-button.component"; - +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -52,14 +52,12 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { render: (text, record) => { return record.ownerid ? ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + ) : ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx index 6db18a3f5..627f2d8e6 100644 --- a/client/src/components/jobs-list/jobs-list.component.jsx +++ b/client/src/components/jobs-list/jobs-list.component.jsx @@ -18,6 +18,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { alphaSort } from "../../utils/sorters"; import AlertComponent from "../alert/alert.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -141,14 +142,12 @@ export function JobsList({ bodyshop }) { to={"/manage/owners/" + record.owner.id} onClick={(e) => e.stopPropagation()} > - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + ) : ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/owner-find-modal/owner-find-modal.container.jsx b/client/src/components/owner-find-modal/owner-find-modal.container.jsx index 7e59b1f85..e79a450cf 100644 --- a/client/src/components/owner-find-modal/owner-find-modal.container.jsx +++ b/client/src/components/owner-find-modal/owner-find-modal.container.jsx @@ -6,6 +6,7 @@ import { QUERY_SEARCH_OWNER_BY_IDX } from "../../graphql/owners.queries"; import AlertComponent from "../alert/alert.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import OwnerFindModalComponent from "./owner-find-modal.component"; +import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; export default function OwnerFindModalContainer({ loading, @@ -30,9 +31,7 @@ export default function OwnerFindModalContainer({ useEffect(() => { if (modalProps.visible && owner) { - const s = `${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${ - owner.ownr_co_nm || "" - }`; + const s = OwnerNameDisplayFunction(owner); setSearchText(s.trim()); callSearchowners({ variables: { search: s.trim() } }); diff --git a/client/src/components/owner-name-display/owner-name-display.component.jsx b/client/src/components/owner-name-display/owner-name-display.component.jsx new file mode 100644 index 000000000..e22065df1 --- /dev/null +++ b/client/src/components/owner-name-display/owner-name-display.component.jsx @@ -0,0 +1,47 @@ +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { store } from "../../redux/store"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(OwnerNameDisplay); + +export function OwnerNameDisplay({ bodyshop, ownerObject }) { + const emptyTest = + ownerObject.ownr_fn + ownerObject.ownr_ln + ownerObject.ownr_co_nm; + + if (!emptyTest || emptyTest === "null" || emptyTest.trim() === "") + return "N/A"; + + if (bodyshop.last_name_first) + return `${ownerObject.ownr_ln || ""}, ${ownerObject.ownr_fn || ""} ${ + ownerObject.ownr_co_nm || "" + }`.trim(); + + return `${ownerObject.ownr_fn || ""} ${ownerObject.ownr_ln || ""} ${ + ownerObject.ownr_co_nm || "" + }`.trim(); +} + +export function OwnerNameDisplayFunction(ownerObject) { + const emptyTest = + ownerObject.ownr_fn + ownerObject.ownr_ln + ownerObject.ownr_co_nm; + + if (!emptyTest || emptyTest === "null" || emptyTest.trim() === "") + return "N/A"; + + const rdxStore = store.getState(); + + if (rdxStore.user.bodyshop.last_name_first) + return `${ownerObject.ownr_ln || ""}, ${ownerObject.ownr_fn || ""} ${ + ownerObject.ownr_co_nm || "" + }`.trim(); + + return `${ownerObject.ownr_fn || ""} ${ownerObject.ownr_ln || ""} ${ + ownerObject.ownr_co_nm || "" + }`.trim(); +} diff --git a/client/src/components/owner-search-select/owner-search-select.component.jsx b/client/src/components/owner-search-select/owner-search-select.component.jsx index bd543dfbd..85e4d9833 100644 --- a/client/src/components/owner-search-select/owner-search-select.component.jsx +++ b/client/src/components/owner-search-select/owner-search-select.component.jsx @@ -8,6 +8,7 @@ import { SEARCH_OWNERS_FOR_AUTOCOMPLETE, } from "../../graphql/owners.queries"; import AlertComponent from "../alert/alert.component"; +import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; const { Option } = Select; @@ -16,10 +17,8 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => { SEARCH_OWNERS_FOR_AUTOCOMPLETE ); - const [ - callIdSearch, - { loading: idLoading, error: idError, data: idData }, - ] = useLazyQuery(SEARCH_OWNERS_BY_ID_FOR_AUTOCOMPLETE); + const [callIdSearch, { loading: idLoading, error: idError, data: idData }] = + useLazyQuery(SEARCH_OWNERS_BY_ID_FOR_AUTOCOMPLETE); const executeSearch = (v) => { callSearch(v); @@ -78,9 +77,7 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => { {theOptions ? theOptions.map((o) => ( )) : null} diff --git a/client/src/components/owner-tag-popover/owner-tag-popover.component.jsx b/client/src/components/owner-tag-popover/owner-tag-popover.component.jsx index 4c5726b6f..b94e576b4 100644 --- a/client/src/components/owner-tag-popover/owner-tag-popover.component.jsx +++ b/client/src/components/owner-tag-popover/owner-tag-popover.component.jsx @@ -3,6 +3,10 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import PhoneFormatter from "../../utils/PhoneFormatter"; +import OwnerNameDisplay, { + OwnerNameDisplayFunction, +} from "../owner-name-display/owner-name-display.component"; + export default function OwnerTagPopoverComponent({ job }) { const { t } = useTranslation(); const content = ( @@ -10,9 +14,9 @@ export default function OwnerTagPopoverComponent({ job }) { - {`${ - job.ownr_fn || "" - } ${job.ownr_ln || ""} ${job.ownr_co_nm || ""}`} + + + {job.ownr_ph1 || ""} @@ -31,11 +35,9 @@ export default function OwnerTagPopoverComponent({ job }) { - {`${ - job.owner.ownr_fn || "" - } ${job.owner.ownr_ln || ""} ${ - job.owner.ownr_co_nm || "" - }`} + + + {job.owner.ownr_ph1 || ""} @@ -68,9 +70,7 @@ export default function OwnerTagPopoverComponent({ job }) { - {job.owner - ? `${job.ownr_co_nm || ""}${job.ownr_fn || ""} ${job.ownr_ln || ""}` - : t("jobs.errors.noowner")} + {job.owner ? OwnerNameDisplayFunction(job) : t("jobs.errors.noowner")} diff --git a/client/src/components/owners-list/owners-list.component.jsx b/client/src/components/owners-list/owners-list.component.jsx index f6e1c3401..78e2c3cb3 100644 --- a/client/src/components/owners-list/owners-list.component.jsx +++ b/client/src/components/owners-list/owners-list.component.jsx @@ -5,6 +5,7 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { Link, useHistory, useLocation } from "react-router-dom"; import PhoneFormatter from "../../utils/PhoneFormatter"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function OwnersListComponent({ loading, @@ -33,9 +34,7 @@ export default function OwnersListComponent({ key: "name", render: (text, record) => ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} + ), }, diff --git a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx index fd5cf5b22..2ce99d870 100644 --- a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx +++ b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx @@ -14,6 +14,7 @@ import { alphaSort } from "../../utils/sorters"; import { TemplateList } from "../../utils/TemplateConstants"; import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container"; import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test"); @@ -78,14 +79,12 @@ export function PaymentsListPaginated({ render: (text, record) => { return record.job.owner ? ( - {`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${ - record.job.ownr_co_nm || "" - }`} + ) : ( - {`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${ - record.job.ownr_co_nm || "" - }`} + + + ); }, }, diff --git a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx index 68f15e79c..0f56e25f3 100644 --- a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx +++ b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx @@ -13,6 +13,7 @@ import ProductionListColumnProductionNote from "../production-list-columns/produ import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component"; import "./production-board-card.styles.scss"; import moment from "moment"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; export default function ProductionBoardCard( technician, @@ -87,9 +88,9 @@ export default function ProductionBoardCard( card.ownr_co_nm || "" }`} ) : ( -
{`${card.ownr_ln || ""}, ${ - card.ownr_fn || "" - } ${card.ownr_co_nm || ""}`}
+
+ +
)} )} diff --git a/client/src/components/production-list-columns/production-list-columns.data.js b/client/src/components/production-list-columns/production-list-columns.data.js index 5a73e2629..659c753d9 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.js +++ b/client/src/components/production-list-columns/production-list-columns.data.js @@ -22,6 +22,7 @@ import ProductionListColumnCategory from "./production-list-columns.status.categ import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component"; import ProductionListColumnComment from "./production-list-columns.comment.component"; import ProductionListColumnPartsReceived from "./production-list-columns.partsreceived.component"; +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const r = ({ technician, state, activeStatuses, bodyshop }) => { return [ @@ -68,11 +69,7 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => { dataIndex: "ownr", key: "ownr", ellipsis: true, - render: (text, record) => ( - {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ - record.ownr_co_nm || "" - }`} - ), + render: (text, record) => , sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), sortOrder: state.sortedInfo.columnKey === "ownr" && state.sortedInfo.order, diff --git a/client/src/components/production-list-detail/production-list-detail.component.jsx b/client/src/components/production-list-detail/production-list-detail.component.jsx index 9494d5fb2..ac0ae9dc8 100644 --- a/client/src/components/production-list-detail/production-list-detail.component.jsx +++ b/client/src/components/production-list-detail/production-list-detail.component.jsx @@ -17,7 +17,7 @@ import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import ProductionRemoveButton from "../production-remove-button/production-remove-button.component"; import JobAtChange from "../job-at-change/job-at-change.component"; import { PrinterFilled } from "@ant-design/icons"; - +import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { setModalContext } from "../../redux/modals/modals.actions"; @@ -107,9 +107,7 @@ export function ProductionListDetail({ jobs, setPrintCenterContext }) { {theJob.ins_co_nm || ""} - {`${theJob.ownr_fn || ""} ${theJob.ownr_ln || ""} ${ - theJob.ownr_co_nm || "" - }`} + {j.ro_number} - {`${j.ownr_fn || ""} ${j.ownr_ln || ""} ${ - j.ownr_co_nm || "" - }`} + {`${j.v_model_yr || ""} ${j.v_make_desc || ""} ${ j.v_model_desc || "" }`} diff --git a/client/src/components/shop-info/shop-info.general.component.jsx b/client/src/components/shop-info/shop-info.general.component.jsx index b5790a29c..9bcf9ccaa 100644 --- a/client/src/components/shop-info/shop-info.general.component.jsx +++ b/client/src/components/shop-info/shop-info.general.component.jsx @@ -520,7 +520,6 @@ export default function ShopInfoGeneral({ form }) { > -