From 71bd8df20865537421d01075f19997f4b2f28bb2 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Fri, 7 Feb 2020 11:55:37 -0800 Subject: [PATCH] Added vehicle detail form. --- bodyshop_translations.babel | 425 ++++++++++++++++++ .../reset-form-item.component.jsx | 21 + .../loading-spinner.component.jsx | 7 +- .../loading-spinner.styles.scss | 1 - .../vehicle-detail-form.component.jsx | 119 +++++ .../vehicle-detail-form.container.jsx | 46 ++ client/src/graphql/vehicles.queries.js | 10 + .../jobs-detail.page.component.jsx | 28 +- .../pages/manage/manage.page.container.jsx | 2 +- client/src/pages/manage/manage.page.jsx | 8 +- .../vehicles-detail.page.component.jsx | 6 +- .../vehicles-detail.page.container.jsx | 6 +- client/src/translations/en_us/common.json | 24 +- client/src/translations/es/common.json | 24 +- client/src/translations/fr/common.json | 24 +- 15 files changed, 712 insertions(+), 39 deletions(-) create mode 100644 client/src/components/form-items-formatted/reset-form-item.component.jsx create mode 100644 client/src/components/vehicle-detail-form/vehicle-detail-form.component.jsx create mode 100644 client/src/components/vehicle-detail-form/vehicle-detail-form.container.jsx diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 1b4f239ba..fbee58836 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -5141,6 +5141,431 @@ + + plate_st + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + trim_color + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_bstyle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_color + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_cond + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_engine + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_make_desc + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_makecode + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_mldgcode + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_model_desc + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_model_yr + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_options + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_paint_codes + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_prod_dt + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_stage + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_tone + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_trimcode + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_type + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + v_vin + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + successes + + + save + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + diff --git a/client/src/components/form-items-formatted/reset-form-item.component.jsx b/client/src/components/form-items-formatted/reset-form-item.component.jsx new file mode 100644 index 000000000..b0ef84a84 --- /dev/null +++ b/client/src/components/form-items-formatted/reset-form-item.component.jsx @@ -0,0 +1,21 @@ +import { Button } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import AlertComponent from "../alert/alert.component"; + +export default function ResetForm({ resetFields }) { + const { t } = useTranslation(); + return ( + + {t("general.messages.unsavedchanges")} + + + } + closable + /> + ); +} diff --git a/client/src/components/loading-spinner/loading-spinner.component.jsx b/client/src/components/loading-spinner/loading-spinner.component.jsx index 550499569..b37665fd8 100644 --- a/client/src/components/loading-spinner/loading-spinner.component.jsx +++ b/client/src/components/loading-spinner/loading-spinner.component.jsx @@ -6,10 +6,13 @@ export default function LoadingSpinner({ loading = true, message, ...props }) { return ( {props.children} diff --git a/client/src/components/loading-spinner/loading-spinner.styles.scss b/client/src/components/loading-spinner/loading-spinner.styles.scss index d057f91ad..598a332cb 100644 --- a/client/src/components/loading-spinner/loading-spinner.styles.scss +++ b/client/src/components/loading-spinner/loading-spinner.styles.scss @@ -1,3 +1,2 @@ .loading-spinner { - text-align: center; } diff --git a/client/src/components/vehicle-detail-form/vehicle-detail-form.component.jsx b/client/src/components/vehicle-detail-form/vehicle-detail-form.component.jsx new file mode 100644 index 000000000..a411dc642 --- /dev/null +++ b/client/src/components/vehicle-detail-form/vehicle-detail-form.component.jsx @@ -0,0 +1,119 @@ +import { Button, DatePicker, Form, Input } from "antd"; +import moment from "moment"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import ResetForm from "../form-items-formatted/reset-form-item.component"; +export default function VehicleDetailFormComponent({ vehicle, form }) { + const { t } = useTranslation(); + const { isFieldsTouched, resetFields, getFieldDecorator } = form; + + return ( +
+ {isFieldsTouched() ? : null} + + The Form + + {getFieldDecorator("v_vin", { + initialValue: vehicle.v_vin + })()} + + + {getFieldDecorator("plate_no", { + initialValue: vehicle.plate_no + })()} + + + {getFieldDecorator("plate_st", { + initialValue: vehicle.plate_st + })()} + + + {getFieldDecorator("v_type", { + initialValue: vehicle.v_type + })()} + + + {getFieldDecorator("v_trimcode", { + initialValue: vehicle.v_trimcode + })()} + + + {getFieldDecorator("v_tone", { + initialValue: vehicle.v_tone + })()} + + + {getFieldDecorator("v_stage", { + initialValue: vehicle.v_stage + })()} + + + {getFieldDecorator("v_prod_dt", { + initialValue: vehicle.v_prod_dt ? moment(vehicle.v_prod_dt) : null + })()} + + + {getFieldDecorator("v_paint_codes", { + initialValue: JSON.stringify(vehicle.v_paint_codes) + })()} + + + {getFieldDecorator("v_options", { + initialValue: vehicle.v_options + })()} + + + {getFieldDecorator("v_model_yr", { + initialValue: vehicle.v_model_yr + })()} + + + {getFieldDecorator("v_model_desc", { + initialValue: vehicle.v_model_desc + })()} + + + {getFieldDecorator("v_mldgcode", { + initialValue: vehicle.v_mldgcode + })()} + + + {getFieldDecorator("v_makecode", { + initialValue: vehicle.v_makecode + })()} + + + {getFieldDecorator("v_make_desc", { + initialValue: vehicle.v_make_desc + })()} + + + {getFieldDecorator("v_engine", { + initialValue: vehicle.v_engine + })()} + + + {getFieldDecorator("v_cond", { + initialValue: vehicle.v_cond + })()} + + + {getFieldDecorator("v_color", { + initialValue: vehicle.v_color + })()} + + + {getFieldDecorator("v_bstyle", { + initialValue: vehicle.v_bstyle + })()} + + + {getFieldDecorator("trim_color", { + initialValue: vehicle.trim_color + })()} + +
+ ); +} diff --git a/client/src/components/vehicle-detail-form/vehicle-detail-form.container.jsx b/client/src/components/vehicle-detail-form/vehicle-detail-form.container.jsx new file mode 100644 index 000000000..d5ccacd26 --- /dev/null +++ b/client/src/components/vehicle-detail-form/vehicle-detail-form.container.jsx @@ -0,0 +1,46 @@ +import React from "react"; +import { Form, notification } from "antd"; +import { useMutation } from "react-apollo"; +import VehicleDetailFormComponent from "./vehicle-detail-form.component"; +import { useTranslation } from "react-i18next"; +import { UPDATE_VEHICLE } from "../../graphql/vehicles.queries"; + +function VehicleDetailFormContainer({ form, vehicle, refetch }) { + const { t } = useTranslation(); + const [updateVehicle] = useMutation(UPDATE_VEHICLE); + + const handleSubmit = e => { + e.preventDefault(); + + form.validateFieldsAndScroll((err, values) => { + if (err) { + notification["error"]({ + message: t("vehicles.errors.validationtitle"), + description: t("vehicles.errors.validation") + }); + } + if (!err) { + updateVehicle({ + variables: { vehId: vehicle.id, vehicle: values } + }).then(r => { + notification["success"]({ + message: t("vehicles.successes.save") + }); + //TODO: Better way to reset the field decorators? + if (refetch) refetch().then(); + form.resetFields(); + }); + } + }); + }; + + return ( +
+ + + ); +} + +export default Form.create({ name: "VehicleDetailFormContainer" })( + VehicleDetailFormContainer +); diff --git a/client/src/graphql/vehicles.queries.js b/client/src/graphql/vehicles.queries.js index 1894f09ef..0e74c6a83 100644 --- a/client/src/graphql/vehicles.queries.js +++ b/client/src/graphql/vehicles.queries.js @@ -36,3 +36,13 @@ export const QUERY_VEHICLE_BY_ID = gql` } } `; + +export const UPDATE_VEHICLE = gql` + mutation UPDATE_VEHICLE($vehId: uuid!, $vehicle: vehicles_set_input!) { + update_vehicles(where: { id: { _eq: $vehId } }, _set: $vehicle) { + returning { + id + } + } + } +`; diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index f64230b64..bf04307a2 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -1,22 +1,18 @@ -import { Alert, Button, Form, Icon, Tabs } from "antd"; +import { Form, Icon, Tabs } from "antd"; import React, { useContext } from "react"; import { useTranslation } from "react-i18next"; -import { - FaHardHat, - FaInfo, - FaRegStickyNote, - FaShieldAlt -} from "react-icons/fa"; +import { FaHardHat, FaInfo, FaRegStickyNote, FaShieldAlt } from "react-icons/fa"; +import ResetForm from "../../components/form-items-formatted/reset-form-item.component"; import JobsLinesContainer from "../../components/job-detail-lines/job-lines.container"; import JobsDetailClaims from "../../components/jobs-detail-claims/jobs-detail-claims.component"; +import JobsDetailDatesComponent from "../../components/jobs-detail-dates/jobs-detail-dates.component"; import JobsDetailFinancials from "../../components/jobs-detail-financial/jobs-detail-financial.component"; import JobsDetailHeader from "../../components/jobs-detail-header/jobs-detail-header.component"; import JobsDetailInsurance from "../../components/jobs-detail-insurance/jobs-detail-insurance.component"; import JobsDocumentsContainer from "../../components/jobs-documents/jobs-documents.container"; import JobNotesContainer from "../../components/jobs-notes/jobs-notes.container"; -import JobDetailFormContext from "./jobs-detail.page.context"; -import JobsDetailDatesComponent from "../../components/jobs-detail-dates/jobs-detail-dates.component"; import ScheduleJobModalContainer from "../../components/schedule-job-modal/schedule-job-modal.container"; +import JobDetailFormContext from "./jobs-detail.page.context"; export default function JobsDetailPage({ job, @@ -60,19 +56,7 @@ export default function JobsDetailPage({ updateJobStatus={updateJobStatus} /> - {isFieldsTouched() ? ( - - {t("general.messages.unsavedchanges")} - - - } - closable - /> - ) : null} + {isFieldsTouched() ? : null} { // }; - }, [data]); + }, [data, setBodyshop]); return ; }); diff --git a/client/src/pages/manage/manage.page.jsx b/client/src/pages/manage/manage.page.jsx index 89bf3e5ef..d63ea3d1a 100644 --- a/client/src/pages/manage/manage.page.jsx +++ b/client/src/pages/manage/manage.page.jsx @@ -1,19 +1,15 @@ -import { BackTop, Layout, notification } from "antd"; +import { BackTop, Layout } from "antd"; import React, { lazy, Suspense, useEffect } from "react"; - import { useTranslation } from "react-i18next"; -//This page will handle all routing for the entire application. -import { connect } from "react-redux"; import { Route } from "react-router"; import ErrorBoundary from "../../components/error-boundary/error-boundary.component"; import FooterComponent from "../../components/footer/footer.component"; //Component Imports import HeaderContainer from "../../components/header/header.container"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; -//const WhiteBoardPage = lazy(() => import("../white-board/white-board.page")); -import { setBodyshop } from "../../redux/user/user.actions"; import "./manage.page.styles.scss"; + const ManageRootPage = lazy(() => import("../manage-root/manage-root.page.container") ); diff --git a/client/src/pages/vehicles-detail/vehicles-detail.page.component.jsx b/client/src/pages/vehicles-detail/vehicles-detail.page.component.jsx index 02400dc7e..62b04e3c0 100644 --- a/client/src/pages/vehicles-detail/vehicles-detail.page.component.jsx +++ b/client/src/pages/vehicles-detail/vehicles-detail.page.component.jsx @@ -1,9 +1,13 @@ import React from "react"; +import VehicleDetailFormContainer from "../../components/vehicle-detail-form/vehicle-detail-form.container"; -export default function VehicleDetailComponent({ vehicle }) { +export default function VehicleDetailComponent({ vehicle, refetch }) { return (
Veh detail {vehicle.v_vin} +
Vehicle Fields
+ +
Associated Jobs
); } diff --git a/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx b/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx index ccc9efe8b..0694ec9fc 100644 --- a/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx +++ b/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx @@ -17,10 +17,10 @@ export default function VehicleDetailContainer({ match }) { if (loading) return ; if (error) return ; - console.log("vehId", vehId); - if (data.vehicles[0]) - return ; + return ( + + ); else return ( diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 35a4d9c39..27bbf0a5f 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -331,7 +331,29 @@ "noaccess": "The vehicle does not exist or you do not have access to it." }, "fields": { - "plate_no": "License Plate" + "plate_no": "License Plate", + "plate_st": "Plate Jurisdiction", + "trim_color": "Trim Color", + "v_bstyle": "Body Style", + "v_color": "Color", + "v_cond": "Condition", + "v_engine": "Engine", + "v_make_desc": "Make", + "v_makecode": "Make Code", + "v_mldgcode": "Molding Code", + "v_model_desc": "Model", + "v_model_yr": "Year", + "v_options": "Options", + "v_paint_codes": "Paint Codes", + "v_prod_dt": "Production Date", + "v_stage": "Stage", + "v_tone": "Tone", + "v_trimcode": "Trim Code", + "v_type": "Type", + "v_vin": "Vehicle Identification Number" + }, + "successes": { + "save": "Vehicle saved successfully." } } } diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 505e60676..aeccb967b 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -331,7 +331,29 @@ "noaccess": "El vehículo no existe o usted no tiene acceso a él." }, "fields": { - "plate_no": "Placa" + "plate_no": "Placa", + "plate_st": "Jurisdicción de placas", + "trim_color": "Recortar color", + "v_bstyle": "Tipo de cuerpo", + "v_color": "Color", + "v_cond": "condición", + "v_engine": "Motor", + "v_make_desc": "Hacer", + "v_makecode": "Hacer código", + "v_mldgcode": "Código de moldeo", + "v_model_desc": "Modelo", + "v_model_yr": "año", + "v_options": "Opciones", + "v_paint_codes": "Códigos de pintura", + "v_prod_dt": "Fecha de producción", + "v_stage": "Escenario", + "v_tone": "Tono", + "v_trimcode": "Código de recorte", + "v_type": "Tipo", + "v_vin": "Número de identificación del vehículo" + }, + "successes": { + "save": "Vehículo guardado con éxito." } } } diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 6bc1f4d8f..42bce0207 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -331,7 +331,29 @@ "noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès." }, "fields": { - "plate_no": "Plaque d'immatriculation" + "plate_no": "Plaque d'immatriculation", + "plate_st": "Juridiction de la plaque", + "trim_color": "Couleur de garniture", + "v_bstyle": "Style corporel", + "v_color": "Couleur", + "v_cond": "Etat", + "v_engine": "moteur", + "v_make_desc": "Faire", + "v_makecode": "Faire du code", + "v_mldgcode": "Code de moulage", + "v_model_desc": "Modèle", + "v_model_yr": "année", + "v_options": "Les options", + "v_paint_codes": "Codes de peinture", + "v_prod_dt": "Date de production", + "v_stage": "Étape", + "v_tone": "ton", + "v_trimcode": "Code de coupe", + "v_type": "Type", + "v_vin": "Plaque d'immatriculation" + }, + "successes": { + "save": "Le véhicule a été enregistré avec succès." } } }