From fe002b0dffa56f32086c27a6fa90f9788a374234 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 2 Apr 2020 17:59:42 -0700 Subject: [PATCH] CLEANUP Refactored parts order to use redux modals. --- bodyshop_translations.babel | 105 +++++++++++ .../job-detail-lines/job-lines.component.jsx | 32 ++-- .../job-detail-lines/job-lines.container.jsx | 12 +- .../parts-order-modal.component.jsx | 170 ++++++++++-------- .../parts-order-modal.container.jsx | 140 +++++++-------- client/src/graphql/vendors.queries.js | 1 + client/src/redux/modals/modals.reducer.js | 3 +- client/src/redux/modals/modals.selectors.js | 5 + client/src/translations/en_us/common.json | 5 + client/src/translations/es/common.json | 5 + client/src/translations/fr/common.json | 5 + 11 files changed, 306 insertions(+), 177 deletions(-) diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 883a4e1d3..c81cdead3 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -10393,6 +10393,48 @@ fields + + act_price + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + db_price + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + deliver_by false @@ -10414,6 +10456,69 @@ + + job_line_id + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + line_desc + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + line_remarks + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + lineremarks false 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 c60a18208..60fa8faf5 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -1,7 +1,9 @@ import { Button, Input, Table } from "antd"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; import { Link } from "react-router-dom"; +import { setModalContext } from "../../redux/modals/modals.actions"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { alphaSort } from "../../utils/sorters"; import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container"; @@ -9,14 +11,19 @@ import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/a import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container"; import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; -export default function JobLinesComponent({ +const mapDispatchToProps = dispatch => ({ + setPartsOrderContext: context => + dispatch(setModalContext({ context: context, modal: "partsOrder" })) +}); + +export function JobLinesComponent({ + setPartsOrderContext, loading, refetch, jobLines, setSearchText, selectedLines, setSelectedLines, - partsOrderModalVisible, jobId, setJobLineEditContext }) { @@ -24,7 +31,7 @@ export default function JobLinesComponent({ sortedInfo: {} }); const { t } = useTranslation(); - const setPartsModalVisible = partsOrderModalVisible[1]; + const columns = [ { title: t("joblines.fields.unq_seq"), @@ -205,13 +212,7 @@ export default function JobLinesComponent({ return (
- - + { return ( @@ -225,7 +226,15 @@ export default function JobLinesComponent({ /> @@ -280,3 +289,4 @@ export default function JobLinesComponent({ ); } +export default connect(null, mapDispatchToProps)(JobLinesComponent); diff --git a/client/src/components/job-detail-lines/job-lines.container.jsx b/client/src/components/job-detail-lines/job-lines.container.jsx index 5ff515c19..2988929cc 100644 --- a/client/src/components/job-detail-lines/job-lines.container.jsx +++ b/client/src/components/job-detail-lines/job-lines.container.jsx @@ -11,10 +11,8 @@ const mapDispatchToProps = dispatch => ({ setJobLineEditContext: context => dispatch(setModalContext({ context: context, modal: "jobLineEdit" })) }); -export default connect( - null, - mapDispatchToProps -)(function JobLinesContainer({ jobId, setJobLineEditContext }) { + +export function JobLinesContainer({ jobId, setJobLineEditContext }) { const { loading, error, data, refetch } = useQuery(GET_JOB_LINES_BY_PK, { variables: { id: jobId }, fetchPolicy: "network-only" @@ -22,7 +20,6 @@ export default connect( const [searchText, setSearchText] = useState(""); const [selectedLines, setSelectedLines] = useState([]); - const partsOrderModalVisible = useState(false); if (error) return ; @@ -64,9 +61,10 @@ export default connect( setSearchText={setSearchText} selectedLines={selectedLines} setSelectedLines={setSelectedLines} - partsOrderModalVisible={partsOrderModalVisible} jobId={jobId} setJobLineEditContext={setJobLineEditContext} /> ); -}); +} + +export default connect(null, mapDispatchToProps)(JobLinesContainer); diff --git a/client/src/components/parts-order-modal/parts-order-modal.component.jsx b/client/src/components/parts-order-modal/parts-order-modal.component.jsx index d9a4e6a0b..e14b32653 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.component.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.component.jsx @@ -1,94 +1,106 @@ -import { AutoComplete, DatePicker, Input, List, Radio } from "antd"; -import { HeartFilled } from "@ant-design/icons"; -import React, { useState } from "react"; +import { DeleteFilled } from "@ant-design/icons"; +import { DatePicker, Form, Input } from "antd"; +import React from "react"; import { useTranslation } from "react-i18next"; +import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component"; +import CurrencyInput from "../form-items-formatted/currency-form-item.component"; export default function PartsOrderModalComponent({ vendorList, - state, - sendTypeState, - orderLinesState + sendTypeState }) { - const [partsOrder, setPartsOrder] = state; const [sendType, setSendType] = sendTypeState; - const orderLines = orderLinesState[0]; - const [vendorComplete, setVendorComplete] = useState(vendorList); + const { t } = useTranslation(); - const handleSearch = value => { - if (value === "") setVendorComplete(vendorList); - else - setVendorComplete( - vendorList.filter(v => - v.name.toLowerCase().includes(value.toLowerCase()) - ) - ); - }; - - const handleSelect = (value, option) => { - setPartsOrder({ ...partsOrder, vendorid: option.key }); - }; - return (
- - {vendorComplete.map(v => ( - -
{v.name}
-
{v.favorite ? : null}
-
- ))} -
- {t("parts_orders.fields.deliver_by")} - { - setPartsOrder({ ...partsOrder, deliver_by: e }); - }} - /> - + + + + + {t("parts_orders.labels.inthisorder")} - ( - - //TODO Editable table/adding line remarks to the order. - ]} - > - { - // - // } - // title={{item.name.last}} - // description='Ant Design, a design language for background applications, is refined by Ant UED Team' - // /> - } -
{`${item.line_desc}${ - item.oem_partno ? " | " + item.oem_partno : "" - }`}
-
- )} - /> - - setSendType(e.target.value)} - > - {t("parts_orders.labels.email")} - {t("parts_orders.labels.print")} - + + {(fields, { add, remove }) => { + return ( +
+ {fields.map((field, index) => ( + +
+ + + + + + + + + + + + + { + remove(field.name); + }} + /> +
+
+ ))} +
+ ); + }} +
); } + +// setSendType(e.target.value)} +// > +// {t("parts_orders.labels.email")} +// {t("parts_orders.labels.print")} +// diff --git a/client/src/components/parts-order-modal/parts-order-modal.container.jsx b/client/src/components/parts-order-modal/parts-order-modal.container.jsx index 30786296c..56011a11b 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.container.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.container.jsx @@ -1,12 +1,20 @@ -import { Modal, notification } from "antd"; -import React, { useState, useEffect } from "react"; import { useMutation, useQuery } from "@apollo/react-hooks"; +import { Form, Modal, notification } from "antd"; +import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries"; +import PartsOrderEmailTemplate from "../../emails/templates/parts-order/parts-order.email"; +import { REPORT_QUERY_PARTS_ORDER_BY_PK } from "../../emails/templates/parts-order/parts-order.query"; import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries"; +import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries"; import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries"; +import { + setEmailOptions, + toggleEmailOverlayVisible +} from "../../redux/email/email.actions"; +import { toggleModalVisible } from "../../redux/modals/modals.actions"; +import { selectPartsOrder } from "../../redux/modals/modals.selectors"; import { selectBodyshop, selectCurrentUser @@ -14,102 +22,53 @@ import { import AlertComponent from "../alert/alert.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import PartsOrderModalComponent from "./parts-order-modal.component"; -import { - setEmailOptions, - toggleEmailOverlayVisible -} from "../../redux/email/email.actions"; -import PartsOrderEmailTemplate from "../../emails/templates/parts-order/parts-order.email"; -import { REPORT_QUERY_PARTS_ORDER_BY_PK } from "../../emails/templates/parts-order/parts-order.query"; - const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, - bodyshop: selectBodyshop + bodyshop: selectBodyshop, + partsOrderModal: selectPartsOrder }); const mapDispatchToProps = dispatch => ({ setEmailOptions: e => dispatch(setEmailOptions(e)), - toggleEmailOverlayVisible: () => dispatch(toggleEmailOverlayVisible()) + toggleEmailOverlayVisible: () => dispatch(toggleEmailOverlayVisible()), + toggleModalVisible: () => dispatch(toggleModalVisible("partsOrder")) }); export default connect( mapStateToProps, mapDispatchToProps )(function PartsOrderModalContainer({ - partsOrderModalVisible, - linesToOrder, - jobId, + partsOrderModal, + toggleModalVisible, currentUser, bodyshop, - refetch, setEmailOptions, toggleEmailOverlayVisible }) { const { t } = useTranslation(); - const [modalVisible, setModalVisible] = partsOrderModalVisible; - //set order lines to be a version of the incoming lines. - const orderLinesState = useState( - linesToOrder.reduce((acc, value) => { - acc.push({ - line_desc: value.line_desc, - oem_partno: value.oem_partno, - db_price: value.db_price, - act_price: value.act_price, - line_remarks: "Alalala", - job_line_id: value.id, - status: bodyshop.md_order_statuses.default_ordered || "Ordered*" - }); - return acc; - }, []) - ); - const [orderLines, setOrderLinesState] = orderLinesState; - useEffect(() => { - if (modalVisible) - setOrderLinesState( - linesToOrder.reduce((acc, value) => { - acc.push({ - line_desc: value.line_desc, - oem_partno: value.oem_partno, - db_price: value.db_price, - act_price: value.act_price, - line_remarks: "Alalala", - job_line_id: value.id, - status: bodyshop.md_order_statuses.default_ordered || "Ordered*" - }); - return acc; - }, []) - ); - }, [ - modalVisible, - setOrderLinesState, - linesToOrder, - bodyshop.md_order_statuses.default_ordered - ]); + const { visible, context, actions } = partsOrderModal; + const { jobId, linesToOrder } = context; + const { refetch } = actions; + const [form] = Form.useForm(); const sendTypeState = useState("e"); const sendType = sendTypeState[0]; - const partsOrderState = useState({ - vendorid: null, - jobid: jobId, - user_email: currentUser.email - }); - const partsOrder = partsOrderState[0]; const { loading, error, data } = useQuery(QUERY_ALL_VENDORS_FOR_ORDER, { fetchPolicy: "network-only", - skip: !modalVisible + skip: !visible }); const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS); const [updateJobLines] = useMutation(UPDATE_JOB_LINE_STATUS); - const handleOk = () => { + const handleFinish = values => { insertPartOrder({ variables: { po: [ { - ...partsOrder, - status: bodyshop.md_order_statuses.default_ordered || "Ordered*", - parts_order_lines: { - data: orderLines - } + ...values, + jobid: jobId, + user_email: currentUser.email, + status: bodyshop.md_order_statuses.default_ordered || "Ordered*" } ] } @@ -117,7 +76,7 @@ export default connect( .then(r => { updateJobLines({ variables: { - ids: linesToOrder.map(item => item.id), + ids: values.parts_order_lines.data.map(item => item.job_line_id), status: bodyshop.md_order_statuses.default_ordered || "Ordered*" } }) @@ -126,7 +85,7 @@ export default connect( message: t("parts_orders.successes.created") }); if (refetch) refetch(); - setModalVisible(false); + toggleModalVisible(); if (sendType === "e") { //Show the email modal and set the data. @@ -160,6 +119,8 @@ export default connect( description: error.message }); }); + + //end no good }) .catch(error => { notification["error"]({ @@ -169,20 +130,41 @@ export default connect( }); }; + const initialValues = + linesToOrder && + linesToOrder.reduce((acc, value) => { + acc.push({ + line_desc: value.line_desc, + oem_partno: value.oem_partno, + db_price: value.db_price, + act_price: value.act_price, + job_line_id: value.id, + status: bodyshop.md_order_statuses.default_ordered || "Ordered*" + }); + return acc; + }, []); + return ( setModalVisible(false)} - onOk={handleOk} + visible={visible} + onCancel={() => toggleModalVisible()} + width="90%" + onOk={() => form.submit()} + destroyOnClose > {error ? : null} - +
+ +
); diff --git a/client/src/graphql/vendors.queries.js b/client/src/graphql/vendors.queries.js index d1bf838e6..94773f2cc 100644 --- a/client/src/graphql/vendors.queries.js +++ b/client/src/graphql/vendors.queries.js @@ -73,6 +73,7 @@ export const QUERY_ALL_VENDORS_FOR_ORDER = gql` cost_center id favorite + discount } } `; diff --git a/client/src/redux/modals/modals.reducer.js b/client/src/redux/modals/modals.reducer.js index cab4d7437..7e75b8842 100644 --- a/client/src/redux/modals/modals.reducer.js +++ b/client/src/redux/modals/modals.reducer.js @@ -13,7 +13,8 @@ const INITIAL_STATE = { invoiceEnter: { ...baseModal }, courtesyCarReturn: { ...baseModal }, noteUpsert: { ...baseModal }, - schedule: { ...baseModal } + schedule: { ...baseModal }, + partsOrder: { ...baseModal } }; const modalsReducer = (state = INITIAL_STATE, action) => { diff --git a/client/src/redux/modals/modals.selectors.js b/client/src/redux/modals/modals.selectors.js index 92ee54a90..85908aa18 100644 --- a/client/src/redux/modals/modals.selectors.js +++ b/client/src/redux/modals/modals.selectors.js @@ -26,3 +26,8 @@ export const selectSchedule = createSelector( [selectModals], modals => modals.schedule ); + +export const selectPartsOrder = createSelector( + [selectModals], + modals => modals.partsOrder +); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 32c8cea3a..196eed0ca 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -679,7 +679,12 @@ "creating": "Error encountered when creating parts order. " }, "fields": { + "act_price": "Price", + "db_price": "DB Price", "deliver_by": "Deliver By", + "job_line_id": "Job Line Id", + "line_desc": "Line Description", + "line_remarks": "Remarks", "lineremarks": "Line Remarks" }, "labels": { diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 6ef9e3687..bbdb067cc 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -679,7 +679,12 @@ "creating": "Se encontró un error al crear el pedido de piezas." }, "fields": { + "act_price": "", + "db_price": "", "deliver_by": "Entregado por", + "job_line_id": "", + "line_desc": "", + "line_remarks": "", "lineremarks": "Comentarios de línea" }, "labels": { diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 6118fb29e..e5b057dc7 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -679,7 +679,12 @@ "creating": "Erreur rencontrée lors de la création de la commande de pièces." }, "fields": { + "act_price": "", + "db_price": "", "deliver_by": "Livrer par", + "job_line_id": "", + "line_desc": "", + "line_remarks": "", "lineremarks": "Remarques sur la ligne" }, "labels": {