From 4e5c305f95c1d9d1c5c9021b7b3528b5ba8e88f9 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Thu, 11 Jun 2020 14:09:12 -0700 Subject: [PATCH] Fixed up job details lines table + jobs totals page. --- bodyshop_translations.babel | 126 ++++-- client/src/App/App.js | 1 + client/src/App/App.styles.scss | 10 + .../allocations-employee-label.component.jsx | 7 +- .../allocations-employee-label.container.jsx | 10 +- .../fcm-notification.component.jsx | 1 - .../currency-form-item.component.jsx | 5 +- .../job-detail-lines/job-lines.component.jsx | 129 +++--- .../job-detail-lines/job-lines.container.jsx | 77 ++-- .../job-totals-table.component.jsx | 405 ++++++++---------- .../job-totals-table.styles.scss | 24 ++ .../jobs-detail-claims.component.jsx | 2 +- .../jobs-detail-financial.component.jsx | 235 +++++----- .../jobs-detail-insurance.component.jsx | 4 +- .../layout-form-row.component.jsx | 4 +- .../layout-form-row.styles.scss | 6 + client/src/translations/en_us/common.json | 14 +- client/src/translations/es/common.json | 8 +- client/src/translations/fr/common.json | 8 +- client/src/utils/arrayHelper.js | 3 + 20 files changed, 562 insertions(+), 517 deletions(-) create mode 100644 client/src/App/App.styles.scss create mode 100644 client/src/components/job-totals-table/job-totals-table.styles.scss create mode 100644 client/src/components/layout-form-row/layout-form-row.styles.scss create mode 100644 client/src/utils/arrayHelper.js diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 31be82e0b..9532b7e87 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -10775,6 +10775,27 @@ + + dedinfo + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + inscoinfo false @@ -10796,6 +10817,27 @@ + + laborrates + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + lossinfo false @@ -11588,6 +11630,48 @@ + + mapa + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + mash + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + net_repairs false @@ -11651,27 +11735,6 @@ - - paint_mat - false - - - - - - en-US - false - - - es-MX - false - - - fr-CA - false - - - parts false @@ -11819,27 +11882,6 @@ - - shop_mat - false - - - - - - en-US - false - - - es-MX - false - - - fr-CA - false - - - state_tax_amt false diff --git a/client/src/App/App.js b/client/src/App/App.js index c232f0efb..ef66bb6d1 100644 --- a/client/src/App/App.js +++ b/client/src/App/App.js @@ -10,6 +10,7 @@ import { checkUserSession } from "../redux/user/user.actions"; import { selectCurrentUser } from "../redux/user/user.selectors"; import PrivateRoute from "../utils/private-route"; import "antd/dist/antd.css"; +import "./App.styles.scss"; const LandingPage = lazy(() => import("../pages/landing/landing.page")); const ManagePage = lazy(() => import("../pages/manage/manage.page.container")); diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss new file mode 100644 index 000000000..3c627e2bf --- /dev/null +++ b/client/src/App/App.styles.scss @@ -0,0 +1,10 @@ +//Global Styles. + +.imex-table-header { + display: flex; + flex-wrap: wrap; + justify-content: center; + &__search { + flex: 1; + } +} diff --git a/client/src/components/allocations-employee-label/allocations-employee-label.component.jsx b/client/src/components/allocations-employee-label/allocations-employee-label.component.jsx index 427c2a2b9..41b14c593 100644 --- a/client/src/components/allocations-employee-label/allocations-employee-label.component.jsx +++ b/client/src/components/allocations-employee-label/allocations-employee-label.component.jsx @@ -4,10 +4,11 @@ import { MdRemoveCircleOutline } from "react-icons/md"; export default function AllocationsLabelComponent({ allocation, handleClick }) { return ( -
+
- {`${allocation.employee.first_name || ""} ${allocation.employee - .last_name || ""} (${allocation.hours || ""})`} + {`${allocation.employee.first_name || ""} ${ + allocation.employee.last_name || "" + } (${allocation.hours || ""})`} { + + const handleClick = (e) => { e.preventDefault(); deleteAllocation({ variables: { id: allocation.id } }) - .then(r => { + .then((r) => { notification["success"]({ - message: t("allocations.successes.deleted") + message: t("allocations.successes.deleted"), }); if (refetch) refetch(); }) - .catch(error => { + .catch((error) => { notification["error"]({ message: t("allocations.errors.deleting") }); }); }; + return ( `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")} - // parser={value => value.replace(/\$\s?|(,*)/g, "")} + style={{ width: "initial" }} + formatter={(value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")} + parser={(value) => value.replace(/\$\s?|(,*)/g, "")} precision={2} /> ); 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 3f61ca0d1..1cab65ce9 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -10,8 +10,11 @@ import AllocationsAssignmentContainer from "../allocations-assignment/allocation import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container"; import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container"; import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; +import { onlyUnique } from "../../utils/arrayHelper"; const mapDispatchToProps = (dispatch) => ({ + setJobLineEditContext: (context) => + dispatch(setModalContext({ context: context, modal: "jobLineEdit" })), setPartsOrderContext: (context) => dispatch(setModalContext({ context: context, modal: "partsOrder" })), }); @@ -34,30 +37,20 @@ export function JobLinesComponent({ const columns = [ { - title: t("joblines.fields.line_no"), + title: "#", dataIndex: "line_no", key: "line_no", - // onFilter: (value, record) => record.ro_number.includes(value), - // filteredValue: state.filteredInfo.text || null, sorter: (a, b) => a.line_no - b.line_no, sortOrder: state.sortedInfo.columnKey === "line_no" && state.sortedInfo.order, - //ellipsis: true, - editable: true, - width: 75, }, { - title: t("joblines.fields.unq_seq"), - dataIndex: "unq_seq", - key: "unq_seq", - // onFilter: (value, record) => record.ro_number.includes(value), - // filteredValue: state.filteredInfo.text || null, - sorter: (a, b) => a.unq_seq - b.unq_seq, + title: t("joblines.fields.line_ind"), + dataIndex: "line_ind", + key: "line_ind", + sorter: (a, b) => alphaSort(a.line_ind, b.line_ind), sortOrder: - state.sortedInfo.columnKey === "unq_seq" && state.sortedInfo.order, - //ellipsis: true, - editable: true, - width: 75, + state.sortedInfo.columnKey === "line_ind" && state.sortedInfo.order, }, { title: t("joblines.fields.line_desc"), @@ -67,7 +60,6 @@ export function JobLinesComponent({ sortOrder: state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order, ellipsis: true, - editable: true, }, { title: t("joblines.fields.oem_partno"), @@ -81,8 +73,6 @@ export function JobLinesComponent({ sortOrder: state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order, ellipsis: true, - editable: true, - render: (text, record) => ( {record.oem_partno ? record.oem_partno : record.op_code_desc} @@ -99,24 +89,28 @@ export function JobLinesComponent({ filters: [ { text: t("jobs.labels.partsfilter"), - value: "parts", + value: ["PAN", "PAL", "PAA", "PAS", "PASL"], + }, + { + text: "PAN", + value: ["PAN"], + }, + { + text: "PAL", + value: ["PAL"], + }, + { + text: "PAA", + value: ["PAA"], + }, + { + text: "PAS/PASL", + value: ["PAS", "PASL"], }, ], - // specify the condition of filtering result - // here is that finding the name started with `value` - onFilter: (value, record) => - ["PAN", "PAL", "PAA", "PAS", "PASL"].includes(record.part_type), - ellipsis: true, - editable: true, - }, - { - title: t("joblines.fields.line_ind"), - dataIndex: "line_ind", - key: "line_ind", - sorter: (a, b) => alphaSort(a.line_ind, b.line_ind), - sortOrder: - state.sortedInfo.columnKey === "line_ind" && state.sortedInfo.order, + onFilter: (value, record) => value.includes(record.part_type), }, + { title: t("joblines.fields.act_price"), dataIndex: "act_price", @@ -125,7 +119,6 @@ export function JobLinesComponent({ sortOrder: state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order, ellipsis: true, - render: (text, record) => ( {record.act_price} ), @@ -134,7 +127,6 @@ export function JobLinesComponent({ title: t("joblines.fields.part_qty"), dataIndex: "part_qty", key: "part_qty", - ellipsis: true, }, { title: t("joblines.fields.total"), @@ -144,7 +136,6 @@ export function JobLinesComponent({ sortOrder: state.sortedInfo.columnKey === "total" && state.sortedInfo.order, ellipsis: true, - render: (text, record) => ( {record.act_price * record.part_qty} @@ -155,6 +146,7 @@ export function JobLinesComponent({ title: t("joblines.fields.mod_lb_hrs"), dataIndex: "mod_lb_hrs", key: "mod_lb_hrs", + responsive: ["lg"], sorter: (a, b) => a.mod_lb_hrs - b.mod_lb_hrs, sortOrder: state.sortedInfo.columnKey === "mod_lb_hrs" && state.sortedInfo.order, @@ -166,12 +158,24 @@ export function JobLinesComponent({ sorter: (a, b) => alphaSort(a.status, b.status), sortOrder: state.sortedInfo.columnKey === "status" && state.sortedInfo.order, + filters: + (jobLines && + jobLines + .map((l) => l.status) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "No Status*", + value: [s], + }; + })) || + [], + onFilter: (value, record) => value.includes(record.status), }, { title: t("allocations.fields.employee"), dataIndex: "employee", key: "employee", - sorter: (a, b) => alphaSort( a.allocations[0] && @@ -194,12 +198,6 @@ export function JobLinesComponent({ /> )) : null} - ), }, @@ -208,7 +206,7 @@ export function JobLinesComponent({ dataIndex: "actions", key: "actions", render: (text, record) => ( - +
- + +
), }, ]; @@ -243,16 +247,17 @@ export function JobLinesComponent({
{ return ( -
- { - e.preventDefault(); - setSearchText(e.target.value); - }} - /> +
+
+ { + e.preventDefault(); + setSearchText(e.target.value); + }} + /> +
); }} - loading={loading} - size='small' expandedRowRender={(record) => (
{t("parts_orders.labels.orderhistory")} @@ -301,7 +313,6 @@ export function JobLinesComponent({ ))}
)} - pagination={{ position: "top", defaultPageSize: 25 }} rowSelection={{ selectedRowKeys: selectedLines.map((item) => item.id), onSelectAll: (selected, selectedRows, changeRows) => { @@ -310,10 +321,6 @@ export function JobLinesComponent({ onSelect: (record, selected, selectedRows, nativeEvent) => setSelectedLines(selectedRows), }} - columns={columns} - rowKey='id' - dataSource={jobLines} - onChange={handleTableChange} />
); 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 2988929cc..bc1f10d42 100644 --- a/client/src/components/job-detail-lines/job-lines.container.jsx +++ b/client/src/components/job-detail-lines/job-lines.container.jsx @@ -1,70 +1,59 @@ import { useQuery } from "@apollo/react-hooks"; import React, { useState } from "react"; - import { GET_JOB_LINES_BY_PK } from "../../graphql/jobs-lines.queries"; import AlertComponent from "../alert/alert.component"; import JobLinesComponent from "./job-lines.component"; -import { connect } from "react-redux"; -import { setModalContext } from "../../redux/modals/modals.actions"; -const mapDispatchToProps = dispatch => ({ - setJobLineEditContext: context => - dispatch(setModalContext({ context: context, modal: "jobLineEdit" })) -}); - -export function JobLinesContainer({ jobId, setJobLineEditContext }) { +function JobLinesContainer({ jobId }) { const { loading, error, data, refetch } = useQuery(GET_JOB_LINES_BY_PK, { variables: { id: jobId }, - fetchPolicy: "network-only" }); const [searchText, setSearchText] = useState(""); const [selectedLines, setSelectedLines] = useState([]); - if (error) return ; + if (error) return ; + + const jobLines = + data && data.joblines + ? searchText + ? data.joblines.filter( + (jl) => + (jl.unq_seq || "") + .toString() + .toLowerCase() + .includes(searchText.toLowerCase()) || + (jl.line_desc || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (jl.part_type || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (jl.oem_partno || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (jl.op_code_desc || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (jl.db_price || "") + .toString() + .includes(searchText.toLowerCase()) || + (jl.act_price || "").toString().includes(searchText.toLowerCase()) + ) + : data.joblines + : null; return ( - (jl.unq_seq || "") - .toString() - .toLowerCase() - .includes(searchText.toLowerCase()) || - (jl.line_desc || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (jl.part_type || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (jl.oem_partno || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (jl.op_code_desc || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (jl.db_price || "") - .toString() - .includes(searchText.toLowerCase()) || - (jl.act_price || "") - .toString() - .includes(searchText.toLowerCase()) - ) - : data.joblines - : null - } + jobLines={jobLines} setSearchText={setSearchText} selectedLines={selectedLines} setSelectedLines={setSelectedLines} jobId={jobId} - setJobLineEditContext={setJobLineEditContext} /> ); } -export default connect(null, mapDispatchToProps)(JobLinesContainer); +export default JobLinesContainer; diff --git a/client/src/components/job-totals-table/job-totals-table.component.jsx b/client/src/components/job-totals-table/job-totals-table.component.jsx index 3c0c29818..ba262560d 100644 --- a/client/src/components/job-totals-table/job-totals-table.component.jsx +++ b/client/src/components/job-totals-table/job-totals-table.component.jsx @@ -6,6 +6,8 @@ import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import { CalculateJob } from "./job-totals.utility"; +import "./job-totals-table.styles.scss"; + const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -23,231 +25,186 @@ export function JobsTotalsTableComponent({ bodyshop, job }) { console.log("Totals was falsey."); return ; } - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + return ( +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t("jobs.labels.rates")}$
{t("jobs.fields.rate_laa")}{totals.rates.laa.total.toFormat()}{`(${totals.rates.laa.hours.toFixed(2)} @ ${ + totals.rates.laa.rate + })`}
{t("jobs.fields.rate_lab")}{totals.rates.lab.total.toFormat()}{`(${totals.rates.lab.hours.toFixed(2)} @ ${ + totals.rates.lab.rate + })`}
{t("jobs.fields.rate_lad")}{totals.rates.lad.total.toFormat()}{`(${totals.rates.lad.hours.toFixed(2)} @ ${ + totals.rates.lad.rate + })`}
{t("jobs.fields.rate_lae")}{totals.rates.lae.total.toFormat()}{`(${totals.rates.lae.hours.toFixed(2)} @ ${ + totals.rates.lae.rate + })`}
{t("jobs.fields.rate_laf")}{totals.rates.laf.total.toFormat()}{`(${totals.rates.laf.hours.toFixed(2)} @ ${ + totals.rates.laf.rate + })`}
{t("jobs.fields.rate_lag")}{totals.rates.lag.total.toFormat()}{`(${totals.rates.lag.hours.toFixed(2)} @ ${ + totals.rates.lag.rate + })`}
{t("jobs.fields.rate_lam")}{totals.rates.lam.total.toFormat()}{`(${totals.rates.lam.hours.toFixed(2)} @ ${ + totals.rates.lam.rate + })`}
{t("jobs.fields.rate_lar")}{totals.rates.lar.total.toFormat()}{`(${totals.rates.lar.hours.toFixed(2)} @ ${ + totals.rates.lar.rate + })`}
{t("jobs.fields.rate_las")}{totals.rates.las.total.toFormat()}{`(${totals.rates.las.hours.toFixed(2)} @ ${ + totals.rates.las.rate + })`}
{t("jobs.fields.rate_lau")}{totals.rates.lau.total.toFormat()}{`(${totals.rates.lau.hours.toFixed(2)} @ ${ + totals.rates.lau.rate + })`}
{t("jobs.fields.rate_la1")}{totals.rates.la1.total.toFormat()}{`(${totals.rates.la1.hours.toFixed(2)} @ ${ + totals.rates.la1.rate + })`}
{t("jobs.fields.rate_la2")}{totals.rates.la2.total.toFormat()}{`(${totals.rates.la2.hours.toFixed(2)} @ ${ + totals.rates.la2.rate + })`}
{t("jobs.fields.rate_la3")}{totals.rates.la3.total.toFormat()}{`(${totals.rates.la3.hours.toFixed(2)} @ ${ + totals.rates.la3.rate + })`}
{t("jobs.fields.rate_la4")}{totals.rates.la4.total.toFormat()}{`(${totals.rates.la4.hours.toFixed(2)} @ ${ + totals.rates.la4.rate + })`}
{t("jobs.fields.rate_atp")}{totals.rates.atp.total.toFormat()}{`(${totals.rates.atp.hours.toFixed(2)} @ ${ + totals.rates.atp.rate + })`}
{t("jobs.labels.mapa")}{totals.rates.mapa.total.toFormat()}{`(${totals.rates.mapa.hours.toFixed(2)} @ ${ + totals.rates.mapa.rate + })`}
{t("jobs.labels.mash")}{totals.rates.mash.total.toFormat()}{`(${totals.rates.mash.hours.toFixed(2)} @ ${ + totals.rates.mash.rate + })`}
{t("jobs.labels.rates_subtotal")}{totals.rates.subtotal.toFormat()}
+ + + + + + + + + + + + + +
{t("jobs.labels.partstotal")}{totals.parts.parts.total.toFormat()}{`(${totals.parts.parts.subtotal.toFormat()} ± ${totals.parts.parts.adjustments.toFormat()})`}
{t("jobs.labels.subletstotal")}{totals.parts.sublets.total.toFormat()}{`(${totals.parts.sublets.subtotal.toFormat()} ± ${totals.parts.sublets.adjustments.toFormat()})`}
+
+
+ + + + + + +
); } diff --git a/client/src/components/job-totals-table/job-totals-table.styles.scss b/client/src/components/job-totals-table/job-totals-table.styles.scss new file mode 100644 index 000000000..633d5be07 --- /dev/null +++ b/client/src/components/job-totals-table/job-totals-table.styles.scss @@ -0,0 +1,24 @@ +.job-totals-container { + display: flex; + flex-flow: wrap; +} +.job-totals-tables { + flex: 1; + display: block; +} + +.job-totals-rates-table, +.job-totals-parts-table { + border: black; + width: 100%; +} + +.job-totals-stats { + margin: 1rem; + display: flex; + flex-direction: column; + align-content: center; + .ant-statistic { + margin: 0.5rem; + } +} diff --git a/client/src/components/jobs-detail-claims/jobs-detail-claims.component.jsx b/client/src/components/jobs-detail-claims/jobs-detail-claims.component.jsx index cba21d320..91344c84c 100644 --- a/client/src/components/jobs-detail-claims/jobs-detail-claims.component.jsx +++ b/client/src/components/jobs-detail-claims/jobs-detail-claims.component.jsx @@ -1,4 +1,4 @@ -import { Form, Input, Switch, InputNumber, Typography } from "antd"; +import { Form, Input, InputNumber, Switch } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import FormRow from "../layout-form-row/layout-form-row.component"; diff --git a/client/src/components/jobs-detail-financial/jobs-detail-financial.component.jsx b/client/src/components/jobs-detail-financial/jobs-detail-financial.component.jsx index 6e1f10518..6027a644c 100644 --- a/client/src/components/jobs-detail-financial/jobs-detail-financial.component.jsx +++ b/client/src/components/jobs-detail-financial/jobs-detail-financial.component.jsx @@ -2,131 +2,128 @@ import { Col, Divider, Form, Input, InputNumber, Row } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import JobTotalsTable from "../job-totals-table/job-totals-table.component"; +import FormRow from "../layout-form-row/layout-form-row.component"; +import CurrencyInput from "../form-items-formatted/currency-form-item.component"; export default function JobsDetailFinancials({ job }) { const { t } = useTranslation(); return ( - - - - - - - - - - - - TODO This is equivalent of GST payable. - - - - TODO equivalent of other customer amount - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Note //TODO Remove ATP rate? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + -

Mitchell: {JSON.stringify(job.cieca_ttl, null, "\t")}

-

Mine:{JSON.stringify(job.job_totals, null, "\t")}

); diff --git a/client/src/components/jobs-detail-insurance/jobs-detail-insurance.component.jsx b/client/src/components/jobs-detail-insurance/jobs-detail-insurance.component.jsx index d460ce4f9..61191031b 100644 --- a/client/src/components/jobs-detail-insurance/jobs-detail-insurance.component.jsx +++ b/client/src/components/jobs-detail-insurance/jobs-detail-insurance.component.jsx @@ -1,10 +1,10 @@ -import { DatePicker, Divider, Form, Input, Typography } from "antd"; +import { DatePicker, Form, Input } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemPhone from "../form-items-formatted/phone-form-item.component"; -import FormRow from "../layout-form-row/layout-form-row.component"; import Car from "../job-damage-visual/job-damage-visual.component"; +import FormRow from "../layout-form-row/layout-form-row.component"; export default function JobsDetailInsurance({ job, form }) { const { getFieldValue } = form; diff --git a/client/src/components/layout-form-row/layout-form-row.component.jsx b/client/src/components/layout-form-row/layout-form-row.component.jsx index 4d2b79672..6ce27493b 100644 --- a/client/src/components/layout-form-row/layout-form-row.component.jsx +++ b/client/src/components/layout-form-row/layout-form-row.component.jsx @@ -1,5 +1,6 @@ import React from "react"; import { Row, Col, Typography } from "antd"; +import "./layout-form-row.styles.scss"; export default function LayoutFormRow({ header, children }) { if (!!!children.length) { @@ -8,7 +9,6 @@ export default function LayoutFormRow({ header, children }) { } const rowGutter = { gutter: [32, 32] }; const colSpan = (maxspan) => { - console.log("maxspan", maxspan); return { xs: { span: 24, @@ -25,7 +25,7 @@ export default function LayoutFormRow({ header, children }) { }; return ( -
+
{header ? {header} : null} {children.map((c, idx) => ( diff --git a/client/src/components/layout-form-row/layout-form-row.styles.scss b/client/src/components/layout-form-row/layout-form-row.styles.scss new file mode 100644 index 000000000..921828efa --- /dev/null +++ b/client/src/components/layout-form-row/layout-form-row.styles.scss @@ -0,0 +1,6 @@ +//Override Antd Row margin to save space on forms. +.imex-form-row { + .ant-row { + margin-bottom: 0rem; + } +} diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 542dee8c6..940ea6216 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -364,7 +364,7 @@ "instanceconflictext": "Your $t(titles.app) account can only be used on one device at any given time. Refresh your session to take control.", "instanceconflictitle": "Your account is being used elsewhere.", "loading": "Loading...", - "loadingapp": "Loading Bodyshop.app", + "loadingapp": "Loading $t(titles.app)", "loadingshop": "Loading shop data...", "loggingin": "Authorizing...", "na": "N/A", @@ -487,14 +487,14 @@ "fields": { "act_price": "Actual Price", "db_price": "Database Price", - "line_desc": "Line Description", + "line_desc": "Line Desc.", "line_ind": "S#", "line_no": "Line #", - "mod_lb_hrs": "Labor Hours", + "mod_lb_hrs": "Hrs", "mod_lbr_ty": "Labor Type", "oem_partno": "OEM Part #", "op_code_desc": "Operation Code Description", - "part_qty": "Quantity", + "part_qty": "Qty.", "part_type": "Part Type", "status": "Status", "total": "Total", @@ -669,7 +669,9 @@ "forms": { "appraiserinfo": "Appraiser Info", "claiminfo": "Claim Information", + "dedinfo": "Deductible Info", "inscoinfo": "Insurance Company Information", + "laborrates": "Labor Rates", "lossinfo": "Loss Information" }, "labels": { @@ -713,10 +715,11 @@ "laborallocations": "Labor Allocations", "lines": "Estimate Lines", "local_tax_amt": "Local Taxes", + "mapa": "Paint Materials", + "mash": "Shop Materials", "net_repairs": "Net Repairs", "notes": "Notes", "override_header": "Override estimate header on import?", - "paint_mat": "Paint Materials", "parts": "Parts", "partsfilter": "Parts Only", "partssubletstotal": "Parts & Sublets Total", @@ -724,7 +727,6 @@ "rates": "Rates", "rates_subtotal": "Rates Subtotal", "reconciliationheader": "Parts & Sublet Reconciliation", - "shop_mat": "Shop Materials", "state_tax_amt": "State/Provincial Taxes", "subletstotal": "Sublets Total", "subtotal": "Subtotal", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index f71a919ec..bb037f735 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -364,7 +364,7 @@ "instanceconflictext": "", "instanceconflictitle": "", "loading": "Cargando...", - "loadingapp": "Cargando Bodyshop.app", + "loadingapp": "Cargando $t(titles.app)", "loadingshop": "Cargando datos de la tienda ...", "loggingin": "Iniciando sesión ...", "na": "N / A", @@ -669,7 +669,9 @@ "forms": { "appraiserinfo": "", "claiminfo": "", + "dedinfo": "", "inscoinfo": "", + "laborrates": "", "lossinfo": "" }, "labels": { @@ -713,10 +715,11 @@ "laborallocations": "", "lines": "Líneas estimadas", "local_tax_amt": "", + "mapa": "", + "mash": "", "net_repairs": "", "notes": "Notas", "override_header": "¿Anular encabezado estimado al importar?", - "paint_mat": "", "parts": "Partes", "partsfilter": "", "partssubletstotal": "", @@ -724,7 +727,6 @@ "rates": "Tarifas", "rates_subtotal": "", "reconciliationheader": "", - "shop_mat": "", "state_tax_amt": "", "subletstotal": "", "subtotal": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 8727fa5c0..8c3f69390 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -364,7 +364,7 @@ "instanceconflictext": "", "instanceconflictitle": "", "loading": "Chargement...", - "loadingapp": "Chargement de Bodyshop.app", + "loadingapp": "Chargement de $t(titles.app)", "loadingshop": "Chargement des données de la boutique ...", "loggingin": "Vous connecter ...", "na": "N / A", @@ -669,7 +669,9 @@ "forms": { "appraiserinfo": "", "claiminfo": "", + "dedinfo": "", "inscoinfo": "", + "laborrates": "", "lossinfo": "" }, "labels": { @@ -713,10 +715,11 @@ "laborallocations": "", "lines": "Estimer les lignes", "local_tax_amt": "", + "mapa": "", + "mash": "", "net_repairs": "", "notes": "Remarques", "override_header": "Remplacer l'en-tête d'estimation à l'importation?", - "paint_mat": "", "parts": "les pièces", "partsfilter": "", "partssubletstotal": "", @@ -724,7 +727,6 @@ "rates": "Les taux", "rates_subtotal": "", "reconciliationheader": "", - "shop_mat": "", "state_tax_amt": "", "subletstotal": "", "subtotal": "", diff --git a/client/src/utils/arrayHelper.js b/client/src/utils/arrayHelper.js new file mode 100644 index 000000000..47108210a --- /dev/null +++ b/client/src/utils/arrayHelper.js @@ -0,0 +1,3 @@ +export function onlyUnique(value, index, self, key) { + return self.indexOf(value) === index; +}