Fixed up job details lines table + jobs totals page.

This commit is contained in:
Patrick Fic
2020-06-11 14:09:12 -07:00
parent 886c7e9cb9
commit 4e5c305f95
20 changed files with 562 additions and 517 deletions

View File

@@ -10775,6 +10775,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>dedinfo</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>inscoinfo</name> <name>inscoinfo</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -10796,6 +10817,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>laborrates</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>lossinfo</name> <name>lossinfo</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -11588,6 +11630,48 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>mapa</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>mash</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>net_repairs</name> <name>net_repairs</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -11651,27 +11735,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>paint_mat</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>parts</name> <name>parts</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -11819,27 +11882,6 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>shop_mat</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node> <concept_node>
<name>state_tax_amt</name> <name>state_tax_amt</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -10,6 +10,7 @@ import { checkUserSession } from "../redux/user/user.actions";
import { selectCurrentUser } from "../redux/user/user.selectors"; import { selectCurrentUser } from "../redux/user/user.selectors";
import PrivateRoute from "../utils/private-route"; import PrivateRoute from "../utils/private-route";
import "antd/dist/antd.css"; import "antd/dist/antd.css";
import "./App.styles.scss";
const LandingPage = lazy(() => import("../pages/landing/landing.page")); const LandingPage = lazy(() => import("../pages/landing/landing.page"));
const ManagePage = lazy(() => import("../pages/manage/manage.page.container")); const ManagePage = lazy(() => import("../pages/manage/manage.page.container"));

View File

@@ -0,0 +1,10 @@
//Global Styles.
.imex-table-header {
display: flex;
flex-wrap: wrap;
justify-content: center;
&__search {
flex: 1;
}
}

View File

@@ -4,10 +4,11 @@ import { MdRemoveCircleOutline } from "react-icons/md";
export default function AllocationsLabelComponent({ allocation, handleClick }) { export default function AllocationsLabelComponent({ allocation, handleClick }) {
return ( return (
<div style={{ display: "flex" }}> <div style={{ display: "flex", alignItems: "center" }}>
<span> <span>
{`${allocation.employee.first_name || ""} ${allocation.employee {`${allocation.employee.first_name || ""} ${
.last_name || ""} (${allocation.hours || ""})`} allocation.employee.last_name || ""
} (${allocation.hours || ""})`}
</span> </span>
<Icon <Icon
style={{ color: "red", padding: "0px 4px" }} style={{ color: "red", padding: "0px 4px" }}

View File

@@ -8,19 +8,21 @@ import { useTranslation } from "react-i18next";
export default function AllocationsLabelContainer({ allocation, refetch }) { export default function AllocationsLabelContainer({ allocation, refetch }) {
const [deleteAllocation] = useMutation(DELETE_ALLOCATION); const [deleteAllocation] = useMutation(DELETE_ALLOCATION);
const { t } = useTranslation(); const { t } = useTranslation();
const handleClick = e => {
const handleClick = (e) => {
e.preventDefault(); e.preventDefault();
deleteAllocation({ variables: { id: allocation.id } }) deleteAllocation({ variables: { id: allocation.id } })
.then(r => { .then((r) => {
notification["success"]({ notification["success"]({
message: t("allocations.successes.deleted") message: t("allocations.successes.deleted"),
}); });
if (refetch) refetch(); if (refetch) refetch();
}) })
.catch(error => { .catch((error) => {
notification["error"]({ message: t("allocations.errors.deleting") }); notification["error"]({ message: t("allocations.errors.deleting") });
}); });
}; };
return ( return (
<AllocationsLabelComponent <AllocationsLabelComponent
allocation={allocation} allocation={allocation}

View File

@@ -21,7 +21,6 @@ class FcmNotificationComponent extends Component {
.requestPermission() .requestPermission()
.then(async function () { .then(async function () {
const token = await messaging.getToken(); const token = await messaging.getToken();
console.log("Instance Token", token);
client.mutate({ client.mutate({
mutation: UPDATE_FCM_TOKEN, mutation: UPDATE_FCM_TOKEN,
variables: { authEmail: currentUser.email, token: { [token]: true } }, variables: { authEmail: currentUser.email, token: { [token]: true } },

View File

@@ -4,8 +4,9 @@ function FormItemCurrency(props, ref) {
return ( return (
<InputNumber <InputNumber
{...props} {...props}
//formatter={value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")} style={{ width: "initial" }}
// parser={value => value.replace(/\$\s?|(,*)/g, "")} formatter={(value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")}
parser={(value) => value.replace(/\$\s?|(,*)/g, "")}
precision={2} precision={2}
/> />
); );

View File

@@ -10,8 +10,11 @@ import AllocationsAssignmentContainer from "../allocations-assignment/allocation
import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container"; import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container"; import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
import { onlyUnique } from "../../utils/arrayHelper";
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setJobLineEditContext: (context) =>
dispatch(setModalContext({ context: context, modal: "jobLineEdit" })),
setPartsOrderContext: (context) => setPartsOrderContext: (context) =>
dispatch(setModalContext({ context: context, modal: "partsOrder" })), dispatch(setModalContext({ context: context, modal: "partsOrder" })),
}); });
@@ -34,30 +37,20 @@ export function JobLinesComponent({
const columns = [ const columns = [
{ {
title: t("joblines.fields.line_no"), title: "#",
dataIndex: "line_no", dataIndex: "line_no",
key: "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, sorter: (a, b) => a.line_no - b.line_no,
sortOrder: sortOrder:
state.sortedInfo.columnKey === "line_no" && state.sortedInfo.order, state.sortedInfo.columnKey === "line_no" && state.sortedInfo.order,
//ellipsis: true,
editable: true,
width: 75,
}, },
{ {
title: t("joblines.fields.unq_seq"), title: t("joblines.fields.line_ind"),
dataIndex: "unq_seq", dataIndex: "line_ind",
key: "unq_seq", key: "line_ind",
// onFilter: (value, record) => record.ro_number.includes(value), sorter: (a, b) => alphaSort(a.line_ind, b.line_ind),
// filteredValue: state.filteredInfo.text || null,
sorter: (a, b) => a.unq_seq - b.unq_seq,
sortOrder: sortOrder:
state.sortedInfo.columnKey === "unq_seq" && state.sortedInfo.order, state.sortedInfo.columnKey === "line_ind" && state.sortedInfo.order,
//ellipsis: true,
editable: true,
width: 75,
}, },
{ {
title: t("joblines.fields.line_desc"), title: t("joblines.fields.line_desc"),
@@ -67,7 +60,6 @@ export function JobLinesComponent({
sortOrder: sortOrder:
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order, state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
ellipsis: true, ellipsis: true,
editable: true,
}, },
{ {
title: t("joblines.fields.oem_partno"), title: t("joblines.fields.oem_partno"),
@@ -81,8 +73,6 @@ export function JobLinesComponent({
sortOrder: sortOrder:
state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order, state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
ellipsis: true, ellipsis: true,
editable: true,
render: (text, record) => ( render: (text, record) => (
<span> <span>
{record.oem_partno ? record.oem_partno : record.op_code_desc} {record.oem_partno ? record.oem_partno : record.op_code_desc}
@@ -99,24 +89,28 @@ export function JobLinesComponent({
filters: [ filters: [
{ {
text: t("jobs.labels.partsfilter"), 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 onFilter: (value, record) => value.includes(record.part_type),
// 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,
}, },
{ {
title: t("joblines.fields.act_price"), title: t("joblines.fields.act_price"),
dataIndex: "act_price", dataIndex: "act_price",
@@ -125,7 +119,6 @@ export function JobLinesComponent({
sortOrder: sortOrder:
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order, state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
ellipsis: true, ellipsis: true,
render: (text, record) => ( render: (text, record) => (
<CurrencyFormatter>{record.act_price}</CurrencyFormatter> <CurrencyFormatter>{record.act_price}</CurrencyFormatter>
), ),
@@ -134,7 +127,6 @@ export function JobLinesComponent({
title: t("joblines.fields.part_qty"), title: t("joblines.fields.part_qty"),
dataIndex: "part_qty", dataIndex: "part_qty",
key: "part_qty", key: "part_qty",
ellipsis: true,
}, },
{ {
title: t("joblines.fields.total"), title: t("joblines.fields.total"),
@@ -144,7 +136,6 @@ export function JobLinesComponent({
sortOrder: sortOrder:
state.sortedInfo.columnKey === "total" && state.sortedInfo.order, state.sortedInfo.columnKey === "total" && state.sortedInfo.order,
ellipsis: true, ellipsis: true,
render: (text, record) => ( render: (text, record) => (
<CurrencyFormatter> <CurrencyFormatter>
{record.act_price * record.part_qty} {record.act_price * record.part_qty}
@@ -155,6 +146,7 @@ export function JobLinesComponent({
title: t("joblines.fields.mod_lb_hrs"), title: t("joblines.fields.mod_lb_hrs"),
dataIndex: "mod_lb_hrs", dataIndex: "mod_lb_hrs",
key: "mod_lb_hrs", key: "mod_lb_hrs",
responsive: ["lg"],
sorter: (a, b) => a.mod_lb_hrs - b.mod_lb_hrs, sorter: (a, b) => a.mod_lb_hrs - b.mod_lb_hrs,
sortOrder: sortOrder:
state.sortedInfo.columnKey === "mod_lb_hrs" && state.sortedInfo.order, state.sortedInfo.columnKey === "mod_lb_hrs" && state.sortedInfo.order,
@@ -166,12 +158,24 @@ export function JobLinesComponent({
sorter: (a, b) => alphaSort(a.status, b.status), sorter: (a, b) => alphaSort(a.status, b.status),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order, 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"), title: t("allocations.fields.employee"),
dataIndex: "employee", dataIndex: "employee",
key: "employee", key: "employee",
sorter: (a, b) => sorter: (a, b) =>
alphaSort( alphaSort(
a.allocations[0] && a.allocations[0] &&
@@ -194,12 +198,6 @@ export function JobLinesComponent({
/> />
)) ))
: null} : null}
<AllocationsAssignmentContainer
key={record.id}
refetch={refetch}
jobLineId={record.id}
hours={record.mod_lb_hrs}
/>
</span> </span>
), ),
}, },
@@ -208,7 +206,7 @@ export function JobLinesComponent({
dataIndex: "actions", dataIndex: "actions",
key: "actions", key: "actions",
render: (text, record) => ( render: (text, record) => (
<span> <div>
<Button <Button
onClick={() => { onClick={() => {
setJobLineEditContext({ setJobLineEditContext({
@@ -218,7 +216,13 @@ export function JobLinesComponent({
}}> }}>
{t("general.actions.edit")} {t("general.actions.edit")}
</Button> </Button>
</span> <AllocationsAssignmentContainer
key={record.id}
refetch={refetch}
jobLineId={record.id}
hours={record.mod_lb_hrs}
/>
</div>
), ),
}, },
]; ];
@@ -243,16 +247,17 @@ export function JobLinesComponent({
<div> <div>
<PartsOrderModalContainer /> <PartsOrderModalContainer />
<Table <Table
columns={columns}
rowKey='id'
loading={loading}
size='small'
pagination={{ position: "top", defaultPageSize: 50 }}
dataSource={jobLines}
onChange={handleTableChange}
scroll={{ x: true, y: "40rem" }}
title={() => { title={() => {
return ( return (
<div> <div className='imex-table-header'>
<Input.Search
placeholder={t("general.labels.search")}
onChange={(e) => {
e.preventDefault();
setSearchText(e.target.value);
}}
/>
<Button <Button
disabled={selectedLines.length > 0 ? false : true} disabled={selectedLines.length > 0 ? false : true}
onClick={() => { onClick={() => {
@@ -282,11 +287,18 @@ export function JobLinesComponent({
}}> }}>
{t("joblines.actions.new")} {t("joblines.actions.new")}
</Button> </Button>
<div className='imex-table-header__search'>
<Input.Search
placeholder={t("general.labels.search")}
onChange={(e) => {
e.preventDefault();
setSearchText(e.target.value);
}}
/>
</div>
</div> </div>
); );
}} }}
loading={loading}
size='small'
expandedRowRender={(record) => ( expandedRowRender={(record) => (
<div style={{ margin: 0 }}> <div style={{ margin: 0 }}>
<strong>{t("parts_orders.labels.orderhistory")}</strong> <strong>{t("parts_orders.labels.orderhistory")}</strong>
@@ -301,7 +313,6 @@ export function JobLinesComponent({
))} ))}
</div> </div>
)} )}
pagination={{ position: "top", defaultPageSize: 25 }}
rowSelection={{ rowSelection={{
selectedRowKeys: selectedLines.map((item) => item.id), selectedRowKeys: selectedLines.map((item) => item.id),
onSelectAll: (selected, selectedRows, changeRows) => { onSelectAll: (selected, selectedRows, changeRows) => {
@@ -310,10 +321,6 @@ export function JobLinesComponent({
onSelect: (record, selected, selectedRows, nativeEvent) => onSelect: (record, selected, selectedRows, nativeEvent) =>
setSelectedLines(selectedRows), setSelectedLines(selectedRows),
}} }}
columns={columns}
rowKey='id'
dataSource={jobLines}
onChange={handleTableChange}
/> />
</div> </div>
); );

View File

@@ -1,70 +1,59 @@
import { useQuery } from "@apollo/react-hooks"; import { useQuery } from "@apollo/react-hooks";
import React, { useState } from "react"; import React, { useState } from "react";
import { GET_JOB_LINES_BY_PK } from "../../graphql/jobs-lines.queries"; import { GET_JOB_LINES_BY_PK } from "../../graphql/jobs-lines.queries";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
import JobLinesComponent from "./job-lines.component"; import JobLinesComponent from "./job-lines.component";
import { connect } from "react-redux"; function JobLinesContainer({ jobId }) {
import { setModalContext } from "../../redux/modals/modals.actions";
const mapDispatchToProps = dispatch => ({
setJobLineEditContext: context =>
dispatch(setModalContext({ context: context, modal: "jobLineEdit" }))
});
export function JobLinesContainer({ jobId, setJobLineEditContext }) {
const { loading, error, data, refetch } = useQuery(GET_JOB_LINES_BY_PK, { const { loading, error, data, refetch } = useQuery(GET_JOB_LINES_BY_PK, {
variables: { id: jobId }, variables: { id: jobId },
fetchPolicy: "network-only"
}); });
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
const [selectedLines, setSelectedLines] = useState([]); const [selectedLines, setSelectedLines] = useState([]);
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type='error' />;
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 ( return (
<JobLinesComponent <JobLinesComponent
loading={loading} loading={loading}
refetch={refetch} refetch={refetch}
jobLines={ jobLines={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
}
setSearchText={setSearchText} setSearchText={setSearchText}
selectedLines={selectedLines} selectedLines={selectedLines}
setSelectedLines={setSelectedLines} setSelectedLines={setSelectedLines}
jobId={jobId} jobId={jobId}
setJobLineEditContext={setJobLineEditContext}
/> />
); );
} }
export default connect(null, mapDispatchToProps)(JobLinesContainer); export default JobLinesContainer;

View File

@@ -6,6 +6,8 @@ import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { CalculateJob } from "./job-totals.utility"; import { CalculateJob } from "./job-totals.utility";
import "./job-totals-table.styles.scss";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser //currentUser: selectCurrentUser
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -23,231 +25,186 @@ export function JobsTotalsTableComponent({ bodyshop, job }) {
console.log("Totals was falsey."); console.log("Totals was falsey.");
return <LoadingSkeleton />; return <LoadingSkeleton />;
} }
return (
<div>
<Row>
<Descriptions
bordered
size="small"
column={3}
title={t("jobs.labels.rates")}
>
<Descriptions.Item label={t("jobs.fields.rate_laa")}>
<Statistic
value={totals.rates.laa.total.toFormat()}
precision={2}
suffix={`(${totals.rates.laa.hours.toFixed(2)} @ ${
totals.rates.laa.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lab")}>
<Statistic
value={totals.rates.lab.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lab.hours.toFixed(2)} @ ${
totals.rates.lab.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lad")}>
<Statistic
value={totals.rates.lad.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lad.hours.toFixed(2)} @ ${
totals.rates.lad.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lae")}>
<Statistic
value={totals.rates.lae.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lae.hours.toFixed(2)} @ ${
totals.rates.lae.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_laf")}>
<Statistic
value={totals.rates.laf.total.toFormat()}
precision={2}
suffix={`(${totals.rates.laf.hours.toFixed(2)} @ ${
totals.rates.laf.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lag")}>
<Statistic
value={totals.rates.lag.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lag.hours.toFixed(2)} @ ${
totals.rates.lag.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lam")}>
<Statistic
value={totals.rates.lam.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lam.hours.toFixed(2)} @ ${
totals.rates.lam.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lar")}>
<Statistic
value={totals.rates.lar.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lar.hours.toFixed(2)} @ ${
totals.rates.lar.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_las")}>
<Statistic
value={totals.rates.las.total.toFormat()}
precision={2}
suffix={`(${totals.rates.las.hours.toFixed(2)} @ ${
totals.rates.las.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_lau")}>
<Statistic
value={totals.rates.lau.total.toFormat()}
precision={2}
suffix={`(${totals.rates.lau.hours.toFixed(2)} @ ${
totals.rates.lau.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_la1")}>
<Statistic
value={totals.rates.la1.total.toFormat()}
precision={2}
suffix={`(${totals.rates.la1.hours.toFixed(2)} @ ${
totals.rates.la1.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_la2")}>
<Statistic
value={totals.rates.la2.total.toFormat()}
precision={2}
suffix={`(${totals.rates.la2.hours.toFixed(2)} @ ${
totals.rates.la2.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_la3")}>
<Statistic
value={totals.rates.la3.total.toFormat()}
precision={2}
suffix={`(${totals.rates.la3.hours.toFixed(2)} @ ${
totals.rates.la3.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_la4")}>
<Statistic
value={totals.rates.la4.total.toFormat()}
precision={2}
suffix={`(${totals.rates.la4.hours.toFixed(2)} @ ${
totals.rates.la4.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.rate_atp")}>
<Statistic
value={totals.rates.atp.total.toFormat()}
precision={2}
suffix={`(${totals.rates.atp.hours.toFixed(2)} @ ${
totals.rates.atp.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.labels.mapa")}>
<Statistic
value={totals.rates.mapa.total.toFormat()}
precision={2}
suffix={`(${totals.rates.mapa.hours.toFixed(2)} @ ${
totals.rates.mapa.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.labels.shop_mat")}>
<Statistic
value={totals.rates.mash.total.toFormat()}
precision={2}
suffix={`(${totals.rates.mash.hours.toFixed(2)} @ ${
totals.rates.mash.rate
})`}
/>
</Descriptions.Item>
<Descriptions.Item
style={{ color: "red" }}
label={t("jobs.labels.rates_subtotal")}
>
<Statistic value={totals.rates.subtotal.toFormat()} />
</Descriptions.Item>
</Descriptions>
</Row>
<Row>
<Col span={8}>
<Descriptions
bordered
size="small"
column={1}
title={t("jobs.labels.partssubletstotal")}
>
<Descriptions.Item label={t("jobs.labels.partstotal")}>
<Statistic
value={totals.parts.parts.total.toFormat()}
suffix={`(${totals.parts.parts.subtotal.toFormat()} ± ${totals.parts.parts.adjustments.toFormat()})`}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.labels.subletstotal")}>
<Statistic
value={totals.parts.sublets.total.toFormat()}
suffix={`(${totals.parts.sublets.subtotal.toFormat()} ± ${totals.parts.sublets.adjustments.toFormat()})`}
/>
</Descriptions.Item>
</Descriptions>
</Col>
<Col span={8}> return (
<Descriptions <div className='job-totals-container'>
bordered <div className='job-totals-tables'>
size="small" <table className='job-totals-rates-table'>
column={1} <thead>
title={t("jobs.labels.totals")} <tr>
> <th>{t("jobs.labels.rates")}</th>
<Descriptions.Item label={t("jobs.labels.subtotal")}> <th>$</th>
<Statistic value={totals.totals.subtotal.toFormat()} /> <th></th>
</Descriptions.Item> </tr>
<Descriptions.Item label={t("jobs.labels.federal_tax_amt")}> </thead>
<Statistic value={totals.totals.federal_tax.toFormat()} /> <tbody>
</Descriptions.Item> <tr>
<Descriptions.Item label={t("jobs.labels.state_tax_amt")}> <td>{t("jobs.fields.rate_laa")}</td>
<Statistic value={totals.totals.state_tax.toFormat()} /> <td>{totals.rates.laa.total.toFormat()}</td>
</Descriptions.Item> <td>{`(${totals.rates.laa.hours.toFixed(2)} @ ${
<Descriptions.Item label={t("jobs.labels.local_tax_amt")}> totals.rates.laa.rate
<Statistic value={totals.totals.local_tax.toFormat()} /> })`}</td>
</Descriptions.Item> </tr>
</Descriptions> <tr>
</Col> <td>{t("jobs.fields.rate_lab")}</td>
<Col span={8}> <td>{totals.rates.lab.total.toFormat()}</td>
<Statistic <td>{`(${totals.rates.lab.hours.toFixed(2)} @ ${
title={t("jobs.labels.total_repairs")} totals.rates.lab.rate
value={totals.totals.total_repairs.toFormat()} })`}</td>
/> </tr>
<Statistic <tr>
title={t("jobs.labels.net_repairs")} <td>{t("jobs.fields.rate_lad")}</td>
value={totals.totals.net_repairs.toFormat()} <td>{totals.rates.lad.total.toFormat()}</td>
/> <td>{`(${totals.rates.lad.hours.toFixed(2)} @ ${
</Col> totals.rates.lad.rate
</Row> })`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lae")}</td>
<td>{totals.rates.lae.total.toFormat()}</td>
<td>{`(${totals.rates.lae.hours.toFixed(2)} @ ${
totals.rates.lae.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_laf")}</td>
<td>{totals.rates.laf.total.toFormat()}</td>
<td>{`(${totals.rates.laf.hours.toFixed(2)} @ ${
totals.rates.laf.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lag")}</td>
<td>{totals.rates.lag.total.toFormat()}</td>
<td>{`(${totals.rates.lag.hours.toFixed(2)} @ ${
totals.rates.lag.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lam")}</td>
<td>{totals.rates.lam.total.toFormat()}</td>
<td>{`(${totals.rates.lam.hours.toFixed(2)} @ ${
totals.rates.lam.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lar")}</td>
<td>{totals.rates.lar.total.toFormat()}</td>
<td>{`(${totals.rates.lar.hours.toFixed(2)} @ ${
totals.rates.lar.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_las")}</td>
<td>{totals.rates.las.total.toFormat()}</td>
<td>{`(${totals.rates.las.hours.toFixed(2)} @ ${
totals.rates.las.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lau")}</td>
<td>{totals.rates.lau.total.toFormat()}</td>
<td>{`(${totals.rates.lau.hours.toFixed(2)} @ ${
totals.rates.lau.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_la1")}</td>
<td>{totals.rates.la1.total.toFormat()}</td>
<td>{`(${totals.rates.la1.hours.toFixed(2)} @ ${
totals.rates.la1.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_la2")}</td>
<td>{totals.rates.la2.total.toFormat()}</td>
<td>{`(${totals.rates.la2.hours.toFixed(2)} @ ${
totals.rates.la2.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_la3")}</td>
<td>{totals.rates.la3.total.toFormat()}</td>
<td>{`(${totals.rates.la3.hours.toFixed(2)} @ ${
totals.rates.la3.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_la4")}</td>
<td>{totals.rates.la4.total.toFormat()}</td>
<td>{`(${totals.rates.la4.hours.toFixed(2)} @ ${
totals.rates.la4.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_atp")}</td>
<td>{totals.rates.atp.total.toFormat()}</td>
<td>{`(${totals.rates.atp.hours.toFixed(2)} @ ${
totals.rates.atp.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.labels.mapa")}</td>
<td>{totals.rates.mapa.total.toFormat()}</td>
<td>{`(${totals.rates.mapa.hours.toFixed(2)} @ ${
totals.rates.mapa.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.labels.mash")}</td>
<td>{totals.rates.mash.total.toFormat()}</td>
<td>{`(${totals.rates.mash.hours.toFixed(2)} @ ${
totals.rates.mash.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.labels.rates_subtotal")}</td>
<td>{totals.rates.subtotal.toFormat()}</td>
<td></td>
</tr>
</tbody>
</table>
<table className='job-totals-parts-table'>
<tbody>
<tr>
<td>{t("jobs.labels.partstotal")}</td>
<td>{totals.parts.parts.total.toFormat()}</td>
<td>{`(${totals.parts.parts.subtotal.toFormat()} ± ${totals.parts.parts.adjustments.toFormat()})`}</td>
</tr>
<tr>
<td>{t("jobs.labels.subletstotal")}</td>
<td>{totals.parts.sublets.total.toFormat()}</td>
<td>{`(${totals.parts.sublets.subtotal.toFormat()} ± ${totals.parts.sublets.adjustments.toFormat()})`}</td>
</tr>
</tbody>
</table>
</div>
<div className='job-totals-stats'>
<Statistic
title={t("jobs.labels.subtotal")}
value={totals.totals.subtotal.toFormat()}
/>
<Statistic
title={t("jobs.labels.state_tax_amt")}
value={totals.totals.state_tax.toFormat()}
/>
<Statistic
title={t("jobs.labels.local_tax_amt")}
value={totals.totals.local_tax.toFormat()}
/>
<Statistic
title={t("jobs.labels.federal_tax_amt")}
value={totals.totals.federal_tax.toFormat()}
/>
<Statistic
title={t("jobs.labels.total_repairs")}
value={totals.totals.total_repairs.toFormat()}
/>
<Statistic
title={t("jobs.labels.net_repairs")}
value={totals.totals.net_repairs.toFormat()}
/>
</div>
</div> </div>
); );
} }

View File

@@ -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;
}
}

View File

@@ -1,4 +1,4 @@
import { Form, Input, Switch, InputNumber, Typography } from "antd"; import { Form, Input, InputNumber, Switch } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import FormRow from "../layout-form-row/layout-form-row.component"; import FormRow from "../layout-form-row/layout-form-row.component";

View File

@@ -2,131 +2,128 @@ import { Col, Divider, Form, Input, InputNumber, Row } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import JobTotalsTable from "../job-totals-table/job-totals-table.component"; 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 }) { export default function JobsDetailFinancials({ job }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Row> <Row gutter={[32, 32]}>
<Col offset={1} span={7}> <Col span={12}>
<Form.Item label={t("jobs.fields.ded_amt")} name='ded_amt'> <FormRow header={t("jobs.forms.dedinfo")}>
<InputNumber /> <Form.Item label={t("jobs.fields.ded_status")} name='ded_status'>
</Form.Item> <Input />
<Form.Item label={t("jobs.fields.ded_status")} name='ded_status'> </Form.Item>
<Input /> <Form.Item label={t("jobs.fields.ded_amt")} name='ded_amt'>
</Form.Item> <CurrencyInput />
<Form.Item </Form.Item>
label={t("jobs.fields.depreciation_taxes")} </FormRow>
name='depreciation_taxes'> <FormRow>
<InputNumber /> <Form.Item
</Form.Item> label={t("jobs.fields.depreciation_taxes")}
TODO This is equivalent of GST payable. name='depreciation_taxes'>
<Form.Item <CurrencyInput />
label={t("jobs.fields.federal_tax_payable")} </Form.Item>
name='federal_tax_payable'> <Form.Item
<InputNumber /> label={t("jobs.fields.other_amount_payable")}
</Form.Item> name='other_amount_payable'>
TODO equivalent of other customer amount <CurrencyInput />
<Form.Item </Form.Item>
label={t("jobs.fields.other_amount_payable")} <Form.Item
name='other_amount_payable'> label={t("jobs.fields.towing_payable")}
<InputNumber /> name='towing_payable'>
</Form.Item> <CurrencyInput />
<Form.Item </Form.Item>
label={t("jobs.fields.towing_payable")} <Form.Item
name='towing_payable'> label={t("jobs.fields.storage_payable")}
<InputNumber /> name='storage_payable'>
</Form.Item> <CurrencyInput />
<Form.Item </Form.Item>
label={t("jobs.fields.storage_payable")} <Form.Item
name='storage_payable'> label={t("jobs.fields.federal_tax_payable")}
<InputNumber /> name='federal_tax_payable'>
</Form.Item> <CurrencyInput />
<Form.Item </Form.Item>
label={t("jobs.fields.adjustment_bottom_line")} <Form.Item
name='adjustment_bottom_line'> label={t("jobs.fields.adjustment_bottom_line")}
<InputNumber /> name='adjustment_bottom_line'>
</Form.Item> <CurrencyInput />
<Divider /> </Form.Item>
<Form.Item </FormRow>
label={t("jobs.fields.labor_rate_desc")} <FormRow header={t("jobs.forms.laborrates")}>
name='labor_rate_desc'> <Form.Item label={t("jobs.fields.rate_laa")} name='rate_laa'>
<Input /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name='rate_lab'> <Form.Item label={t("jobs.fields.rate_lab")} name='rate_lab'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name='rate_lad'> <Form.Item label={t("jobs.fields.rate_lad")} name='rate_lad'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name='rate_lae'> <Form.Item label={t("jobs.fields.rate_lae")} name='rate_lae'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name='rate_lar'> <Form.Item label={t("jobs.fields.rate_lar")} name='rate_lar'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name='rate_las'> <Form.Item label={t("jobs.fields.rate_las")} name='rate_las'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name='rate_laf'> <Form.Item label={t("jobs.fields.rate_laf")} name='rate_laf'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name='rate_lam'> <Form.Item label={t("jobs.fields.rate_lam")} name='rate_lam'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name='rate_lag'> <Form.Item label={t("jobs.fields.rate_lag")} name='rate_lag'>
<InputNumber /> <CurrencyInput />
</Form.Item> </Form.Item>
Note //TODO Remove ATP rate? <Form.Item label={t("jobs.fields.rate_la1")} name='rate_la1'>
<Form.Item label={t("jobs.fields.rate_atp")} name='rate_atp'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_la2")} name='rate_la2'>
<Form.Item label={t("jobs.fields.rate_lau")} name='rate_lau'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_la3")} name='rate_la3'>
<Form.Item label={t("jobs.fields.rate_la1")} name='rate_la1'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_la4")} name='rate_la4'>
<Form.Item label={t("jobs.fields.rate_la2")} name='rate_la2'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_atp")} name='rate_atp'>
<Form.Item label={t("jobs.fields.rate_la3")} name='rate_la3'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_lau")} name='rate_lau'>
<Form.Item label={t("jobs.fields.rate_la4")} name='rate_la4'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_mapa")} name='rate_mapa'>
<Form.Item label={t("jobs.fields.rate_mapa")} name='rate_mapa'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_mash")} name='rate_mash'>
<Form.Item label={t("jobs.fields.rate_mash")} name='rate_mash'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_mahw")} name='rate_mahw'>
<Form.Item label={t("jobs.fields.rate_mahw")} name='rate_mahw'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_ma2s")} name='rate_ma2s'>
<Form.Item label={t("jobs.fields.rate_ma2s")} name='rate_ma2s'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_ma3s")} name='rate_ma3s'>
<Form.Item label={t("jobs.fields.rate_ma3s")} name='rate_ma3s'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_mabl")} name='rate_mabl'>
<Form.Item label={t("jobs.fields.rate_mabl")} name='rate_mabl'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_macs")} name='rate_macs'>
<Form.Item label={t("jobs.fields.rate_macs")} name='rate_macs'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> <Form.Item label={t("jobs.fields.rate_matd")} name='rate_matd'>
<Form.Item label={t("jobs.fields.rate_matd")} name='rate_matd'> <CurrencyInput />
<InputNumber /> </Form.Item>
</Form.Item> </FormRow>
<Form.Item label={t("jobs.fields.rate_laa")} name='rate_laa'>
<InputNumber />
</Form.Item>
</Col> </Col>
<Col offset={1} span={15}> <Col span={12}>
<JobTotalsTable job={job} /> <JobTotalsTable job={job} />
<p>Mitchell: {JSON.stringify(job.cieca_ttl, null, "\t")}</p>
<p>Mine:{JSON.stringify(job.job_totals, null, "\t")}</p>
</Col> </Col>
</Row> </Row>
); );

View File

@@ -1,10 +1,10 @@
import { DatePicker, Divider, Form, Input, Typography } from "antd"; import { DatePicker, Form, Input } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import FormItemEmail from "../form-items-formatted/email-form-item.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-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 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 }) { export default function JobsDetailInsurance({ job, form }) {
const { getFieldValue } = form; const { getFieldValue } = form;

View File

@@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { Row, Col, Typography } from "antd"; import { Row, Col, Typography } from "antd";
import "./layout-form-row.styles.scss";
export default function LayoutFormRow({ header, children }) { export default function LayoutFormRow({ header, children }) {
if (!!!children.length) { if (!!!children.length) {
@@ -8,7 +9,6 @@ export default function LayoutFormRow({ header, children }) {
} }
const rowGutter = { gutter: [32, 32] }; const rowGutter = { gutter: [32, 32] };
const colSpan = (maxspan) => { const colSpan = (maxspan) => {
console.log("maxspan", maxspan);
return { return {
xs: { xs: {
span: 24, span: 24,
@@ -25,7 +25,7 @@ export default function LayoutFormRow({ header, children }) {
}; };
return ( return (
<div> <div className='imex-form-row'>
{header ? <Typography.Title level={4}>{header}</Typography.Title> : null} {header ? <Typography.Title level={4}>{header}</Typography.Title> : null}
<Row {...rowGutter}> <Row {...rowGutter}>
{children.map((c, idx) => ( {children.map((c, idx) => (

View File

@@ -0,0 +1,6 @@
//Override Antd Row margin to save space on forms.
.imex-form-row {
.ant-row {
margin-bottom: 0rem;
}
}

View File

@@ -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.", "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.", "instanceconflictitle": "Your account is being used elsewhere.",
"loading": "Loading...", "loading": "Loading...",
"loadingapp": "Loading Bodyshop.app", "loadingapp": "Loading $t(titles.app)",
"loadingshop": "Loading shop data...", "loadingshop": "Loading shop data...",
"loggingin": "Authorizing...", "loggingin": "Authorizing...",
"na": "N/A", "na": "N/A",
@@ -487,14 +487,14 @@
"fields": { "fields": {
"act_price": "Actual Price", "act_price": "Actual Price",
"db_price": "Database Price", "db_price": "Database Price",
"line_desc": "Line Description", "line_desc": "Line Desc.",
"line_ind": "S#", "line_ind": "S#",
"line_no": "Line #", "line_no": "Line #",
"mod_lb_hrs": "Labor Hours", "mod_lb_hrs": "Hrs",
"mod_lbr_ty": "Labor Type", "mod_lbr_ty": "Labor Type",
"oem_partno": "OEM Part #", "oem_partno": "OEM Part #",
"op_code_desc": "Operation Code Description", "op_code_desc": "Operation Code Description",
"part_qty": "Quantity", "part_qty": "Qty.",
"part_type": "Part Type", "part_type": "Part Type",
"status": "Status", "status": "Status",
"total": "Total", "total": "Total",
@@ -669,7 +669,9 @@
"forms": { "forms": {
"appraiserinfo": "Appraiser Info", "appraiserinfo": "Appraiser Info",
"claiminfo": "Claim Information", "claiminfo": "Claim Information",
"dedinfo": "Deductible Info",
"inscoinfo": "Insurance Company Information", "inscoinfo": "Insurance Company Information",
"laborrates": "Labor Rates",
"lossinfo": "Loss Information" "lossinfo": "Loss Information"
}, },
"labels": { "labels": {
@@ -713,10 +715,11 @@
"laborallocations": "Labor Allocations", "laborallocations": "Labor Allocations",
"lines": "Estimate Lines", "lines": "Estimate Lines",
"local_tax_amt": "Local Taxes", "local_tax_amt": "Local Taxes",
"mapa": "Paint Materials",
"mash": "Shop Materials",
"net_repairs": "Net Repairs", "net_repairs": "Net Repairs",
"notes": "Notes", "notes": "Notes",
"override_header": "Override estimate header on import?", "override_header": "Override estimate header on import?",
"paint_mat": "Paint Materials",
"parts": "Parts", "parts": "Parts",
"partsfilter": "Parts Only", "partsfilter": "Parts Only",
"partssubletstotal": "Parts & Sublets Total", "partssubletstotal": "Parts & Sublets Total",
@@ -724,7 +727,6 @@
"rates": "Rates", "rates": "Rates",
"rates_subtotal": "Rates Subtotal", "rates_subtotal": "Rates Subtotal",
"reconciliationheader": "Parts & Sublet Reconciliation", "reconciliationheader": "Parts & Sublet Reconciliation",
"shop_mat": "Shop Materials",
"state_tax_amt": "State/Provincial Taxes", "state_tax_amt": "State/Provincial Taxes",
"subletstotal": "Sublets Total", "subletstotal": "Sublets Total",
"subtotal": "Subtotal", "subtotal": "Subtotal",

View File

@@ -364,7 +364,7 @@
"instanceconflictext": "", "instanceconflictext": "",
"instanceconflictitle": "", "instanceconflictitle": "",
"loading": "Cargando...", "loading": "Cargando...",
"loadingapp": "Cargando Bodyshop.app", "loadingapp": "Cargando $t(titles.app)",
"loadingshop": "Cargando datos de la tienda ...", "loadingshop": "Cargando datos de la tienda ...",
"loggingin": "Iniciando sesión ...", "loggingin": "Iniciando sesión ...",
"na": "N / A", "na": "N / A",
@@ -669,7 +669,9 @@
"forms": { "forms": {
"appraiserinfo": "", "appraiserinfo": "",
"claiminfo": "", "claiminfo": "",
"dedinfo": "",
"inscoinfo": "", "inscoinfo": "",
"laborrates": "",
"lossinfo": "" "lossinfo": ""
}, },
"labels": { "labels": {
@@ -713,10 +715,11 @@
"laborallocations": "", "laborallocations": "",
"lines": "Líneas estimadas", "lines": "Líneas estimadas",
"local_tax_amt": "", "local_tax_amt": "",
"mapa": "",
"mash": "",
"net_repairs": "", "net_repairs": "",
"notes": "Notas", "notes": "Notas",
"override_header": "¿Anular encabezado estimado al importar?", "override_header": "¿Anular encabezado estimado al importar?",
"paint_mat": "",
"parts": "Partes", "parts": "Partes",
"partsfilter": "", "partsfilter": "",
"partssubletstotal": "", "partssubletstotal": "",
@@ -724,7 +727,6 @@
"rates": "Tarifas", "rates": "Tarifas",
"rates_subtotal": "", "rates_subtotal": "",
"reconciliationheader": "", "reconciliationheader": "",
"shop_mat": "",
"state_tax_amt": "", "state_tax_amt": "",
"subletstotal": "", "subletstotal": "",
"subtotal": "", "subtotal": "",

View File

@@ -364,7 +364,7 @@
"instanceconflictext": "", "instanceconflictext": "",
"instanceconflictitle": "", "instanceconflictitle": "",
"loading": "Chargement...", "loading": "Chargement...",
"loadingapp": "Chargement de Bodyshop.app", "loadingapp": "Chargement de $t(titles.app)",
"loadingshop": "Chargement des données de la boutique ...", "loadingshop": "Chargement des données de la boutique ...",
"loggingin": "Vous connecter ...", "loggingin": "Vous connecter ...",
"na": "N / A", "na": "N / A",
@@ -669,7 +669,9 @@
"forms": { "forms": {
"appraiserinfo": "", "appraiserinfo": "",
"claiminfo": "", "claiminfo": "",
"dedinfo": "",
"inscoinfo": "", "inscoinfo": "",
"laborrates": "",
"lossinfo": "" "lossinfo": ""
}, },
"labels": { "labels": {
@@ -713,10 +715,11 @@
"laborallocations": "", "laborallocations": "",
"lines": "Estimer les lignes", "lines": "Estimer les lignes",
"local_tax_amt": "", "local_tax_amt": "",
"mapa": "",
"mash": "",
"net_repairs": "", "net_repairs": "",
"notes": "Remarques", "notes": "Remarques",
"override_header": "Remplacer l'en-tête d'estimation à l'importation?", "override_header": "Remplacer l'en-tête d'estimation à l'importation?",
"paint_mat": "",
"parts": "les pièces", "parts": "les pièces",
"partsfilter": "", "partsfilter": "",
"partssubletstotal": "", "partssubletstotal": "",
@@ -724,7 +727,6 @@
"rates": "Les taux", "rates": "Les taux",
"rates_subtotal": "", "rates_subtotal": "",
"reconciliationheader": "", "reconciliationheader": "",
"shop_mat": "",
"state_tax_amt": "", "state_tax_amt": "",
"subletstotal": "", "subletstotal": "",
"subtotal": "", "subtotal": "",

View File

@@ -0,0 +1,3 @@
export function onlyUnique(value, index, self, key) {
return self.indexOf(value) === index;
}