From d7afe7e43f9bcada2219ab38586f69334ea7e9bb Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 18 Mar 2020 14:31:33 -0700 Subject: [PATCH] BOD-10 BOD-12 BOD-11 WIP for Manual Job Creation. --- bodyshop_translations.babel | 89 +++++++++ .../invoice-enter-modal.container.jsx | 16 -- .../jobs-create-vehicle-info.component.jsx | 43 +++++ .../jobs-create-vehicle-info.container.jsx | 19 ++ ...jobs-create-vehicle-info.new.component.jsx | 179 ++++++++++++++++++ ...s-create-vehicle-info.search.component.jsx | 118 ++++++++++++ .../jobs-documents-gallery.component.jsx | 28 +-- client/src/graphql/vehicles.queries.js | 30 +++ .../jobs-create/jobs-create.component.jsx | 76 ++++++++ .../jobs-create/jobs-create.container.jsx | 36 ++++ .../pages/jobs-create/jobs-create.context.js | 3 + .../pages/manage/manage.page.component.jsx | 25 ++- client/src/translations/en_us/common.json | 6 + client/src/translations/es/common.json | 6 + client/src/translations/fr/common.json | 6 + 15 files changed, 643 insertions(+), 37 deletions(-) create mode 100644 client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.component.jsx create mode 100644 client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.container.jsx create mode 100644 client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx create mode 100644 client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.search.component.jsx create mode 100644 client/src/pages/jobs-create/jobs-create.component.jsx create mode 100644 client/src/pages/jobs-create/jobs-create.container.jsx create mode 100644 client/src/pages/jobs-create/jobs-create.context.js diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index f6c1ca8f4..274cca523 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -6670,6 +6670,95 @@ + + create + + + jobinfo + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + newvehicle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + ownerinfo + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + vehicleinfo + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + creating_new_job false diff --git a/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx b/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx index 38103e825..e7dd2b4ec 100644 --- a/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx +++ b/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx @@ -72,22 +72,6 @@ function InvoiceEnterModalContainer({ }; const handleFinish = values => { - console.log("values", values); - console.log( - "Assigned", - Object.assign( - {}, - values, - { jobid: roSearch.selectedId }, - { vendorid: vendorSearch.selectedId }, - { - invoicelines: { - data: values.invoicelines.map(item => delete item.joblinename) - } - } - ) - ); - insertInvoice({ variables: { invoice: [ diff --git a/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.component.jsx b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.component.jsx new file mode 100644 index 000000000..15e56eb48 --- /dev/null +++ b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.component.jsx @@ -0,0 +1,43 @@ +import { Checkbox, Col, Row, Typography } from "antd"; +import React, { useContext } from "react"; +import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; +import { useTranslation } from "react-i18next"; +import JobsCreateVehicleInfoNewComponent from "./jobs-create-vehicle-info.new.component"; +import JobsCreateVehicleInfoSearchComponent from "./jobs-create-vehicle-info.search.component"; + +export default function JobsCreateVehicleInfoComponent({ loading, vehicles }) { + const [state, setState] = useContext(JobCreateContext); + const { t } = useTranslation(); + return ( +
+ {t("jobs.labels.create.vehicleinfo")} + + + + + + { + setState({ + ...state, + vehicle: { + ...state.vehicle, + new: !state.vehicle.new, + selectedid: null + } + }); + }} + > + {t("jobs.labels.create.newvehicle")} + + + + +
+ ); +} diff --git a/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.container.jsx b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.container.jsx new file mode 100644 index 000000000..084f4f73b --- /dev/null +++ b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.container.jsx @@ -0,0 +1,19 @@ +import React, { useContext } from "react"; +import JobsCreateVehicleInfoComponent from "./jobs-create-vehicle-info.component"; +import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; + +import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries"; +import { useQuery } from "react-apollo"; +export default function JobsCreateVehicleInfoContainer({ form }) { + const [state, setState] = useContext(JobCreateContext); + const { loading, error, data } = useQuery(SEARCH_VEHICLE_BY_VIN, { + variables: { vin: `%${state.vehicle.search}%` }, + skip: !state.vehicle.search + }); + return ( + + ); +} diff --git a/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx new file mode 100644 index 000000000..17cf1727d --- /dev/null +++ b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.new.component.jsx @@ -0,0 +1,179 @@ +import { DatePicker, Form, Input } from "antd"; +import React, { useContext } from "react"; +import { useTranslation } from "react-i18next"; +import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; + +export default function JobsCreateVehicleInfoNewComponent() { + const [state] = useContext(JobCreateContext); + + const { t } = useTranslation(); + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + { + //TODO Add handling for paint code json + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.search.component.jsx b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.search.component.jsx new file mode 100644 index 000000000..57988a6df --- /dev/null +++ b/client/src/components/jobs-create-vehicle-info/jobs-create-vehicle-info.search.component.jsx @@ -0,0 +1,118 @@ +import React, { useContext, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Table, Input } from "antd"; +import { Link } from "react-router-dom"; +import { alphaSort } from "../../utils/sorters"; +import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; + +export default function JobsCreateVehicleInfoSearchComponent({ + loading, + vehicles +}) { + const [state, setState] = useContext(JobCreateContext); + const [tableState, setTableState] = useState({ + sortedInfo: {}, + filteredInfo: { text: "" } + }); + + const { t } = useTranslation(); + + const columns = [ + { + title: t("vehicles.fields.v_vin"), + dataIndex: "v_vin", + key: "v_vin", + sorter: (a, b) => alphaSort(a.v_vin, b.v_vin), + sortOrder: + tableState.sortedInfo.columnKey === "v_vin" && + tableState.sortedInfo.order, + render: (text, record) => ( + {record.v_vin} + ) + }, + { + title: t("vehicles.fields.description"), + dataIndex: "description", + key: "description", + render: (text, record) => { + return ( + {`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc} ${record.v_color}`} + ); + } + }, + { + title: t("vehicles.fields.plate_no"), + dataIndex: "plate", + key: "plate", + render: (text, record) => { + return {`${record.plate_st} | ${record.plate_no}`}; + } + } + ]; + + const handleTableChange = (pagination, filters, sorter) => { + setTableState({ ...tableState, filteredInfo: filters, sortedInfo: sorter }); + }; + //TODO Implement searching & pagination + + console.log("vehicles", vehicles); + return ( + { + return ( + { + setState({ + ...state, + vehicle: { ...state.vehicle, search: value } + }); + }} + enterButton + /> + ); + }} + size="small" + pagination={{ position: "top" }} + columns={columns.map(item => ({ ...item }))} + rowKey="id" + dataSource={vehicles} + onChange={handleTableChange} + rowSelection={{ + onSelect: props => { + setState({ + ...state, + vehicle: { ...state.vehicle, new: false, selectedid: props.id } + }); + }, + type: "radio", + selectedRowKeys: [state.vehicle.selectedid] + }} + onRow={(record, rowIndex) => { + return { + onClick: event => { + if (record) { + if (record.id) { + setState({ + ...state, + vehicle: { + ...state.vehicle, + new: false, + selectedid: record.id + } + }); + console.log("Should be clearing fields."); + return; + } + } + setState({ + ...state, + vehicle: { ...state.vehicle, selectedid: null } + }); + } + }; + }} + /> + ); +} diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index 04e80feda..44de66731 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -1,13 +1,13 @@ import axios from "axios"; import React, { useEffect, useState } from "react"; import Gallery from "react-grid-gallery"; -import { Document, Page, pdfjs } from "react-pdf"; +//import { Document, Page, pdfjs } from "react-pdf"; import DocumentsUploadContainer from "../documents-upload/documents-upload.container"; -import LoadingSpinner from "../loading-spinner/loading-spinner.component"; +//import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import { Collapse } from "antd"; import { useTranslation } from "react-i18next"; -pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf.worker.min.js`; +//pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.1.266/pdf.worker.min.js`; function JobsDocumentsComponent({ data, jobId, refetch }) { const [galleryImages, setgalleryImages] = useState([]); @@ -87,16 +87,18 @@ function JobsDocumentsComponent({ data, jobId, refetch }) { }} > - - {pdfDocuments.map((doc, idx) => ( - } file={doc.src}> - - - ))} - + { + // + // {pdfDocuments.map((doc, idx) => ( + // } file={doc.src}> + // + // + // ))} + // + } ); diff --git a/client/src/graphql/vehicles.queries.js b/client/src/graphql/vehicles.queries.js index 5efbad1c9..571462b01 100644 --- a/client/src/graphql/vehicles.queries.js +++ b/client/src/graphql/vehicles.queries.js @@ -70,3 +70,33 @@ export const QUERY_ALL_VEHICLES = gql` } } `; + +export const SEARCH_VEHICLE_BY_VIN = gql` + query SEARCH_VEHICLE_BY_VIN($vin: String!) { + vehicles(where: { v_vin: { _ilike: $vin } }) { + id + plate_no + plate_st + v_vin + v_model_yr + v_model_desc + v_make_desc + v_color + v_bstyle + updated_at + v_type + v_trimcode + v_tone + v_stage + v_prod_dt + v_paint_codes + v_options + v_mldgcode + v_makecode + v_engine + v_cond + trim_color + db_v_code + } + } +`; diff --git a/client/src/pages/jobs-create/jobs-create.component.jsx b/client/src/pages/jobs-create/jobs-create.component.jsx new file mode 100644 index 000000000..59495f367 --- /dev/null +++ b/client/src/pages/jobs-create/jobs-create.component.jsx @@ -0,0 +1,76 @@ +import { Button, message, Steps } from "antd"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import JobsCreateVehicleInfoContainer from "../../components/jobs-create-vehicle-info/jobs-create-vehicle-info.container"; + +export default function JobsCreateComponent({ form }) { + const [pageIndex, setPageIndex] = useState(0); + const { t } = useTranslation(); + const steps = [ + { + title: t("jobs.labels.create.vehicleinfo"), + content: + }, + { + title: t("jobs.labels.create.ownerinfo"), + content: "Second-content" + }, + { + title: t("jobs.labels.create.jobinfo"), + content: "Last-content" + } + ]; + + const next = () => { + setPageIndex(pageIndex + 1); + }; + const prev = () => { + setPageIndex(pageIndex - 1); + }; + + const { Step } = Steps; + return ( +
+ + {steps.map((item, idx) => ( + { + setPageIndex(idx); + }} + /> + ))} + + + {steps.map((item, idx) => ( +
+ {item.content} +
+ ))} + +
+ {pageIndex > 0 && ( + + )} + {pageIndex < steps.length - 1 && ( + + )} + {pageIndex === steps.length - 1 && ( + + )} +
+
+ ); +} diff --git a/client/src/pages/jobs-create/jobs-create.container.jsx b/client/src/pages/jobs-create/jobs-create.container.jsx new file mode 100644 index 000000000..323a03c96 --- /dev/null +++ b/client/src/pages/jobs-create/jobs-create.container.jsx @@ -0,0 +1,36 @@ +import React, { useState } from "react"; +import JobsCreateComponent from "./jobs-create.component"; +import { Form } from "antd"; +import JobCreateContext from "./jobs-create.context"; +export default function JobsCreateContainer() { + const [form] = Form.useForm(); + + const contextState = useState({ + vehicle: { new: false, search: "", selectedid: null }, + owner: { new: false }, + job: null + }); + + const [state, setState] = contextState; + + const handleFinish = values => { + console.log("Form Values", values); + //const vehicleSpread = state.vehicle.selectedid ? {vehicleid: state.vehicle.selectedid} : {vehicle: {data: { ...values.vehicle} } + const job = Object.assign( + {}, + { + vehicle: state.vehicle.selectedid ? null : values.vehicle, + vehicleid: state.vehicle.selectedid || null + } + ); + console.log("Job To Save", job); + }; + + return ( + +
+ + +
+ ); +} diff --git a/client/src/pages/jobs-create/jobs-create.context.js b/client/src/pages/jobs-create/jobs-create.context.js new file mode 100644 index 000000000..52f2f0a9e --- /dev/null +++ b/client/src/pages/jobs-create/jobs-create.context.js @@ -0,0 +1,3 @@ +import React from "react"; +const JobCreateContext = React.createContext(null); +export default JobCreateContext; diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index f12db8762..5f4567c70 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -1,7 +1,7 @@ import { BackTop, Layout } from "antd"; import React, { lazy, Suspense, useEffect } from "react"; import { useTranslation } from "react-i18next"; -import { Route } from "react-router"; +import { Route, Switch } from "react-router-dom"; import ErrorBoundary from "../../components/error-boundary/error-boundary.component"; import FooterComponent from "../../components/footer/footer.component"; //Component Imports @@ -40,14 +40,15 @@ const ShopPage = lazy(() => import("../shop/shop.page.component")); const ShopVendorPageContainer = lazy(() => import("../shop-vendor/shop-vendor.page.container") ); - const EmailOverlayContainer = lazy(() => import("../../components/email-overlay/email-overlay.container.jsx") ); - const GlobalLoadingBar = lazy(() => import("../../components/global-loading-bar/global-loading-bar.component") ); +const JobsCreateContainerPage = lazy(() => + import("../jobs-create/jobs-create.container") +); const { Header, Content, Footer } = Layout; @@ -78,11 +79,19 @@ export default function Manage({ match }) { - + + + + +