Minor fixed + refactored job details screens based on review.

This commit is contained in:
Patrick Fic
2020-08-18 16:43:04 -07:00
parent 9b9feffdfa
commit 534e0a0398
79 changed files with 4119 additions and 909 deletions

View File

@@ -15,7 +15,7 @@ describe("AllocationsAssignmentComponent component", () => {
assignment: {},
setAssignment: jest.fn(),
visibilityState: [false, jest.fn()],
maxHours: 4
maxHours: 4,
};
wrapper = mount(<AllocationsAssignmentComponent {...mockProps} />);
@@ -27,7 +27,6 @@ describe("AllocationsAssignmentComponent component", () => {
it("should render a list of employees", () => {
const empList = wrapper.find("#employeeSelector");
console.log(empList.debug());
expect(empList.children()).to.have.lengthOf(2);
});

View File

@@ -6,7 +6,7 @@ import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
bodyshop: selectBodyshop,
});
export default connect(
@@ -18,12 +18,11 @@ export default connect(
handleAssignment,
assignment,
setAssignment,
visibilityState
visibilityState,
}) {
const { t } = useTranslation();
const onChange = e => {
console.log("e", e);
const onChange = (e) => {
setAssignment({ ...assignment, employeeid: e });
};
@@ -34,13 +33,14 @@ export default connect(
<Select
showSearch
style={{ width: 200 }}
placeholder='Select a person'
optionFilterProp='children'
placeholder="Select a person"
optionFilterProp="children"
onChange={onChange}
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}>
{bodyshop.employees.map(emp => (
}
>
{bodyshop.employees.map((emp) => (
<Select.Option value={emp.id} key={emp.id}>
{`${emp.first_name} ${emp.last_name}`}
</Select.Option>
@@ -48,9 +48,10 @@ export default connect(
</Select>
<Button
type='primary'
type="primary"
disabled={!assignment.employeeid}
onClick={handleAssignment}>
onClick={handleAssignment}
>
Assign
</Button>
<Button onClick={() => setVisibility(false)}>Close</Button>

View File

@@ -12,13 +12,11 @@ export default function ContractLicenseDecodeButton({ form }) {
const [modalVisible, setModalVisible] = useState(false);
const [loading, setLoading] = useState(false);
const [decodedBarcode, setDecodedBarcode] = useState(null);
console.log("form", form);
const handleDecode = (e) => {
logImEXEvent("contract_license_decode");
setLoading(true);
const aamvaParse = aamva.parse(e.currentTarget.value);
console.log("AAMVA", aamvaParse);
setDecodedBarcode(aamvaParse);
setLoading(false);
};
@@ -61,7 +59,8 @@ export default function ContractLicenseDecodeButton({ form }) {
okText={t("contracts.actions.senddltoform")}
onOk={handleInsertForm}
okButtonProps={{ disabled: !!!decodedBarcode }}
onCancel={handleCancel}>
onCancel={handleCancel}
>
<div>
<div>
<Input

View File

@@ -38,7 +38,6 @@ const mapDispatchToProps = (dispatch) => ({
export function DashboardGridComponent({ currentUser, bodyshop }) {
const { loading, error, data } = useQuery(QUERY_DASHBOARD_DETAILS);
console.log("DashboardGridComponent -> data", data)
const { t } = useTranslation();
const [state, setState] = useState({
layout: bodyshop.associations[0].user.dashboardlayout || [
@@ -70,7 +69,6 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
const idxToRemove = state.layout.findIndex((i) => i.i === key);
const newLayout = state.layout;
newLayout.splice(idxToRemove, 1);
console.log(newLayout);
handleLayoutChange(newLayout);
};
@@ -100,14 +98,15 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
<Menu.Item
key={key}
value={key}
disabled={existingLayoutKeys.includes(key)}>
disabled={existingLayoutKeys.includes(key)}
>
{componentList[key].label}
</Menu.Item>
))}
</Menu>
);
if (error) return <AlertComponent message={error.message} type='error' />;
if (error) return <AlertComponent message={error.message} type="error" />;
return (
<div>
@@ -115,12 +114,13 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
<Button>{t("dashboard.actions.addcomponent")}</Button>
</Dropdown>
<ResponsiveReactGridLayout
className='layout'
className="layout"
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
width='100%'
width="100%"
onLayoutChange={handleLayoutChange}
onBreakpointChange={onBreakpointChange}>
onBreakpointChange={onBreakpointChange}
>
{state.layout.map((item, index) => {
const TheComponent = componentList[item.i].component;
return (
@@ -139,8 +139,8 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
onClick={() => handleRemoveComponent(item.i)}
/>
<TheComponent
className='dashboard-card'
size='small'
className="dashboard-card"
size="small"
style={{ height: "100%", width: "100%" }}
/>
</LoadingSkeleton>

View File

@@ -62,7 +62,6 @@ export function EmailOverlayContainer({
};
attachments.push(t);
});
console.log("messageOptions", messageOptions);
setSending(true);
try {

View File

@@ -21,7 +21,6 @@ export default function FormsFieldChanged({ form }) {
<Prompt
when={true}
message={(location) => {
//console.log("location", location);
if (loc.pathname === location.pathname) return false;
return t("general.messages.unsavedchangespopup");
}}

View File

@@ -38,8 +38,6 @@ function InvoiceEnterModalContainer({
const [loading, setLoading] = useState(false);
const handleFinish = (values) => {
console.log("handleFinish -> values", values);
setLoading(true);
const { upload, ...remainingValues } = values;
insertInvoice({
@@ -48,11 +46,6 @@ function InvoiceEnterModalContainer({
Object.assign({}, remainingValues, {
invoicelines: {
data: remainingValues.invoicelines.map((i) => {
console.log(
"Initial insert value",
i.joblineid,
i.joblineid === "noline"
);
return {
...i,
joblineid: i.joblineid === "noline" ? null : i.joblineid,

View File

@@ -42,7 +42,6 @@ export function InvoiceExportAllButton({
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
@@ -121,7 +120,8 @@ export function InvoiceExportAllButton({
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type='dashed'>
type="dashed"
>
{t("jobs.actions.exportselected")}
</Button>
);

View File

@@ -41,7 +41,6 @@ export function InvoiceExportButton({
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
@@ -118,7 +117,8 @@ export function InvoiceExportButton({
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type='dashed'>
type="dashed"
>
{t("jobs.actions.export")}
</Button>
);

View File

@@ -159,7 +159,6 @@ export default function InvoiceFormComponent({
style={{ display: invoiceEdit ? "none" : null }}
valuePropName="fileList"
getValueFromEvent={(e) => {
console.log("Upload event:", e);
if (Array.isArray(e)) {
return e;
}

View File

@@ -208,19 +208,12 @@ export function InvoicesListTableComponent({
];
const handleOnInvoiceRowclick = (selectedRows) => {
console.log("selectedRows", selectedRows);
console.log("record.id", record.id);
setSelectedInvoiceLinesByInvoice({
...selectedInvoiceLinesByInvoice,
[record.id]: selectedRows.map((r) => r.id),
});
};
console.log(
"selectedInvoiceLinesByInvoice[record.id]",
selectedInvoiceLinesByInvoice[record.id]
);
return (
<div>
<Typography.Title level={3}>{`${t("invoices.fields.invoice_number")} ${

View File

@@ -20,11 +20,6 @@ export function JobCostingModalComponent({ bodyshop, job }) {
const jobLineTotalsByProfitCenter = job.joblines.reduce(
(acc, val) => {
const laborProfitCenter = defaultProfits[val.mod_lbr_ty] || "?";
// if (!!!laborProfitCenter)
// console.log(
// "Unknown cost/profit center mapping for labor.",
// val.mod_lbr_ty
// );
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
const laborAmount = Dinero({

View File

@@ -15,7 +15,6 @@ export default function JobDetailCardsPartsComponent({ loading, data }) {
joblines_status,
]);
console.log("memoizedData :>> ", memoizedData);
const [state, setState] = useState({ activeIndex: 0 });
const onPieEnter = (data, index) => {
@@ -47,8 +46,6 @@ export default function JobDetailCardsPartsComponent({ loading, data }) {
}
const Calculatedata = (data) => {
console.log("calculating data", data);
if (data.length > 0) {
const statusMapping = {};
data.map((i) => {

View File

@@ -267,7 +267,6 @@ export function JobLinesComponent({
];
const handleTableChange = (pagination, filters, sorter) => {
console.log("filters", filters);
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};

View File

@@ -67,62 +67,77 @@ export function JobEmployeeAssignments({
return (
<div>
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
<DataLabel label={t("jobs.fields.employee_body")}>
{body ? (
<div>
<span>{`${body.first_name || ""} ${body.last_name || ""}`}</span>
<MinusOutlined
operation="body"
onClick={() => handleRemove("body")}
<div style={{ display: "flex" }}>
<DataLabel
label={t("jobs.fields.employee_body")}
style={{ margin: "0rem .5rem" }}
>
{body ? (
<div>
<span>{`${body.first_name || ""} ${
body.last_name || ""
}`}</span>
<MinusOutlined
operation="body"
onClick={() => handleRemove("body")}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "body" });
setVisibility(true);
}}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "body" });
setVisibility(true);
}}
/>
)}
</DataLabel>
<DataLabel label={t("jobs.fields.employee_prep")}>
{prep ? (
<div>
<span>{`${prep.first_name || ""} ${prep.last_name || ""}`}</span>
<MinusOutlined
operation="prep"
onClick={() => handleRemove("prep")}
)}
</DataLabel>
<DataLabel
label={t("jobs.fields.employee_prep")}
style={{ margin: "0rem .5rem" }}
>
{prep ? (
<div>
<span>{`${prep.first_name || ""} ${
prep.last_name || ""
}`}</span>
<MinusOutlined
operation="prep"
onClick={() => handleRemove("prep")}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "prep" });
setVisibility(true);
}}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "prep" });
setVisibility(true);
}}
/>
)}
</DataLabel>
<DataLabel label={t("jobs.fields.employee_refinish")}>
{refinish ? (
<div>
<span>{`${refinish.first_name || ""} ${
refinish.last_name || ""
}`}</span>
<MinusOutlined
operation="refinish"
onClick={() => handleRemove("refinish")}
)}
</DataLabel>
<DataLabel
label={t("jobs.fields.employee_refinish")}
style={{ margin: "0rem .5rem" }}
>
{refinish ? (
<div>
<span>{`${refinish.first_name || ""} ${
refinish.last_name || ""
}`}</span>
<MinusOutlined
operation="refinish"
onClick={() => handleRemove("refinish")}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "refinish" });
setVisibility(true);
}}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "refinish" });
setVisibility(true);
}}
/>
)}
</DataLabel>
)}
</DataLabel>
</div>
</Popover>
</div>
);

View File

@@ -30,7 +30,6 @@ export function JobIntakeForm({ formItems, bodyshop }) {
const search = queryString.parse(useLocation().search);
const handleFinish = async (values) => {
console.log("values", values);
setLoading(true);
logImEXEvent("job_complete_intake");
@@ -71,7 +70,6 @@ export function JobIntakeForm({ formItems, bodyshop }) {
}),
});
}
console.log("handleFinish -> result", result);
setLoading(false);
};

View File

@@ -16,11 +16,6 @@ export default function JobReconciliationModalComponent({ job, invoices }) {
)
.flat() || [];
console.log(
"JobReconciliationModalComponent -> invoiceLineData",
invoiceLineData
);
const jobLineData = job.joblines.filter((j) => j.part_type !== null);
return (

View File

@@ -1,4 +1,4 @@
import { Statistic } from "antd";
import { Statistic, Typography, Row, Col } from "antd";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -13,6 +13,11 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const colSpan = {
md: { span: 24 },
lg: { span: 12 },
};
export function JobsTotalsTableComponent({ bodyshop, job }) {
const { t } = useTranslation();
const [totals, setTotals] = useState(null);
@@ -26,194 +31,251 @@ export function JobsTotalsTableComponent({ bodyshop, job }) {
}
return (
<div className='job-totals-container'>
<div className='job-totals-tables'>
<table className='job-totals-rates-table'>
<thead>
<tr>
<th>{t("jobs.labels.rates")}</th>
<th>$</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>{t("jobs.fields.rate_laa")}</td>
<td>{totals.rates.laa.total.toFormat()}</td>
<td>{`(${totals.rates.laa.hours.toFixed(2)} @ ${
totals.rates.laa.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lab")}</td>
<td>{totals.rates.lab.total.toFormat()}</td>
<td>{`(${totals.rates.lab.hours.toFixed(2)} @ ${
totals.rates.lab.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lad")}</td>
<td>{totals.rates.lad.total.toFormat()}</td>
<td>{`(${totals.rates.lad.hours.toFixed(2)} @ ${
totals.rates.lad.rate
})`}</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'
onClick={(e) => {
if (e.detail === 3) {
try {
console.log("Job", job);
} catch {
console.log("Unable to show job.");
}
}
}}>
<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>
<Row gutter={[32, 32]}>
<Col {...colSpan}>
<div className="job-totals-half">
<Typography.Title level={4}>
{t("jobs.labels.labortotals")}
</Typography.Title>
<table>
<tbody>
<tr>
<td>{t("jobs.fields.rate_laa")}</td>
<td className="currency">
{totals.rates.laa.total.toFormat()}
</td>
<td>{`(${totals.rates.laa.hours.toFixed(2)} @ ${
totals.rates.laa.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lab")}</td>
<td className="currency">
{totals.rates.lab.total.toFormat()}
</td>
<td>{`(${totals.rates.lab.hours.toFixed(2)} @ ${
totals.rates.lab.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lad")}</td>
<td className="currency">
{totals.rates.lad.total.toFormat()}
</td>
<td>{`(${totals.rates.lad.hours.toFixed(2)} @ ${
totals.rates.lad.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.fields.rate_lae")}</td>
<td className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{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 className="currency">
{totals.rates.atp.total.toFormat()}
</td>
<td>{`(${totals.rates.atp.hours.toFixed(2)} @ ${
totals.rates.atp.rate
})`}</td>
</tr>
<tr>
<td>{t("jobs.labels.rates_subtotal")}</td>
<td>{totals.rates.subtotal.toFormat()}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</Col>
<Col {...colSpan}>
<div className="job-totals-half">
<table>
<tbody>
<tr>
<td>{t("jobs.labels.partstotal")}</td>
<td className="currency">
{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 className="currency">
{totals.parts.sublets.total.toFormat()}
</td>
<td>{`(${totals.parts.sublets.subtotal.toFormat()} ± ${totals.parts.sublets.adjustments.toFormat()})`}</td>
</tr>
<tr>
<td>{t("jobs.labels.mapa")}</td>
<td className="currency">
{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 className="currency">
{totals.rates.mash.total.toFormat()}
</td>
<td>{`(${totals.rates.mash.hours.toFixed(2)} @ ${
totals.rates.mash.rate
})`}</td>
</tr>
</tbody>
</table>
<div
className="job-totals-stats"
onClick={(e) => {
if (e.detail === 3) {
try {
console.log("Job", job);
} catch {
console.log("Unable to show job.");
}
}
}}
>
<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()}
/>
</div>
<div
className="job-totals-stats"
onClick={(e) => {
if (e.detail === 3) {
try {
console.log("Job", job);
} catch {
console.log("Unable to show job.");
}
}
}}
>
<Statistic
title={t("jobs.labels.subtotal")}
value={totals.totals.subtotal.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>
</Col>
</Row>
</div>
);
}

View File

@@ -1,24 +1,38 @@
.job-totals-container {
display: flex;
flex-flow: wrap;
}
.job-totals-tables {
.job-totals-half {
flex: 1;
display: block;
}
display: flex;
flex-direction: column;
align-items: center;
.job-totals-rates-table,
.job-totals-parts-table {
border: black;
width: 100%;
table {
border: 1px solid #ccc;
border-collapse: collapse;
margin: 0;
padding: 0;
width: 80%;
table-layout: fixed;
}
table tr {
//background-color: #f8f8f8;
border: 1px solid #ddd;
padding: 0.35em;
}
table th,
table td {
padding: 0.625em;
//text-align: center;
}
table td.currency {
text-align: right;
}
}
.job-totals-stats {
margin: 1rem;
display: flex;
flex-direction: column;
align-content: center;
.ant-statistic {
margin: 0.5rem;
}
width: 100%;
//flex-direction: column;
justify-content: space-evenly;
}

View File

@@ -67,7 +67,6 @@ export function JobsAvailableSupplementContainer({
} else {
//create upsert job
let supp = estData.data.available_jobs_by_pk.est_data;
console.log("supp before", supp);
delete supp.owner;
delete supp.vehicle;
@@ -140,11 +139,12 @@ export function JobsAvailableSupplementContainer({
setSelectedJob(null);
};
if (error) return <AlertComponent type='error' message={error.message} />;
if (error) return <AlertComponent type="error" message={error.message} />;
return (
<LoadingSpinner
loading={insertLoading}
message={t("jobs.labels.creating_new_job")}>
message={t("jobs.labels.creating_new_job")}
>
<JobsAvailableSupplementComponent
loading={loading}
data={data}

View File

@@ -1,66 +0,0 @@
import { Form, Input, InputNumber, Switch, Select } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import FormRow from "../layout-form-row/layout-form-row.component";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobsDetailClaims({ bodyshop, job }) {
const { t } = useTranslation();
return (
<div>
<FormRow>
<Form.Item label={t("jobs.fields.csr")} name="csr">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ponumber")} name="po_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.unitnumber")} name="unit_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<InputNumber precision={1} />
</Form.Item>
<Form.Item label={t("jobs.fields.kmout")} name="kmout">
<InputNumber precision={1} />
</Form.Item>
<Form.Item
label={t("jobs.fields.exempt")}
valuePropName="checked"
name="exempt"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.specialcoveragepolicy")}
valuePropName="checked"
name="special_coverage_policy"
>
<Switch />
</Form.Item>
</FormRow>
<Form.Item label={t("jobs.fields.referralsource")} name="referral_source">
<Select>
{bodyshop.md_referral_sources.map((s) => (
<Select.Option key={s} value={s}>
{s}
</Select.Option>
))}
</Select>
</Form.Item>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailClaims);

View File

@@ -1,215 +0,0 @@
import { Col, Divider, Form, Row, Select } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobTotalsTable from "../job-totals-table/job-totals-table.component";
import FormRow from "../layout-form-row/layout-form-row.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
export function JobsDetailFinancials({ job, bodyshop }) {
const { t } = useTranslation();
const colSpan = {
sm: { span: 24 },
lg: { span: 12 },
};
return (
<div>
<Row>
<Col span={24}>
<FormRow header={t("payments.labels.title")}>
<table style={{ width: "100%" }}>
<thead>
<tr>
<th>{t("payments.fields.created_at")}</th>
<th>{t("payments.fields.payer")}</th>
<th>{t("payments.fields.amount")}</th>
<th>{t("payments.fields.memo")}</th>
<th>{t("payments.fields.type")}</th>
<th>{t("payments.fields.transactionid")}</th>
<th>{t("payments.fields.stripeid")}</th>
</tr>
</thead>
<tbody>
{job.payments.map((p, idx) => (
<tr key={idx}>
<td>
<DateTimeFormatter>{p.created_at}</DateTimeFormatter>
</td>
<td>{p.payer}</td>
<td>
<CurrencyFormatter>{p.amount}</CurrencyFormatter>
</td>
<td>{p.memo}</td>
<td>{p.type}</td>
<td>{p.transactionid}</td>
<td>
{p.stripeid ? (
<a
href={
stripeTestEnv
? `https://dashboard.stripe.com/${bodyshop.stripe_acct_id}/test/payments/${p.stripeid}`
: `https://dashboard.stripe.com/${bodyshop.stripe_acct_id}/payments/${p.stripeid}`
}
>
{p.stripeid}
</a>
) : null}
</td>
</tr>
))}
</tbody>
</table>
</FormRow>
</Col>
</Row>
<Divider />
<Row gutter={[32, 32]}>
<Col {...colSpan}>
<FormRow header={t("jobs.forms.dedinfo")}>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
<Select>
<Select.Option value="W">
{t("jobs.labels.deductible.waived")}
</Select.Option>
<Select.Option value="Y">
{t("jobs.labels.deductible.yes")}
</Select.Option>
<Select.Option value="N">
{t("jobs.labels.deductible.no")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
<CurrencyInput />
</Form.Item>
</FormRow>
<FormRow>
<Form.Item
label={t("jobs.fields.depreciation_taxes")}
name="depreciation_taxes"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.other_amount_payable")}
name="other_amount_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.towing_payable")}
name="towing_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.storage_payable")}
name="storage_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.federal_tax_payable")}
name="federal_tax_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.adjustment_bottom_line")}
name="adjustment_bottom_line"
>
<CurrencyInput />
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.laborrates")}>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_atp")} name="rate_atp">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<CurrencyInput />
</Form.Item>
</FormRow>
</Col>
<Col {...colSpan}>
<JobTotalsTable job={job} />
</Col>
</Row>
</div>
);
}
export default connect(mapStateToProps, null)(JobsDetailFinancials);

View File

@@ -1,19 +1,56 @@
import { Form, Input } from "antd";
import { Form, Input, InputNumber, Select, Switch } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import FormDatePicker from "../form-date-picker/form-date-picker.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormItemEmail from "../form-items-formatted/email-form-item.component";
import FormItemPhone from "../form-items-formatted/phone-form-item.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 mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobsDetailGeneral({ bodyshop, job, form }) {
const { getFieldValue } = form;
const { t } = useTranslation();
return (
<div>
<FormRow header={t("jobs.forms.inscoinfo")}>
<FormRow header={t("jobs.forms.claiminfo")}>
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
<Select>
<Select.Option value="W">
{t("jobs.labels.deductible.waived")}
</Select.Option>
<Select.Option value="Y">
{t("jobs.labels.deductible.yes")}
</Select.Option>
<Select.Option value="N">
{t("jobs.labels.deductible.no")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.regie_number")} name="regie_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_co_id")} name="ins_co_id">
<Input />
</Form.Item>
@@ -47,19 +84,21 @@ export default function JobsDetailInsurance({ job, form }) {
>
<FormItemEmail email={getFieldValue("ins_ea")} />
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.claiminfo")}>
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.regie_number")} name="regie_number">
<Input />
<Form.Item
label={t("jobs.fields.referralsource")}
name="referral_source"
>
<Select>
{bodyshop.md_referral_sources.map((s) => (
<Select.Option key={s} value={s}>
{s}
</Select.Option>
))}
</Select>
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.lossinfo")}>
<FormRow header={t("jobs.forms.lossinfo")} grow>
<div style={{ display: "inline", height: "8rem" }}>
{job.area_of_damage ? (
<Car
@@ -76,6 +115,31 @@ export default function JobsDetailInsurance({ job, form }) {
<Form.Item label={t("jobs.fields.loss_date")} name="loss_date">
<FormDatePicker />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<InputNumber precision={1} />
</Form.Item>
<Form.Item label={t("jobs.fields.kmout")} name="kmout">
<InputNumber precision={1} />
</Form.Item>
<Form.Item label={t("jobs.fields.ponumber")} name="po_number">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.unitnumber")} name="unit_number">
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.specialcoveragepolicy")}
valuePropName="checked"
name="special_coverage_policy"
>
<Switch />
</Form.Item>
<Form.Item
label={t("jobs.fields.tax_registration_number")}
name="tax_registration_number"
>
<Input />
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.appraiserinfo")}>
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
@@ -103,10 +167,15 @@ export default function JobsDetailInsurance({ job, form }) {
<FormItemEmail email={getFieldValue("est_ea")} />
</Form.Item>
</FormRow>
<FormRow header="TODO: TO BE PLACED">
<Form.Item label={t("jobs.fields.pay_date")} name="pay_date">
<FormRow header={t("jobs.forms.other")}>
<Form.Item label={t("jobs.fields.csr")} name="csr">
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.category")} name="category">
<Select />
</Form.Item>
<Form.Item
label={t("jobs.fields.selling_dealer")}
name="selling_dealer"
@@ -131,8 +200,8 @@ export default function JobsDetailInsurance({ job, form }) {
>
<Input />
</Form.Item>
TODO: Adding servicing/selling dealer contact info?
</FormRow>
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsDetailGeneral);

View File

@@ -39,8 +39,6 @@ export default function DuplicateJob(
variables: { job: [existingJob] },
})
.then((res2) => {
console.log("res2", res2);
if (completionCallback)
completionCallback(res2.data.insert_jobs.returning[0].id);
});

View File

@@ -1,19 +1,8 @@
import { DownCircleFilled, PrinterFilled } from "@ant-design/icons";
import {
Button,
Checkbox,
Descriptions,
Dropdown,
Menu,
notification,
PageHeader,
Tag,
} from "antd";
import { Button, Dropdown, Menu, notification, PageHeader, Tag } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import Moment from "react-moment";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
@@ -21,9 +10,8 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
import JobsDetailHeaderActions from "../jobs-detail-header-actions/jobs-detail-header-actions.component";
import OwnerTagPopoverComponent from "../owner-tag-popover/owner-tag-popover.component";
import VehicleTagPopoverComponent from "../vehicle-tag-popover/vehicle-tag-popover.component";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
import "./jobs-detail-header.styles.scss";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -136,67 +124,22 @@ export function JobsDetailHeader({
>
{t("jobs.labels.inproduction")}
</Tag>,
<Tag title={t("jobs.fields.repairtotal")} key="total" color="green">
<CurrencyFormatter>{job.clm_total}</CurrencyFormatter>
</Tag>,
<Tag
title={t("jobs.fields.customerowing")}
key="custowing"
color="green"
>
<CurrencyFormatter>{job.owner_owing}</CurrencyFormatter>
</Tag>,
]}
extra={menuExtra}
>
<Descriptions
size="small"
column={{ xs: 1, sm: 1, md: 2, lg: 3, xl: 3, xxl: 6 }}
>
<Descriptions.Item key="total" label={t("jobs.fields.repairtotal")}>
<CurrencyFormatter>{job.clm_total}</CurrencyFormatter>
</Descriptions.Item>
<Descriptions.Item
key="custowing"
label={t("jobs.fields.customerowing")}
>
<CurrencyFormatter>{job.owner_owing}</CurrencyFormatter>
</Descriptions.Item>
<Descriptions.Item
key="scp"
label={t("jobs.fields.specialcoveragepolicy")}
>
<Checkbox checked={job.special_coverage_policy} />
</Descriptions.Item>
<Descriptions.Item
key="sched_comp"
label={t("jobs.fields.scheduled_completion")}
>
{job.scheduled_completion ? (
<Moment format="MM/DD/YYYY">{job.scheduled_completion}</Moment>
) : null}
</Descriptions.Item>
<Descriptions.Item key="servicecar" label={t("jobs.fields.servicecar")}>
{job.cccontracts &&
job.cccontracts.map((item) => (
<Link
key={item.id}
to={`/manage/courtesycars/contracts/${item.id}`}
>
<div>
<div>{`${item.courtesycar.year} ${item.courtesycar.make} ${item.courtesycar.model} (${item.courtesycar.plate})`}</div>
<div style={{ display: "inline-block" }}>
<DateTimeFormatter>{item.start}</DateTimeFormatter>
<span> -- </span>
<DateTimeFormatter>
{item.scheduledreturn}
</DateTimeFormatter>
</div>
</div>
</Link>
))}
</Descriptions.Item>
<Descriptions.Item
key="assignments"
label={t("jobs.labels.employeeassignments")}
>
<JobEmployeeAssignments job={job} />
</Descriptions.Item>
</Descriptions>
<div style={{ display: "flex", justifyContent: "flex-end" }}>
<JobEmployeeAssignments job={job} />
</div>
</PageHeader>
);
}

View File

@@ -0,0 +1,139 @@
import { Col, Divider, Form, Row, Select } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobTotalsTable from "../job-totals-table/job-totals-table.component";
import FormRow from "../layout-form-row/layout-form-row.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
export function JobsDetailRates({ job, bodyshop }) {
const { t } = useTranslation();
return (
<div>
<FormRow>
<Form.Item label={t("jobs.fields.class")} name="class">
<Select disabled={true} />
</Form.Item>
<Form.Item
label={t("jobs.fields.depreciation_taxes")}
name="depreciation_taxes"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.other_amount_payable")}
name="other_amount_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.towing_payable")}
name="towing_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.storage_payable")}
name="storage_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.federal_tax_payable")}
name="federal_tax_payable"
>
<CurrencyInput />
</Form.Item>
<Form.Item
label={t("jobs.fields.adjustment_bottom_line")}
name="adjustment_bottom_line"
>
<CurrencyInput />
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.laborrates")}>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_atp")} name="rate_atp">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<CurrencyInput />
</Form.Item>
</FormRow>
</div>
);
}
export default connect(mapStateToProps, null)(JobsDetailRates);

View File

@@ -0,0 +1,81 @@
import { Col, Divider, Form, Row, Select, Typography } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobTotalsTable from "../job-totals-table/job-totals-table.component";
import FormRow from "../layout-form-row/layout-form-row.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
export function JobsDetailTotals({ job, bodyshop }) {
const { t } = useTranslation();
const colSpan = {
sm: { span: 24 },
lg: { span: 12 },
};
return (
<div>
<Typography.Title level={4}>
{t("payments.labels.title")}
</Typography.Title>
<table style={{ width: "100%" }}>
<thead>
<tr>
<th>{t("payments.fields.created_at")}</th>
<th>{t("payments.fields.payer")}</th>
<th>{t("payments.fields.amount")}</th>
<th>{t("payments.fields.memo")}</th>
<th>{t("payments.fields.type")}</th>
<th>{t("payments.fields.transactionid")}</th>
<th>{t("payments.fields.stripeid")}</th>
</tr>
</thead>
<tbody>
{job.payments.map((p, idx) => (
<tr key={idx}>
<td>
<DateTimeFormatter>{p.created_at}</DateTimeFormatter>
</td>
<td>{p.payer}</td>
<td>
<CurrencyFormatter>{p.amount}</CurrencyFormatter>
</td>
<td>{p.memo}</td>
<td>{p.type}</td>
<td>{p.transactionid}</td>
<td>
{p.stripeid ? (
<a
href={
stripeTestEnv
? `https://dashboard.stripe.com/${bodyshop.stripe_acct_id}/test/payments/${p.stripeid}`
: `https://dashboard.stripe.com/${bodyshop.stripe_acct_id}/payments/${p.stripeid}`
}
>
{p.stripeid}
</a>
) : null}
</td>
</tr>
))}
</tbody>
</table>
<Divider />
<JobTotalsTable job={job} />
</div>
);
}
export default connect(mapStateToProps, null)(JobsDetailTotals);

View File

@@ -38,7 +38,6 @@ export function JobsExportAllButton({
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({

View File

@@ -113,7 +113,6 @@ export function PartsOrderModalContainer({
});
if (values.vendorid === bodyshop.inhousevendorid) {
console.log("Inhouse Invoice needs to be psoted.");
logImEXEvent("parts_order_inhouse_invoice");
let invoiceToPost = {

View File

@@ -13,7 +13,6 @@ export default function PartsStatusPie({ partsList }) {
: {};
const pieData = Object.keys(result).map((i) => {
console.log("i", i);
return {
id: i,
label: i,

View File

@@ -23,7 +23,6 @@ export function PaymentFormComponent({
const { t } = useTranslation();
const handleStripeChange = (e) => {
console.log("e", e);
setStripeState({ error: e.error, cardComplete: e.complete });
};

View File

@@ -88,7 +88,6 @@ function InvoiceEnterModalContainer({
},
}
);
console.log("handleFinish -> stripePayment", stripePayment);
if (stripePayment.paymentIntent.status === "succeeded") {
notification["success"]({ message: t("payments.successes.stripe") });
@@ -172,13 +171,15 @@ function InvoiceEnterModalContainer({
okButtonProps={{
loading: loading,
}}
destroyOnClose>
destroyOnClose
>
<Form
onFinish={handleFinish}
autoComplete={"off"}
form={form}
layout='vertical'
initialValues={{ jobid: context.jobId }}>
layout="vertical"
initialValues={{ jobid: context.jobId }}
>
<PaymentForm form={form} stripeStateArr={stripeStateArr} />
</Form>
</Modal>

View File

@@ -38,7 +38,6 @@ export function PaymentsExportAllButton({
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({

View File

@@ -80,13 +80,13 @@ export function ProductionBoardKanbanComponent({ data, bodyshop }) {
let movedCardNewKanbanParent;
if (movedCardWillBeFirst) {
console.log("==> New Card is first.");
//console.log("==> New Card is first.");
movedCardNewKanbanParent = "-1";
} else if (movedCardWillBeLast) {
console.log("==> New Card is last.");
// console.log("==> New Card is last.");
movedCardNewKanbanParent = lastCardInDestinationColumn.id;
} else if (!!newChildCard) {
console.log("==> New Card is somewhere in the middle");
// console.log("==> New Card is somewhere in the middle");
movedCardNewKanbanParent = newChildCard.kanbanparent;
} else {
throw new Error("==> !!!!!!Couldn't find a parent.!!!! <==");

View File

@@ -85,7 +85,6 @@ export const createBoardData = (AllStatuses, Jobs, filter) => {
};
const CheckSearch = (search, job) => {
console.log("job", job, search);
return (
(job.ro_number || "").toLowerCase().includes(search.toLowerCase()) ||
(job.est_number || "")

View File

@@ -41,7 +41,6 @@ export function ProductionListSaveConfigButton({
},
}).then((response) => {
const shopDetails = response.data.update_bodyshops.returning[0];
console.log("handleSaveConfig -> shopDetails", shopDetails);
});
};

View File

@@ -29,7 +29,6 @@ export default function ScheduleJobModalComponent({
},
}
);
console.log("response", response);
setAppData({ ...appData, smartDates: response.data });
} catch (error) {
console.log("error", error, error.message);
@@ -60,7 +59,6 @@ export default function ScheduleJobModalComponent({
className="imex-flex-row__margin"
key={idx}
onClick={() => {
console.log("new Date(d)", new Date(d));
setAppData({
...appData,
start: new moment(d).add(8, "hours"),

View File

@@ -8,7 +8,6 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
const { data } = scoreboardSubscription;
const scoreBoardlist = (data && data.scoreboard) || [];
console.log("ScoreboardDisplayComponent -> scoreBoardlist", scoreBoardlist);
const sbEntriesByDate = {};
@@ -20,7 +19,6 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
sbEntriesByDate[entryDate].push(i);
});
console.log("ScoreboardDisplayComponent -> sbEntriesByDate", sbEntriesByDate);
return (
<div>
<ScoreboardTargetsTable />

View File

@@ -52,7 +52,6 @@ function ShopEmployeesContainer({ bodyshop }) {
};
const handleFinish = (values) => {
console.log("values", values);
if (employeeState[0].id) {
//Update a record.
logImEXEvent("shop_employee_update");
@@ -98,7 +97,7 @@ function ShopEmployeesContainer({ bodyshop }) {
}
};
if (error) return <AlertComponent message={error.message} type='error' />;
if (error) return <AlertComponent message={error.message} type="error" />;
return (
<ShopEmployeeComponent

View File

@@ -18,7 +18,6 @@ export default function ShopTemplateSaveButton({
logImEXEvent("shop_template_update");
emailEditorRef.current.exportHtml(async (data) => {
console.log(data.html);
inlineCss(data.html, {
url: `${window.location.protocol}://${window.location.host}`,
}).then(async function (inlineHtml) {

View File

@@ -27,14 +27,11 @@ export default function ShopTemplateEditorComponent({
const exportJson = (props) => {
emailEditorRef.current.saveDesign((js) => {
seteditorContent({ ...editorContent, JSON: js });
console.log(js);
});
};
const exportHtml = (props) => {
emailEditorRef.current.exportHtml((js) => {
console.log(js);
});
emailEditorRef.current.exportHtml((js) => {});
};
return (

View File

@@ -101,12 +101,7 @@ export default function TimeTicketModalComponent({
},
]}
>
<Select
style={{ width: "150px" }}
onChange={() => {
console.log("Changed.");
}}
>
<Select style={{ width: "150px" }}>
{responsibilityCenters.costs.map((item) => (
<Select.Option key={item.name}>{item.name}</Select.Option>
))}

View File

@@ -31,7 +31,6 @@ export function TimeTicektShiftContainer({
const handleFinish = async (values) => {
setLoading(true);
console.log(values);
const theTime = moment((await axios.post("/utils/time")).data);
const result = await insertTimeTicket({
@@ -71,12 +70,13 @@ export function TimeTicektShiftContainer({
<div>
<Form
form={form}
layout='vertical'
autoComplete='no'
layout="vertical"
autoComplete="no"
onFinish={handleFinish}
initialValues={{ cost_center: t("timetickets.labels.shift") }}>
initialValues={{ cost_center: t("timetickets.labels.shift") }}
>
<TimeTicektShiftComponent form={form} />
<Button htmlType='submit' loading={loading}>
<Button htmlType="submit" loading={loading}>
{t("timetickets.actions.clockin")}
</Button>
</Form>

View File

@@ -78,8 +78,6 @@ export function TimeTicketsSummaryEmployees({
displayTemplateInWindow(html);
};
console.log("jobTickets", jobTickets);
return (
<div>
<List
@@ -96,8 +94,6 @@ export function TimeTicketsSummaryEmployees({
.map((i) => i.cost_center)
.filter(onlyUnique);
console.log("employeeCostCenters", employeeCostCenters);
return employeeCostCenters.map((costCenter) => {
const actHrs = item.tickets
.filter((ticket) => ticket.cost_center === costCenter)

View File

@@ -11,21 +11,24 @@ export default function VehicleTagPopoverComponent({ job }) {
<Col span={12}>
<Descriptions
title={t("owners.labels.fromclaim")}
size='small'
column={1}>
<Descriptions.Item key='1' label={t("jobs.fields.vehicle")}>
{`${job.v_model_yr || t("general.labels.na")}
size="small"
column={1}
>
<Descriptions.Item key="1" label={t("jobs.fields.vehicle")}>
{`${job.v_model_yr || t("general.labels.na")} ${
job.v_color || ""
}
${job.v_make_desc || t("general.labels.na")}
${job.v_model_desc || t("general.labels.na")}`}
</Descriptions.Item>
<Descriptions.Item key='2' label={t("vehicles.fields.plate_no")}>
<Descriptions.Item key="2" label={t("vehicles.fields.plate_no")}>
{`${job.plate_no || t("general.labels.na")}`}
</Descriptions.Item>
<Descriptions.Item key='3' label={t("vehicles.fields.plate_st")}>
<Descriptions.Item key="3" label={t("vehicles.fields.plate_st")}>
{`${job.plate_st || t("general.labels.na")}`}
</Descriptions.Item>
<Descriptions.Item key='4' label={t("vehicles.fields.v_vin")}>
<Descriptions.Item key="4" label={t("vehicles.fields.v_vin")}>
{`${job.v_vin || t("general.labels.na")}`}
</Descriptions.Item>
</Descriptions>
@@ -33,21 +36,22 @@ export default function VehicleTagPopoverComponent({ job }) {
<Col span={12}>
<Descriptions
title={t("owners.labels.fromowner")}
size='small'
column={1}>
<Descriptions.Item key='1' label={t("jobs.fields.vehicle")}>
size="small"
column={1}
>
<Descriptions.Item key="1" label={t("jobs.fields.vehicle")}>
{`${job.vehicle.v_model_yr || t("general.labels.na")}
${job.vehicle.v_make_desc || t("general.labels.na")}
${job.vehicle.v_model_desc || t("general.labels.na")}`}
</Descriptions.Item>
<Descriptions.Item key='2' label={t("vehicles.fields.plate_no")}>
<Descriptions.Item key="2" label={t("vehicles.fields.plate_no")}>
{`${job.vehicle.plate_no || t("general.labels.na")}`}
</Descriptions.Item>
<Descriptions.Item key='3' label={t("vehicles.fields.plate_st")}>
<Descriptions.Item key="3" label={t("vehicles.fields.plate_st")}>
{`${job.vehicle.plate_st || t("general.labels.na")}`}
</Descriptions.Item>
<Descriptions.Item key='4' label={t("vehicles.fields.v_vin")}>
<Descriptions.Item key="4" label={t("vehicles.fields.v_vin")}>
{`${job.vehicle.v_vin || t("general.labels.na")}`}
</Descriptions.Item>
</Descriptions>
@@ -60,11 +64,11 @@ export default function VehicleTagPopoverComponent({ job }) {
);
return (
<Popover placement='bottom' content={content}>
<Tag color='green'>
<Popover placement="bottom" content={content}>
<Tag color="blue">
{job.vehicleid ? (
<Link to={`/manage/vehicles/${job.vehicleid}`}>
{`${job.v_model_yr || ""}
{`${job.v_model_yr || ""} ${job.v_color || ""}
${job.v_make_desc || ""}
${job.v_model_desc || ""} |
${job.plate_no || ""}`}