diff --git a/client/src/components/job-detail-cards/job-detail-cards.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.component.jsx index 09aadf4c9..a869e5eac 100644 --- a/client/src/components/job-detail-cards/job-detail-cards.component.jsx +++ b/client/src/components/job-detail-cards/job-detail-cards.component.jsx @@ -1,6 +1,6 @@ import { PrinterFilled } from "@ant-design/icons"; import { useQuery } from "@apollo/client"; -import { Button, Card, Drawer, Grid, PageHeader, Space, Tag } from "antd"; +import { Button, Card, Col, Divider, Drawer, Grid, Row, Space } from "antd"; import queryString from "query-string"; import React from "react"; import { useTranslation } from "react-i18next"; @@ -9,9 +9,8 @@ import { Link, useHistory, useLocation } from "react-router-dom"; import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries"; import { setModalContext } from "../../redux/modals/modals.actions"; import AlertComponent from "../alert/alert.component"; +import JobsDetailHeader from "../jobs-detail-header/jobs-detail-header.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; -import OwnerTagPopoverComponent from "../owner-tag-popover/owner-tag-popover.component"; -import VehicleTagPopoverComponent from "../vehicle-tag-popover/vehicle-tag-popover.component"; import JobDetailCardsDamageComponent from "./job-detail-cards.damage.component"; import JobDetailCardsDatesComponent from "./job-detail-cards.dates.component"; import JobDetailCardsDocumentsComponent from "./job-detail-cards.documents.component"; @@ -25,6 +24,12 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(setModalContext({ context: context, modal: "printCenter" })), }); +const span = { + sm: { span: 24 }, + md: { span: 12 }, + lg: { span: 8 }, +}; + export function JobDetailCards({ setPrintCenterContext }) { const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) .filter((screen) => !!screen[1]) @@ -34,9 +39,9 @@ export function JobDetailCards({ setPrintCenterContext }) { xs: "100%", sm: "100%", md: "100%", - lg: "50%", - xl: "50%", - xxl: "45%", + lg: "75%", + xl: "75%", + xxl: "60%", }; const drawerPercentage = selectedBreakpoint ? bpoints[selectedBreakpoint[0]] @@ -46,7 +51,6 @@ export function JobDetailCards({ setPrintCenterContext }) { const { selected } = searchParams; const history = useHistory(); const { loading, error, data, refetch } = useQuery(QUERY_JOB_CARD_DETAILS, { - fetchPolicy: "network-only", variables: { id: selected }, skip: !selected, }); @@ -60,10 +64,7 @@ export function JobDetailCards({ setPrintCenterContext }) { }), }); }; - const gridStyle = { - width: "25%", - textAlign: "center", - }; + return ( : null} {error ? : null} {data ? ( - , - , - - {t("jobs.labels.inproduction")} - , - ]} - subTitle={data.jobs_by_pk.status} - > - - {data.jobs_by_pk.ro_number || t("general.labels.na")} + + {data.jobs_by_pk.ro_number || t("general.labels.na")} + + } + extra={ + + + + - } - extra={ - - - - - - - } - > - - - - - - - - - - - - - - - - - - - - - - - + + } + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) : null} ); diff --git a/client/src/components/production-list-columns/production-list-columns.add.component.jsx b/client/src/components/production-list-columns/production-list-columns.add.component.jsx index 936794fd5..8e47110a7 100644 --- a/client/src/components/production-list-columns/production-list-columns.add.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.add.component.jsx @@ -23,7 +23,7 @@ export function ProductionColumnsComponent({ columnState, technician }) { const { t } = useTranslation(); const handleAdd = (e) => { - setColumns([...columns, ...dataSource.filter((i) => i.key === e.key)]); + setColumns([...columns, ...dataSource({technician}).filter((i) => i.key === e.key)]); }; const columnKeys = columns.map((i) => i.key); 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 d70cc31bd..98e5ba2a0 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 @@ -10,6 +10,7 @@ import ProductionListColumnAlert from "./production-list-columns.alert.component import ProductionListColumnBodyPriority from "./production-list-columns.bodypriority.component"; import ProductionListDate from "./production-list-columns.date.component"; import ProductionListColumnDetailPriority from "./production-list-columns.detailpriority.component"; +import ProductionListEmployeeAssignment from "./production-list-columns.empassignment.component"; import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component"; import ProductionListColumnNote from "./production-list-columns.productionnote.component"; import ProductionListColumnStatus from "./production-list-columns.status.component"; @@ -249,6 +250,39 @@ const r = ({ technician }) => { ), }, + { + title: i18n.t("jobs.fields.employee_body"), + dataIndex: "employee_body", + key: "employee_body", + render: (text, record) => ( + + ), + }, + { + title: i18n.t("jobs.fields.employee_prep"), + dataIndex: "employee_prep", + key: "employee_prep", + render: (text, record) => ( + + ), + }, + { + title: i18n.t("jobs.fields.employee_refinish"), + dataIndex: "employee_refinish", + key: "employee_refinish", + render: (text, record) => ( + + ), + }, ]; }; export default r; diff --git a/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx b/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx new file mode 100644 index 000000000..c7d47b14e --- /dev/null +++ b/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx @@ -0,0 +1,170 @@ +import { DeleteFilled, PlusCircleFilled } from "@ant-design/icons"; +import { useMutation } from "@apollo/client"; +import { + Button, + Col, + notification, + Popover, + Row, + Select, + Space, + Spin, +} from "antd"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { logImEXEvent } from "../../firebase/firebase.utils"; +import { UPDATE_JOB } from "../../graphql/jobs.queries"; +import { selectBodyshop } from "../../redux/user/user.selectors"; + +const iconStyle = { marginLeft: ".3rem" }; +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop, +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); + +export function ProductionListEmpAssignment({ bodyshop, record, type }) { + const { t } = useTranslation(); + const [updateJob] = useMutation(UPDATE_JOB); + const [loading, setLoading] = useState(false); + + const handleAdd = async (assignment) => { + setLoading(true); + const { operation, employeeid } = assignment; + logImEXEvent("job_assign_employee", { operation }); + + let empAssignment = determineFieldName(operation); + + const result = await updateJob({ + variables: { jobId: record.id, job: { [empAssignment]: employeeid } }, + + awaitRefetchQueries: true, + }); + + if (!!result.errors) { + notification["error"]({ + message: t("jobs.errors.assigning", { + message: JSON.stringify(result.errors), + }), + }); + } + setLoading(false); + }; + const handleRemove = async (operation) => { + setLoading(true); + logImEXEvent("job_unassign_employee", { operation }); + + let empAssignment = determineFieldName(operation); + const result = await updateJob({ + variables: { jobId: record.id, job: { [empAssignment]: null } }, + + awaitRefetchQueries: true, + }); + + if (!!result.errors) { + notification["error"]({ + message: t("jobs.errors.assigning", { + message: JSON.stringify(result.errors), + }), + }); + } + setLoading(false); + }; + + const [assignment, setAssignment] = useState({ + operation: null, + employeeid: null, + }); + + const [visibility, setVisibility] = useState(false); + const onChange = (e) => { + setAssignment({ ...assignment, employeeid: e }); + }; + + const popContent = ( + + + + + + + + + + + + ); + + return ( + + + {record[type] ? ( +
+ {`${record[type].first_name || ""} ${ + record[type].last_name || "" + }`} + handleRemove(type)} + /> +
+ ) : ( + { + setAssignment({ operation: type }); + setVisibility(true); + }} + /> + )} +
+
+ ); +} + +const determineFieldName = (operation) => { + switch (operation) { + case "employee_body_rel": + return "employee_body"; + case "employee_prep_rel": + return "employee_prep"; + case "employee_refinish_rel": + return "employee_refinish"; + + default: + return null; + } +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ProductionListEmpAssignment); diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx index 599531593..544b30ce6 100644 --- a/client/src/components/production-list-table/production-list-table.component.jsx +++ b/client/src/components/production-list-table/production-list-table.component.jsx @@ -175,7 +175,7 @@ export function ProductionListTable({ rowKey="id" loading={loading} dataSource={dataSource} - scrol={{ x: true }} + // scroll={{ x: true }} onChange={handleTableChange} />