feature/IO-3499-React-19 - The great button refactor of 2026
This commit is contained in:
@@ -33,13 +33,12 @@ export function BillEnterModalLinesComponent({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
||||||
|
|
||||||
// Keep input row heights consistent with the rest of the table controls.
|
|
||||||
const CONTROL_HEIGHT = 32;
|
const CONTROL_HEIGHT = 32;
|
||||||
|
|
||||||
const normalizeDiscount = (d) => {
|
const normalizeDiscount = (d) => {
|
||||||
const n = Number(d);
|
const n = Number(d);
|
||||||
if (!Number.isFinite(n) || n <= 0) return 0;
|
if (!Number.isFinite(n) || n <= 0) return 0;
|
||||||
return n > 1 ? n / 100 : n; // supports 15 or 0.15
|
return n > 1 ? n / 100 : n;
|
||||||
};
|
};
|
||||||
|
|
||||||
const round2 = (v) => Math.round((v + Number.EPSILON) * 100) / 100;
|
const round2 = (v) => Math.round((v + Number.EPSILON) * 100) / 100;
|
||||||
@@ -79,7 +78,6 @@ export function BillEnterModalLinesComponent({
|
|||||||
return NaN;
|
return NaN;
|
||||||
};
|
};
|
||||||
|
|
||||||
// safe per-field setter (supports AntD 6+ setFieldValue, falls back to setFieldsValue)
|
|
||||||
const setLineField = (index, field, value) => {
|
const setLineField = (index, field, value) => {
|
||||||
if (typeof form.setFieldValue === "function") {
|
if (typeof form.setFieldValue === "function") {
|
||||||
form.setFieldValue(["billlines", index, field], value);
|
form.setFieldValue(["billlines", index, field], value);
|
||||||
@@ -115,7 +113,6 @@ export function BillEnterModalLinesComponent({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getIndicatorShellStyles = (statusColor) => {
|
const getIndicatorShellStyles = (statusColor) => {
|
||||||
// bring back the “colored shell” feel around the $ indicator while keeping row height stable
|
|
||||||
if (isDarkMode) {
|
if (isDarkMode) {
|
||||||
if (statusColor === "green")
|
if (statusColor === "green")
|
||||||
return { borderColor: "rgba(82, 196, 26, 0.75)", background: "rgba(82, 196, 26, 0.10)" };
|
return { borderColor: "rgba(82, 196, 26, 0.75)", background: "rgba(82, 196, 26, 0.10)" };
|
||||||
@@ -145,7 +142,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
minWidth: "10rem",
|
minWidth: "10rem",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}joblinename`,
|
key: `${field.name}joblinename`,
|
||||||
name: [field.name, "joblineid"],
|
name: [field.name, "joblineid"],
|
||||||
label: t("billlines.fields.jobline"),
|
label: t("billlines.fields.jobline"),
|
||||||
rules: [{ required: true }]
|
rules: [{ required: true }]
|
||||||
@@ -203,7 +200,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
minWidth: "10rem",
|
minWidth: "10rem",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}line_desc`,
|
key: `${field.name}line_desc`,
|
||||||
name: [field.name, "line_desc"],
|
name: [field.name, "line_desc"],
|
||||||
label: t("billlines.fields.line_desc"),
|
label: t("billlines.fields.line_desc"),
|
||||||
rules: [{ required: true }]
|
rules: [{ required: true }]
|
||||||
@@ -216,17 +213,19 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
width: "4rem",
|
width: "4rem",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}quantity`,
|
key: `${field.name}quantity`,
|
||||||
name: [field.name, "quantity"],
|
name: [field.name, "quantity"],
|
||||||
label: t("billlines.fields.quantity"),
|
label: t("billlines.fields.quantity"),
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true },
|
{ required: true },
|
||||||
({ getFieldValue: gf }) => ({
|
({ getFieldValue: gf }) => ({
|
||||||
validator(rule, value) {
|
validator(_, value) {
|
||||||
if (value && gf("billlines")[field.fieldKey]?.inventories?.length > value) {
|
const invLen = gf(["billlines", field.name, "inventories"])?.length ?? 0;
|
||||||
|
|
||||||
|
if (value && invLen > value) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
t("bills.validation.inventoryquantity", {
|
t("bills.validation.inventoryquantity", {
|
||||||
number: gf("billlines")[field.fieldKey]?.inventories?.length
|
number: invLen
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -243,7 +242,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
width: "8rem",
|
width: "8rem",
|
||||||
editable: true,
|
editable: true,
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}actual_price`,
|
key: `${field.name}actual_price`,
|
||||||
name: [field.name, "actual_price"],
|
name: [field.name, "actual_price"],
|
||||||
label: t("billlines.fields.actual_price"),
|
label: t("billlines.fields.actual_price"),
|
||||||
rules: [{ required: true }]
|
rules: [{ required: true }]
|
||||||
@@ -295,7 +294,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
width: "10rem",
|
width: "10rem",
|
||||||
skipFormItem: true,
|
skipFormItem: true,
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}actual_cost`,
|
key: `${field.name}actual_cost`,
|
||||||
name: [field.name, "actual_cost"],
|
name: [field.name, "actual_cost"],
|
||||||
label: t("billlines.fields.actual_cost"),
|
label: t("billlines.fields.actual_cost"),
|
||||||
rules: [{ required: true }]
|
rules: [{ required: true }]
|
||||||
@@ -386,7 +385,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
dataIndex: "cost_center",
|
dataIndex: "cost_center",
|
||||||
editable: true,
|
editable: true,
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}cost_center`,
|
key: `${field.name}cost_center`,
|
||||||
name: [field.name, "cost_center"],
|
name: [field.name, "cost_center"],
|
||||||
label: t("billlines.fields.cost_center"),
|
label: t("billlines.fields.cost_center"),
|
||||||
valuePropName: "value",
|
valuePropName: "value",
|
||||||
@@ -409,7 +408,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
label: t("billlines.fields.location"),
|
label: t("billlines.fields.location"),
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}location`,
|
key: `${field.name}location`,
|
||||||
name: [field.name, "location"]
|
name: [field.name, "location"]
|
||||||
}),
|
}),
|
||||||
formInput: () => (
|
formInput: () => (
|
||||||
@@ -430,7 +429,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
width: "40px",
|
width: "40px",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
valuePropName: "checked",
|
valuePropName: "checked",
|
||||||
key: `${field.index}deductedfromlbr`,
|
key: `${field.name}deductedfromlbr`,
|
||||||
name: [field.name, "deductedfromlbr"]
|
name: [field.name, "deductedfromlbr"]
|
||||||
}),
|
}),
|
||||||
formInput: () => <Switch disabled={disabled} />,
|
formInput: () => <Switch disabled={disabled} />,
|
||||||
@@ -516,7 +515,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
width: "40px",
|
width: "40px",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}fedtax`,
|
key: `${field.name}fedtax`,
|
||||||
valuePropName: "checked",
|
valuePropName: "checked",
|
||||||
name: [field.name, "applicable_taxes", "federal"]
|
name: [field.name, "applicable_taxes", "federal"]
|
||||||
}),
|
}),
|
||||||
@@ -531,7 +530,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
width: "40px",
|
width: "40px",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}statetax`,
|
key: `${field.name}statetax`,
|
||||||
valuePropName: "checked",
|
valuePropName: "checked",
|
||||||
name: [field.name, "applicable_taxes", "state"]
|
name: [field.name, "applicable_taxes", "state"]
|
||||||
}),
|
}),
|
||||||
@@ -547,7 +546,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
editable: true,
|
editable: true,
|
||||||
width: "40px",
|
width: "40px",
|
||||||
formItemProps: (field) => ({
|
formItemProps: (field) => ({
|
||||||
key: `${field.index}localtax`,
|
key: `${field.name}localtax`,
|
||||||
valuePropName: "checked",
|
valuePropName: "checked",
|
||||||
name: [field.name, "applicable_taxes", "local"]
|
name: [field.name, "applicable_taxes", "local"]
|
||||||
}),
|
}),
|
||||||
@@ -561,23 +560,28 @@ export function BillEnterModalLinesComponent({
|
|||||||
dataIndex: "actions",
|
dataIndex: "actions",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Form.Item shouldUpdate noStyle>
|
<Form.Item shouldUpdate noStyle>
|
||||||
{() => (
|
{() => {
|
||||||
<Space wrap>
|
const currentLine = getFieldValue(["billlines", record.name]);
|
||||||
<Button
|
const invLen = currentLine?.inventories?.length ?? 0;
|
||||||
icon={<DeleteFilled />}
|
|
||||||
disabled={disabled || getFieldValue("billlines")[record.fieldKey]?.inventories?.length > 0}
|
|
||||||
onClick={() => remove(record.name)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{Simple_Inventory.treatment === "on" && (
|
return (
|
||||||
<BilllineAddInventory
|
<Space wrap>
|
||||||
disabled={!billEdit || form.isFieldsTouched() || form.getFieldValue("is_credit_memo")}
|
<Button
|
||||||
billline={getFieldValue("billlines")[record.fieldKey]}
|
icon={<DeleteFilled />}
|
||||||
jobid={getFieldValue("jobid")}
|
disabled={disabled || invLen > 0}
|
||||||
|
onClick={() => remove(record.name)}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</Space>
|
{Simple_Inventory.treatment === "on" && (
|
||||||
)}
|
<BilllineAddInventory
|
||||||
|
disabled={!billEdit || form.isFieldsTouched() || form.getFieldValue("is_credit_memo")}
|
||||||
|
billline={currentLine}
|
||||||
|
jobid={getFieldValue("jobid")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -625,8 +629,9 @@ export function BillEnterModalLinesComponent({
|
|||||||
size="small"
|
size="small"
|
||||||
bordered
|
bordered
|
||||||
dataSource={fields}
|
dataSource={fields}
|
||||||
|
rowKey="key"
|
||||||
columns={mergedColumns(remove)}
|
columns={mergedColumns(remove)}
|
||||||
scroll={hasRows ? { x: "max-content" } : undefined} // <-- no scrollbar when empty
|
scroll={hasRows ? { x: "max-content" } : undefined}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
rowClassName="editable-row"
|
rowClassName="editable-row"
|
||||||
/>
|
/>
|
||||||
@@ -681,11 +686,7 @@ const EditableCell = ({
|
|||||||
const control = skipFormItem ? (
|
const control = skipFormItem ? (
|
||||||
(formInput && formInput(record, record.name, propsFinal)) || children
|
(formInput && formInput(record, record.name, propsFinal)) || children
|
||||||
) : (
|
) : (
|
||||||
<Form.Item
|
<Form.Item labelCol={{ span: 0 }} {...propsFinal} style={{ marginBottom: 0 }}>
|
||||||
labelCol={{ span: 0 }}
|
|
||||||
{...propsFinal}
|
|
||||||
style={{ marginBottom: 0 }} // <-- important: remove default Form.Item margin
|
|
||||||
>
|
|
||||||
{(formInput && formInput(record, record.name, propsFinal)) || children}
|
{(formInput && formInput(record, record.name, propsFinal)) || children}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
@@ -702,10 +703,7 @@ const EditableCell = ({
|
|||||||
const { style: tdStyle, ...tdRest } = restProps;
|
const { style: tdStyle, ...tdRest } = restProps;
|
||||||
|
|
||||||
const td = (
|
const td = (
|
||||||
<td
|
<td {...tdRest} style={{ ...tdStyle, verticalAlign: "middle" }}>
|
||||||
{...tdRest}
|
|
||||||
style={{ ...tdStyle, verticalAlign: "middle" }} // optional but helps consistency
|
|
||||||
>
|
|
||||||
{cellInner}
|
{cellInner}
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,108 +17,126 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
currentUser: selectCurrentUser
|
currentUser: selectCurrentUser
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = () => ({
|
const mapDispatchToProps = () => ({});
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(BilllineAddInventory);
|
export default connect(mapStateToProps, mapDispatchToProps)(BilllineAddInventory);
|
||||||
|
|
||||||
export function BilllineAddInventory({ currentUser, bodyshop, billline, disabled, jobid }) {
|
export function BilllineAddInventory({ currentUser, bodyshop, billline, disabled, jobid }) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { billid } = queryString.parse(useLocation().search);
|
const qs = queryString.parse(useLocation().search);
|
||||||
|
const billid = qs?.billid != null ? String(qs.billid) : null;
|
||||||
|
|
||||||
const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT);
|
const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT);
|
||||||
const notification = useNotification();
|
const notification = useNotification();
|
||||||
|
|
||||||
|
const inventoryCount = billline?.inventories?.length ?? 0;
|
||||||
|
const quantity = billline?.quantity ?? 0;
|
||||||
|
|
||||||
const addToInventory = async () => {
|
const addToInventory = async () => {
|
||||||
setLoading(true);
|
if (loading) return;
|
||||||
|
|
||||||
//Check to make sure there are no existing items already in the inventory.
|
// Defensive: row identity can transiently desync during remove/add reindexing.
|
||||||
|
if (!billline) {
|
||||||
const cm = {
|
|
||||||
vendorid: bodyshop.inhousevendorid,
|
|
||||||
invoice_number: "ih",
|
|
||||||
jobid: jobid,
|
|
||||||
isinhouse: true,
|
|
||||||
is_credit_memo: true,
|
|
||||||
date: dayjs().format("YYYY-MM-DD"),
|
|
||||||
federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate,
|
|
||||||
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate,
|
|
||||||
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate,
|
|
||||||
total: 0,
|
|
||||||
billlines: [
|
|
||||||
{
|
|
||||||
actual_price: billline.actual_price,
|
|
||||||
actual_cost: billline.actual_cost,
|
|
||||||
quantity: billline.quantity,
|
|
||||||
line_desc: billline.line_desc,
|
|
||||||
cost_center: billline.cost_center,
|
|
||||||
deductedfromlbr: billline.deductedfromlbr,
|
|
||||||
applicable_taxes: {
|
|
||||||
local: billline.applicable_taxes.local,
|
|
||||||
state: billline.applicable_taxes.state,
|
|
||||||
federal: billline.applicable_taxes.federal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
cm.total = CalculateBillTotal(cm).enteredTotal.getAmount() / 100;
|
|
||||||
|
|
||||||
const insertResult = await insertInventoryLine({
|
|
||||||
variables: {
|
|
||||||
joblineId: billline.joblineid === "noline" ? billline.id : billline.joblineid, //This will return null as there will be no jobline that has the id of the bill line.
|
|
||||||
//Unfortunately, we can't send null as the GQL syntax validation fails.
|
|
||||||
joblineStatus: bodyshop.md_order_statuses.default_returned,
|
|
||||||
inv: {
|
|
||||||
shopid: bodyshop.id,
|
|
||||||
billlineid: billline.id,
|
|
||||||
actual_price: billline.actual_price,
|
|
||||||
actual_cost: billline.actual_cost,
|
|
||||||
quantity: billline.quantity,
|
|
||||||
line_desc: billline.line_desc
|
|
||||||
},
|
|
||||||
cm: { ...cm, billlines: { data: cm.billlines } }, //Fix structure for apollo insert.
|
|
||||||
pol: {
|
|
||||||
returnfrombill: billid,
|
|
||||||
vendorid: bodyshop.inhousevendorid,
|
|
||||||
deliver_by: dayjs().format("YYYY-MM-DD"),
|
|
||||||
parts_order_lines: {
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
line_desc: billline.line_desc,
|
|
||||||
|
|
||||||
act_price: billline.actual_price,
|
|
||||||
cost: billline.actual_cost,
|
|
||||||
quantity: billline.quantity,
|
|
||||||
job_line_id: billline.joblineid === "noline" ? null : billline.joblineid,
|
|
||||||
part_type: billline.jobline && billline.jobline.part_type,
|
|
||||||
cm_received: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
order_date: "2022-06-01",
|
|
||||||
orderedby: currentUser.email,
|
|
||||||
jobid: jobid,
|
|
||||||
user_email: currentUser.email,
|
|
||||||
return: true,
|
|
||||||
status: "Ordered"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
refetchQueries: ["QUERY_BILL_BY_PK"]
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!insertResult.errors) {
|
|
||||||
notification.success({
|
|
||||||
title: t("inventory.successes.inserted")
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
notification.error({
|
notification.error({
|
||||||
title: t("inventory.errors.inserting", {
|
title: t("inventory.errors.inserting", { error: "Bill line is missing (please try again)." })
|
||||||
error: JSON.stringify(insertResult.errors)
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const taxes = billline?.applicable_taxes ?? {};
|
||||||
|
const cm = {
|
||||||
|
vendorid: bodyshop.inhousevendorid,
|
||||||
|
invoice_number: "ih",
|
||||||
|
jobid: jobid,
|
||||||
|
isinhouse: true,
|
||||||
|
is_credit_memo: true,
|
||||||
|
date: dayjs().format("YYYY-MM-DD"),
|
||||||
|
federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate,
|
||||||
|
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate,
|
||||||
|
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate,
|
||||||
|
total: 0,
|
||||||
|
billlines: [
|
||||||
|
{
|
||||||
|
actual_price: billline.actual_price,
|
||||||
|
actual_cost: billline.actual_cost,
|
||||||
|
quantity: billline.quantity,
|
||||||
|
line_desc: billline.line_desc,
|
||||||
|
cost_center: billline.cost_center,
|
||||||
|
deductedfromlbr: billline.deductedfromlbr,
|
||||||
|
applicable_taxes: {
|
||||||
|
local: taxes.local,
|
||||||
|
state: taxes.state,
|
||||||
|
federal: taxes.federal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
cm.total = CalculateBillTotal(cm).enteredTotal.getAmount() / 100;
|
||||||
|
|
||||||
|
const insertResult = await insertInventoryLine({
|
||||||
|
variables: {
|
||||||
|
joblineId: billline.joblineid === "noline" ? billline.id : billline.joblineid,
|
||||||
|
joblineStatus: bodyshop.md_order_statuses.default_returned,
|
||||||
|
inv: {
|
||||||
|
shopid: bodyshop.id,
|
||||||
|
billlineid: billline.id,
|
||||||
|
actual_price: billline.actual_price,
|
||||||
|
actual_cost: billline.actual_cost,
|
||||||
|
quantity: billline.quantity,
|
||||||
|
line_desc: billline.line_desc
|
||||||
|
},
|
||||||
|
cm: { ...cm, billlines: { data: cm.billlines } },
|
||||||
|
pol: {
|
||||||
|
returnfrombill: billid,
|
||||||
|
vendorid: bodyshop.inhousevendorid,
|
||||||
|
deliver_by: dayjs().format("YYYY-MM-DD"),
|
||||||
|
parts_order_lines: {
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
line_desc: billline.line_desc,
|
||||||
|
act_price: billline.actual_price,
|
||||||
|
cost: billline.actual_cost,
|
||||||
|
quantity: billline.quantity,
|
||||||
|
job_line_id: billline.joblineid === "noline" ? null : billline.joblineid,
|
||||||
|
part_type: billline.jobline && billline.jobline.part_type,
|
||||||
|
cm_received: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
order_date: "2022-06-01",
|
||||||
|
orderedby: currentUser.email,
|
||||||
|
jobid: jobid,
|
||||||
|
user_email: currentUser.email,
|
||||||
|
return: true,
|
||||||
|
status: "Ordered"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
refetchQueries: ["QUERY_BILL_BY_PK"]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!insertResult?.errors?.length) {
|
||||||
|
notification.success({
|
||||||
|
title: t("inventory.successes.inserted")
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
notification.error({
|
||||||
|
title: t("inventory.errors.inserting", {
|
||||||
|
error: JSON.stringify(insertResult.errors)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
notification.error({
|
||||||
|
title: t("inventory.errors.inserting", {
|
||||||
|
error: err?.message || String(err)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -126,10 +144,10 @@ export function BilllineAddInventory({ currentUser, bodyshop, billline, disabled
|
|||||||
<Button
|
<Button
|
||||||
icon={<FileAddFilled />}
|
icon={<FileAddFilled />}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={disabled || billline?.inventories?.length >= billline.quantity}
|
disabled={disabled || inventoryCount >= quantity}
|
||||||
onClick={addToInventory}
|
onClick={addToInventory}
|
||||||
>
|
>
|
||||||
{billline?.inventories?.length > 0 && <div>({billline?.inventories?.length} in inv)</div>}
|
{inventoryCount > 0 && <div>({inventoryCount} in inv)</div>}
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user