Updating styling on parts and invoicing modals BOD-404

This commit is contained in:
Patrick Fic
2020-09-22 14:23:27 -07:00
parent 43490bbcba
commit 49f6cfa8c1
16 changed files with 431 additions and 333 deletions

View File

@@ -9789,6 +9789,27 @@
<folder_node> <folder_node>
<name>fields</name> <name>fields</name>
<children> <children>
<concept_node>
<name>allpartslocation</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>date</name> <name>date</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -10109,6 +10130,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>invoice_lines</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>invoice_total</name> <name>invoice_total</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -160,6 +160,7 @@ function InvoiceEnterModalContainer({
<Form <Form
onFinish={handleFinish} onFinish={handleFinish}
autoComplete={"off"} autoComplete={"off"}
layout="vertical"
form={form} form={form}
onFinishFailed={() => { onFinishFailed={() => {
setEnterAgain(false); setEnterAgain(false);

View File

@@ -1,4 +1,14 @@
import { Button, Form, Input, Select, Statistic, Switch, Upload } from "antd"; import {
Button,
Form,
Input,
Select,
Space,
Statistic,
Switch,
Typography,
Upload,
} from "antd";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -8,6 +18,7 @@ import AlertComponent from "../alert/alert.component";
import FormDatePicker from "../form-date-picker/form-date-picker.component"; import FormDatePicker from "../form-date-picker/form-date-picker.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobSearchSelect from "../job-search-select/job-search-select.component"; import JobSearchSelect from "../job-search-select/job-search-select.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component"; import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
import InvoiceFormLines from "./invoice-form.lines.component"; import InvoiceFormLines from "./invoice-form.lines.component";
import "./invoice-form.styles.scss"; import "./invoice-form.styles.scss";
@@ -54,8 +65,8 @@ export function InvoiceFormComponent({
}, [form, setDiscount, vendorAutoCompleteOptions, loadLines]); }, [form, setDiscount, vendorAutoCompleteOptions, loadLines]);
return ( return (
<div className="invoice-form-wrapper"> <div>
<div className="invoice-form-invoice-details"> <LayoutFormRow>
<Form.Item <Form.Item
name="jobid" name="jobid"
label={t("invoices.fields.ro_number")} label={t("invoices.fields.ro_number")}
@@ -91,8 +102,9 @@ export function InvoiceFormComponent({
onSelect={handleVendorSelect} onSelect={handleVendorSelect}
/> />
</Form.Item> </Form.Item>
</div> </LayoutFormRow>
<div className="invoice-form-invoice-details">
<LayoutFormRow>
<Form.Item <Form.Item
label={t("invoices.fields.invoice_number")} label={t("invoices.fields.invoice_number")}
name="invoice_number" name="invoice_number"
@@ -167,7 +179,10 @@ export function InvoiceFormComponent({
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
</div> </LayoutFormRow>
<Typography.Title level={4}>
{t("invoices.labels.invoice_lines")}
</Typography.Title>
<InvoiceFormLines <InvoiceFormLines
lineData={lineData} lineData={lineData}
discount={discount} discount={discount}
@@ -211,7 +226,7 @@ export function InvoiceFormComponent({
if (!!totals) if (!!totals)
return ( return (
<div> <div>
<div className="invoice-form-totals"> <Space>
<Statistic <Statistic
title={t("invoices.labels.subtotal")} title={t("invoices.labels.subtotal")}
value={totals.subtotal.toFormat()} value={totals.subtotal.toFormat()}
@@ -251,7 +266,7 @@ export function InvoiceFormComponent({
value={totals.discrepancy.toFormat()} value={totals.discrepancy.toFormat()}
precision={2} precision={2}
/> />
</div> </Space>
{form.getFieldValue("is_credit_memo") ? ( {form.getFieldValue("is_credit_memo") ? (
<AlertComponent <AlertComponent
type="warning" type="warning"

View File

@@ -1,10 +1,19 @@
import { DeleteFilled, WarningOutlined } from "@ant-design/icons"; import { DeleteFilled, WarningOutlined } from "@ant-design/icons";
import { Button, Form, Input, InputNumber, Select, Switch } from "antd"; import {
Button,
Divider,
Form,
Input,
InputNumber,
Select,
Switch,
} from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import InvoiceLineSearchSelect from "../invoice-line-search-select/invoice-line-search-select.component"; import InvoiceLineSearchSelect from "../invoice-line-search-select/invoice-line-search-select.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component"; import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
export default function InvoiceEnterModalLinesComponent({ export default function InvoiceEnterModalLinesComponent({
lineData, lineData,
discount, discount,
@@ -21,197 +30,202 @@ export default function InvoiceEnterModalLinesComponent({
<div className="invoice-form-lines-wrapper"> <div className="invoice-form-lines-wrapper">
{fields.map((field, index) => ( {fields.map((field, index) => (
<Form.Item required={false} key={field.key}> <Form.Item required={false} key={field.key}>
<div className="invoice-form-line"> <div>
<Form.Item <div style={{ display: "flex", alignItems: "center" }}>
label={t("invoicelines.fields.jobline")} <LayoutFormRow style={{ flex: 1 }} grow>
key={`${index}joblinename`} <Form.Item
name={[field.name, "joblineid"]} label={t("invoicelines.fields.jobline")}
rules={[ key={`${index}joblinename`}
{ name={[field.name, "joblineid"]}
required: true, rules={[
message: t("general.validation.required"), {
}, required: true,
]} message: t("general.validation.required"),
> },
<InvoiceLineSearchSelect ]}
options={lineData} >
onSelect={(value, opt) => { <InvoiceLineSearchSelect
setFieldsValue({ options={lineData}
invoicelines: getFieldsValue([ onSelect={(value, opt) => {
"invoicelines", setFieldsValue({
]).invoicelines.map((item, idx) => { invoicelines: getFieldsValue([
if (idx === index) { "invoicelines",
return { ]).invoicelines.map((item, idx) => {
...item, if (idx === index) {
line_desc: opt.line_desc, return {
quantity: opt.part_qty || 1, ...item,
actual_price: opt.cost, line_desc: opt.line_desc,
cost_center: opt.part_type quantity: opt.part_qty || 1,
? responsibilityCenters.defaults.costs[ actual_price: opt.cost,
opt.part_type cost_center: opt.part_type
] || null ? responsibilityCenters.defaults.costs[
: null, opt.part_type
}; ] || null
} : null,
return item; };
}), }
}); return item;
}),
});
}}
/>
</Form.Item>
<Form.Item
label={t("invoicelines.fields.line_desc")}
key={`${index}line_desc`}
name={[field.name, "line_desc"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.quantity")}
key={`${index}quantity`}
name={[field.name, "quantity"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<InputNumber precision={0} min={0} />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.actual")}
key={`${index}actual_price`}
name={[field.name, "actual_price"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput
min={0}
onBlur={(e) => {
setFieldsValue({
invoicelines: getFieldsValue(
"invoicelines"
).invoicelines.map((item, idx) => {
if (idx === index) {
return {
...item,
actual_cost: !!item.actual_cost
? item.actual_cost
: parseFloat(e.target.value) *
(1 - discount),
};
}
return item;
}),
});
}}
/>
</Form.Item>
<Form.Item
label={t("invoicelines.fields.actual_cost")}
key={`${index}actual_cost`}
name={[field.name, "actual_cost"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput min={0} />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
const line = getFieldsValue(["invoicelines"])
.invoicelines[index];
if (!!!line) return null;
const lineDiscount = (
1 -
Math.round(
(line.actual_cost / line.actual_price) * 100
) /
100
).toPrecision(2);
if (lineDiscount - discount === 0) return <div />;
return <WarningOutlined style={{ color: "red" }} />;
}}
</Form.Item>
<Form.Item
label={t("invoicelines.fields.cost_center")}
key={`${index}cost_center`}
name={[field.name, "cost_center"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Select style={{ width: "150px" }}>
{responsibilityCenters.costs.map((item) => (
<Select.Option key={item.name}>
{item.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("invoicelines.fields.federal_tax_applicable")}
key={`${index}fedtax`}
initialValue={true}
valuePropName="checked"
name={[field.name, "applicable_taxes", "federal"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.state_tax_applicable")}
key={`${index}statetax`}
valuePropName="checked"
name={[field.name, "applicable_taxes", "state"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.local_tax_applicable")}
key={`${index}localtax`}
valuePropName="checked"
name={[field.name, "applicable_taxes", "local"]}
>
<Switch />
</Form.Item>
</LayoutFormRow>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
<DeleteFilled
onClick={() => {
remove(field.name);
}} }}
/> />
</Form.Item> </div>
<Divider />
<Form.Item
label={t("invoicelines.fields.line_desc")}
key={`${index}line_desc`}
name={[field.name, "line_desc"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.quantity")}
key={`${index}quantity`}
name={[field.name, "quantity"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<InputNumber precision={0} min={0} />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.actual")}
key={`${index}actual_price`}
name={[field.name, "actual_price"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput
min={0}
onBlur={(e) => {
setFieldsValue({
invoicelines: getFieldsValue(
"invoicelines"
).invoicelines.map((item, idx) => {
if (idx === index) {
return {
...item,
actual_cost: !!item.actual_cost
? item.actual_cost
: parseFloat(e.target.value) * (1 - discount),
};
}
return item;
}),
});
}}
/>
</Form.Item>
<Form.Item
label={t("invoicelines.fields.actual_cost")}
key={`${index}actual_cost`}
name={[field.name, "actual_cost"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<CurrencyInput min={0} />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
const line = getFieldsValue(["invoicelines"])
.invoicelines[index];
if (!!!line) return null;
const lineDiscount = (
1 -
Math.round(
(line.actual_cost / line.actual_price) * 100
) /
100
).toPrecision(2);
if (lineDiscount - discount === 0) return null;
return <WarningOutlined style={{ color: "red" }} />;
}}
</Form.Item>
<Form.Item
label={t("invoicelines.fields.cost_center")}
key={`${index}cost_center`}
name={[field.name, "cost_center"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<Select style={{ width: "150px" }}>
{responsibilityCenters.costs.map((item) => (
<Select.Option key={item.name}>
{item.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("invoicelines.fields.federal_tax_applicable")}
key={`${index}fedtax`}
initialValue={true}
valuePropName="checked"
name={[field.name, "applicable_taxes", "federal"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.state_tax_applicable")}
key={`${index}statetax`}
valuePropName="checked"
name={[field.name, "applicable_taxes", "state"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("invoicelines.fields.local_tax_applicable")}
key={`${index}localtax`}
valuePropName="checked"
name={[field.name, "applicable_taxes", "local"]}
>
<Switch />
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
</div> </div>
</Form.Item> </Form.Item>
))} ))}
<Form.Item> <Form.Item>
<Button <Button
type="dashed"
onClick={() => { onClick={() => {
add(); add();
}} }}
style={{ width: "50%" }} style={{ width: "100%" }}
> >
{t("invoicelines.actions.newline")} {t("invoicelines.actions.newline")}
</Button> </Button>

View File

@@ -1,40 +1,40 @@
.invoice-form-wrapper { // .invoice-form-wrapper {
display: flex; // display: flex;
flex-direction: column; // flex-direction: column;
justify-content: left; // justify-content: left;
} // }
.invoice-form-totals { // .invoice-form-totals {
display: flex; // display: flex;
justify-content: space-around; // justify-content: space-around;
align-items: flex-start; // align-items: flex-start;
flex-wrap: wrap; // flex-wrap: wrap;
& > * { // & > * {
padding: 5px; // padding: 5px;
} // }
} // }
.invoice-form-invoice-details { // .invoice-form-invoice-details {
display: flex; // display: flex;
align-items: flex-start; // align-items: flex-start;
flex-wrap: wrap; // flex-wrap: wrap;
& > * { // & > * {
padding: 5px; // padding: 5px;
} // }
} // }
.invoice-form-lines-wrapper { // .invoice-form-lines-wrapper {
border: 3px ridge rgba(28, 110, 164, 0.24); // border: 3px ridge rgba(28, 110, 164, 0.24);
border-radius: 4px; // border-radius: 4px;
} // }
.invoice-form-line { // .invoice-form-line {
display: flex; // display: flex;
flex-wrap: wrap; // flex-wrap: wrap;
align-items: flex-start; // align-items: flex-start;
justify-content: space-around; // justify-content: space-around;
border-bottom: 2px dashed rgba(7, 7, 7, 0.4); // border-bottom: 2px dashed rgba(7, 7, 7, 0.4);
F & > * { // F & > * {
margin: 5px; // margin: 5px;
} // }
} // }

View File

@@ -25,7 +25,7 @@ const InvoiceLineSearchSelect = (
autoFocus autoFocus
value={option} value={option}
style={{ style={{
width: 300, width: "100%",
}} }}
onChange={setOption} onChange={setOption}
optionFilterProp="line_desc" optionFilterProp="line_desc"
@@ -48,12 +48,18 @@ const InvoiceLineSearchSelect = (
<Row justify="center" align="middle"> <Row justify="center" align="middle">
<Col span={12}>{item.line_desc}</Col> <Col span={12}>{item.line_desc}</Col>
<Col span={8}> <Col span={8}>
<Tag color="blue">{item.oem_partno}</Tag> {item.oem_partno ? (
<Tag color="blue">{item.oem_partno}</Tag>
) : null}
</Col> </Col>
<Col span={4}> <Col span={4}>
<Tag color="green"> {item.act_price ? (
<CurrencyFormatter>{item.act_price || 0}</CurrencyFormatter> <Tag color="green">
</Tag> <CurrencyFormatter>
{item.act_price || 0}
</CurrencyFormatter>
</Tag>
) : null}
</Col> </Col>
</Row> </Row>
</Option> </Option>

View File

@@ -315,7 +315,7 @@ export function JobLinesComponent({
setPartsOrderContext({ setPartsOrderContext({
actions: { refetch: refetch }, actions: { refetch: refetch },
context: { context: {
jobId: job.jobId, jobId: job.id,
linesToOrder: selectedLines, linesToOrder: selectedLines,
}, },
}); });
@@ -348,7 +348,7 @@ export function JobLinesComponent({
onClick={() => { onClick={() => {
setJobLineEditContext({ setJobLineEditContext({
actions: { refetch: refetch }, actions: { refetch: refetch },
context: { jobid: job.jobId }, context: { jobid: job.id },
}); });
}} }}
> >
@@ -372,7 +372,7 @@ export function JobLinesComponent({
{record.parts_order_lines.map((item) => ( {record.parts_order_lines.map((item) => (
<div key={item.id}> <div key={item.id}>
<Link <Link
to={`/manage/jobs/${job.jobId}?tab=partssublet&partsorderid=${item.parts_order.id}`} to={`/manage/jobs/${job.id}?tab=partssublet&partsorderid=${item.parts_order.id}`}
> >
{item.parts_order.order_number || ""} {item.parts_order.order_number || ""}
</Link> </Link>

View File

@@ -64,7 +64,7 @@ const JobSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
autoFocus autoFocus
value={option} value={option}
style={{ style={{
width: 300, width: "100%",
}} }}
filterOption={false} filterOption={false}
onSearch={handleSearch} onSearch={handleSearch}

View File

@@ -2,7 +2,12 @@ import React from "react";
import { Row, Col, Typography } from "antd"; import { Row, Col, Typography } from "antd";
import "./layout-form-row.styles.scss"; import "./layout-form-row.styles.scss";
export default function LayoutFormRow({ header, children, grow = false }) { export default function LayoutFormRow({
header,
children,
grow = false,
...restProps
}) {
if (!!!children.length) { if (!!!children.length) {
//We have only one element. It's going to get the whole thing. //We have only one element. It's going to get the whole thing.
return ( return (
@@ -20,7 +25,7 @@ export default function LayoutFormRow({ header, children, grow = false }) {
if (spanOverride) return { span: spanOverride }; if (spanOverride) return { span: spanOverride };
return { return {
xs: { xs: {
span: 24, span: !grow ? 24 : Math.max(12, 24 / children.length),
}, },
sm: { sm: {
span: !grow ? 12 : Math.max(12, 24 / children.length), span: !grow ? 12 : Math.max(12, 24 / children.length),
@@ -38,7 +43,7 @@ export default function LayoutFormRow({ header, children, grow = false }) {
}; };
return ( return (
<div className="imex-form-row"> <div className="imex-form-row" {...restProps}>
{header ? <Typography.Title level={4}>{header}</Typography.Title> : null} {header ? <Typography.Title level={4}>{header}</Typography.Title> : null}
<Row {...rowGutter}> <Row {...rowGutter}>
{children.map( {children.map(

View File

@@ -1,11 +1,12 @@
import { DeleteFilled } from "@ant-design/icons"; import { DeleteFilled } from "@ant-design/icons";
import { Form, Input, InputNumber, Radio } from "antd"; import { Form, Input, InputNumber, Radio, Typography } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import FormDatePicker from "../form-date-picker/form-date-picker.component"; import FormDatePicker from "../form-date-picker/form-date-picker.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component"; import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component"; import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
export default function PartsOrderModalComponent({ export default function PartsOrderModalComponent({
vendorList, vendorList,
@@ -19,85 +20,84 @@ export default function PartsOrderModalComponent({
return ( return (
<div> <div>
<Form.Item <LayoutFormRow>
name="vendorid" <Form.Item
label={t("vendors.fields.name")} name="vendorid"
rules={[ label={t("vendors.fields.name")}
{ rules={[
required: true, {
message: t("general.validation.required"), required: true,
}, message: t("general.validation.required"),
]} },
> ]}
<VendorSearchSelect >
options={vendorList} <VendorSearchSelect
disabled={isReturn} options={vendorList}
preferredMake={preferredMake} disabled={isReturn}
/> preferredMake={preferredMake}
</Form.Item> />
<Form.Item </Form.Item>
name="deliver_by" <Form.Item
rules={[ name="deliver_by"
{ rules={[
required: true, {
message: t("general.validation.required"), required: true,
}, message: t("general.validation.required"),
]} },
label={t("parts_orders.fields.deliver_by")} ]}
> label={t("parts_orders.fields.deliver_by")}
<FormDatePicker /> >
</Form.Item> <FormDatePicker />
{t("parts_orders.labels.inthisorder")} </Form.Item>
</LayoutFormRow>
<Typography.Title level={4}>
{t("parts_orders.labels.inthisorder")}
</Typography.Title>
<Form.List name={["parts_order_lines", "data"]}> <Form.List name={["parts_order_lines", "data"]}>
{(fields, { add, remove, move }) => { {(fields, { add, remove, move }) => {
return ( return (
<div> <div>
{fields.map((field, index) => ( {fields.map((field, index) => (
<Form.Item required={false} key={field.key}> <Form.Item required={false} key={field.key}>
<div style={{ display: "flex" }}> <div style={{ display: "flex", alignItems: "center" }}>
<Form.Item <LayoutFormRow grow style={{ flex: 1 }}>
label={t("parts_orders.fields.line_desc")} <Form.Item
key={`${index}line_desc`} label={t("parts_orders.fields.line_desc")}
name={[field.name, "line_desc"]} key={`${index}line_desc`}
rules={[ name={[field.name, "line_desc"]}
{ rules={[
required: true, {
message: t("general.validation.required"), required: true,
}, message: t("general.validation.required"),
]} },
> ]}
<Input /> >
</Form.Item> <Input />
<Form.Item </Form.Item>
label={t("parts_orders.fields.line_remarks")} <Form.Item
key={`${index}line_remarks`} label={t("parts_orders.fields.line_remarks")}
name={[field.name, "line_remarks"]} key={`${index}line_remarks`}
> name={[field.name, "line_remarks"]}
<Input /> >
</Form.Item> <Input />
<Form.Item </Form.Item>
label={t("parts_orders.fields.db_price")} <Form.Item
key={`${index}db_price`} label={t("parts_orders.fields.act_price")}
name={[field.name, "db_price"]} key={`${index}act_price`}
> name={[field.name, "act_price"]}
<CurrencyInput /> >
</Form.Item> <CurrencyInput />
<Form.Item </Form.Item>
label={t("parts_orders.fields.act_price")} <Form.Item
key={`${index}act_price`} label={t("parts_orders.fields.quantity")}
name={[field.name, "act_price"]} key={`${index}quantity`}
> name={[field.name, "quantity"]}
<CurrencyInput /> >
</Form.Item> <InputNumber />
<Form.Item </Form.Item>
label={t("parts_orders.fields.quantity")} </LayoutFormRow>
key={`${index}quantity`}
name={[field.name, "quantity"]}
>
<InputNumber />
</Form.Item>
<DeleteFilled <DeleteFilled
style={{ margin: "1rem" }}
onClick={() => { onClick={() => {
remove(field.name); remove(field.name);
}} }}

View File

@@ -223,21 +223,24 @@ export function PartsOrderModalContainer({
forceRender forceRender
> >
{error ? <AlertComponent message={error.message} type="error" /> : null} {error ? <AlertComponent message={error.message} type="error" /> : null}
<LoadingSpinner loading={loading}> <Form
<Form form={form}
form={form} layout="vertical"
autoComplete="no" autoComplete="no"
onFinish={handleFinish} onFinish={handleFinish}
initialValues={initialValues} initialValues={initialValues}
> >
{loading ? (
<LoadingSpinner />
) : (
<PartsOrderModalComponent <PartsOrderModalComponent
vendorList={(data && data.vendors) || []} vendorList={(data && data.vendors) || []}
sendTypeState={sendTypeState} sendTypeState={sendTypeState}
isReturn={isReturn} isReturn={isReturn}
preferredMake={data && data.jobs[0] && data.jobs[0].v_make_desc} preferredMake={data && data.jobs[0] && data.jobs[0].v_make_desc}
/> />
</Form> )}
</LoadingSpinner> </Form>
</Modal> </Modal>
); );
} }

View File

@@ -52,7 +52,7 @@ export function ScheduleJobModalContainer({
const [updateJobStatus] = useMutation(UPDATE_JOBS); const [updateJobStatus] = useMutation(UPDATE_JOBS);
useEffect(() => { useEffect(() => {
form.resetFields(); if (job) form.resetFields();
}, [job, form]); }, [job, form]);
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -1,4 +1,4 @@
import { Select, Tag } from "antd"; import { Col, Row, Select, Tag } from "antd";
import React, { useEffect, useState, forwardRef } from "react"; import React, { useEffect, useState, forwardRef } from "react";
import { HeartOutlined } from "@ant-design/icons"; import { HeartOutlined } from "@ant-design/icons";
const { Option } = Select; const { Option } = Select;
@@ -30,7 +30,7 @@ const VendorSearchSelect = (
showSearch showSearch
value={option} value={option}
style={{ style={{
width: 300, width: "100%",
}} }}
onChange={setOption} onChange={setOption}
optionFilterProp="name" optionFilterProp="name"
@@ -45,21 +45,27 @@ const VendorSearchSelect = (
name={o.name} name={o.name}
discount={o.discount} discount={o.discount}
> >
<div style={{ display: "flex" }}> <Row>
{o.name} <Col span={16}>{o.name}</Col>
<Tag color="green">{`${o.discount * 100}%`}</Tag> <Col span={4}>
<HeartOutlined /> <HeartOutlined />
</div> </Col>
<Col span={4}>
<Tag color="green">{`${o.discount * 100}%`}</Tag>
</Col>
</Row>
</Option> </Option>
)) ))
: null} : null}
{options {options
? options.map((o) => ( ? options.map((o) => (
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}> <Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
<div style={{ display: "flex" }}> <Row>
{o.name} <Col span={20}>{o.name}</Col>
<Tag color="green">{`${o.discount * 100}%`}</Tag> <Col span={4}>
</div> <Tag color="green">{`${o.discount * 100}%`}</Tag>
</Col>
</Row>
</Option> </Option>
)) ))
: null} : null}

View File

@@ -652,6 +652,7 @@
"validation": "Please ensure all fields are entered correctly. " "validation": "Please ensure all fields are entered correctly. "
}, },
"fields": { "fields": {
"allpartslocation": "Parts Bin",
"date": "Invoice Date", "date": "Invoice Date",
"federal_tax_rate": "Federal Tax Rate", "federal_tax_rate": "Federal Tax Rate",
"invoice_number": "Invoice Number", "invoice_number": "Invoice Number",
@@ -669,6 +670,7 @@
"entered_total": "Total of Entered Lines", "entered_total": "Total of Entered Lines",
"enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.", "enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.",
"federal_tax": "Federal Tax", "federal_tax": "Federal Tax",
"invoice_lines": "Invoice Lines",
"invoice_total": "Invoice Total Amount", "invoice_total": "Invoice Total Amount",
"invoices": "Invoices", "invoices": "Invoices",
"local_tax": "Local Tax", "local_tax": "Local Tax",

View File

@@ -652,6 +652,7 @@
"validation": "" "validation": ""
}, },
"fields": { "fields": {
"allpartslocation": "",
"date": "", "date": "",
"federal_tax_rate": "", "federal_tax_rate": "",
"invoice_number": "", "invoice_number": "",
@@ -669,6 +670,7 @@
"entered_total": "", "entered_total": "",
"enteringcreditmemo": "", "enteringcreditmemo": "",
"federal_tax": "", "federal_tax": "",
"invoice_lines": "",
"invoice_total": "", "invoice_total": "",
"invoices": "", "invoices": "",
"local_tax": "", "local_tax": "",

View File

@@ -652,6 +652,7 @@
"validation": "" "validation": ""
}, },
"fields": { "fields": {
"allpartslocation": "",
"date": "", "date": "",
"federal_tax_rate": "", "federal_tax_rate": "",
"invoice_number": "", "invoice_number": "",
@@ -669,6 +670,7 @@
"entered_total": "", "entered_total": "",
"enteringcreditmemo": "", "enteringcreditmemo": "",
"federal_tax": "", "federal_tax": "",
"invoice_lines": "",
"invoice_total": "", "invoice_total": "",
"invoices": "", "invoices": "",
"local_tax": "", "local_tax": "",