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 { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
||||
|
||||
// Keep input row heights consistent with the rest of the table controls.
|
||||
const CONTROL_HEIGHT = 32;
|
||||
|
||||
const normalizeDiscount = (d) => {
|
||||
const n = Number(d);
|
||||
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;
|
||||
@@ -79,7 +78,6 @@ export function BillEnterModalLinesComponent({
|
||||
return NaN;
|
||||
};
|
||||
|
||||
// safe per-field setter (supports AntD 6+ setFieldValue, falls back to setFieldsValue)
|
||||
const setLineField = (index, field, value) => {
|
||||
if (typeof form.setFieldValue === "function") {
|
||||
form.setFieldValue(["billlines", index, field], value);
|
||||
@@ -115,7 +113,6 @@ export function BillEnterModalLinesComponent({
|
||||
};
|
||||
|
||||
const getIndicatorShellStyles = (statusColor) => {
|
||||
// bring back the “colored shell” feel around the $ indicator while keeping row height stable
|
||||
if (isDarkMode) {
|
||||
if (statusColor === "green")
|
||||
return { borderColor: "rgba(82, 196, 26, 0.75)", background: "rgba(82, 196, 26, 0.10)" };
|
||||
@@ -145,7 +142,7 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
minWidth: "10rem",
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}joblinename`,
|
||||
key: `${field.name}joblinename`,
|
||||
name: [field.name, "joblineid"],
|
||||
label: t("billlines.fields.jobline"),
|
||||
rules: [{ required: true }]
|
||||
@@ -203,7 +200,7 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
minWidth: "10rem",
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}line_desc`,
|
||||
key: `${field.name}line_desc`,
|
||||
name: [field.name, "line_desc"],
|
||||
label: t("billlines.fields.line_desc"),
|
||||
rules: [{ required: true }]
|
||||
@@ -216,17 +213,19 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
width: "4rem",
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}quantity`,
|
||||
key: `${field.name}quantity`,
|
||||
name: [field.name, "quantity"],
|
||||
label: t("billlines.fields.quantity"),
|
||||
rules: [
|
||||
{ required: true },
|
||||
({ getFieldValue: gf }) => ({
|
||||
validator(rule, value) {
|
||||
if (value && gf("billlines")[field.fieldKey]?.inventories?.length > value) {
|
||||
validator(_, value) {
|
||||
const invLen = gf(["billlines", field.name, "inventories"])?.length ?? 0;
|
||||
|
||||
if (value && invLen > value) {
|
||||
return Promise.reject(
|
||||
t("bills.validation.inventoryquantity", {
|
||||
number: gf("billlines")[field.fieldKey]?.inventories?.length
|
||||
number: invLen
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -243,7 +242,7 @@ export function BillEnterModalLinesComponent({
|
||||
width: "8rem",
|
||||
editable: true,
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}actual_price`,
|
||||
key: `${field.name}actual_price`,
|
||||
name: [field.name, "actual_price"],
|
||||
label: t("billlines.fields.actual_price"),
|
||||
rules: [{ required: true }]
|
||||
@@ -295,7 +294,7 @@ export function BillEnterModalLinesComponent({
|
||||
width: "10rem",
|
||||
skipFormItem: true,
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}actual_cost`,
|
||||
key: `${field.name}actual_cost`,
|
||||
name: [field.name, "actual_cost"],
|
||||
label: t("billlines.fields.actual_cost"),
|
||||
rules: [{ required: true }]
|
||||
@@ -386,7 +385,7 @@ export function BillEnterModalLinesComponent({
|
||||
dataIndex: "cost_center",
|
||||
editable: true,
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}cost_center`,
|
||||
key: `${field.name}cost_center`,
|
||||
name: [field.name, "cost_center"],
|
||||
label: t("billlines.fields.cost_center"),
|
||||
valuePropName: "value",
|
||||
@@ -409,7 +408,7 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
label: t("billlines.fields.location"),
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}location`,
|
||||
key: `${field.name}location`,
|
||||
name: [field.name, "location"]
|
||||
}),
|
||||
formInput: () => (
|
||||
@@ -430,7 +429,7 @@ export function BillEnterModalLinesComponent({
|
||||
width: "40px",
|
||||
formItemProps: (field) => ({
|
||||
valuePropName: "checked",
|
||||
key: `${field.index}deductedfromlbr`,
|
||||
key: `${field.name}deductedfromlbr`,
|
||||
name: [field.name, "deductedfromlbr"]
|
||||
}),
|
||||
formInput: () => <Switch disabled={disabled} />,
|
||||
@@ -516,7 +515,7 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
width: "40px",
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}fedtax`,
|
||||
key: `${field.name}fedtax`,
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "federal"]
|
||||
}),
|
||||
@@ -531,7 +530,7 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
width: "40px",
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}statetax`,
|
||||
key: `${field.name}statetax`,
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "state"]
|
||||
}),
|
||||
@@ -547,7 +546,7 @@ export function BillEnterModalLinesComponent({
|
||||
editable: true,
|
||||
width: "40px",
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.index}localtax`,
|
||||
key: `${field.name}localtax`,
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "local"]
|
||||
}),
|
||||
@@ -561,23 +560,28 @@ export function BillEnterModalLinesComponent({
|
||||
dataIndex: "actions",
|
||||
render: (text, record) => (
|
||||
<Form.Item shouldUpdate noStyle>
|
||||
{() => (
|
||||
<Space wrap>
|
||||
<Button
|
||||
icon={<DeleteFilled />}
|
||||
disabled={disabled || getFieldValue("billlines")[record.fieldKey]?.inventories?.length > 0}
|
||||
onClick={() => remove(record.name)}
|
||||
/>
|
||||
{() => {
|
||||
const currentLine = getFieldValue(["billlines", record.name]);
|
||||
const invLen = currentLine?.inventories?.length ?? 0;
|
||||
|
||||
{Simple_Inventory.treatment === "on" && (
|
||||
<BilllineAddInventory
|
||||
disabled={!billEdit || form.isFieldsTouched() || form.getFieldValue("is_credit_memo")}
|
||||
billline={getFieldValue("billlines")[record.fieldKey]}
|
||||
jobid={getFieldValue("jobid")}
|
||||
return (
|
||||
<Space wrap>
|
||||
<Button
|
||||
icon={<DeleteFilled />}
|
||||
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>
|
||||
)
|
||||
}
|
||||
@@ -625,8 +629,9 @@ export function BillEnterModalLinesComponent({
|
||||
size="small"
|
||||
bordered
|
||||
dataSource={fields}
|
||||
rowKey="key"
|
||||
columns={mergedColumns(remove)}
|
||||
scroll={hasRows ? { x: "max-content" } : undefined} // <-- no scrollbar when empty
|
||||
scroll={hasRows ? { x: "max-content" } : undefined}
|
||||
pagination={false}
|
||||
rowClassName="editable-row"
|
||||
/>
|
||||
@@ -681,11 +686,7 @@ const EditableCell = ({
|
||||
const control = skipFormItem ? (
|
||||
(formInput && formInput(record, record.name, propsFinal)) || children
|
||||
) : (
|
||||
<Form.Item
|
||||
labelCol={{ span: 0 }}
|
||||
{...propsFinal}
|
||||
style={{ marginBottom: 0 }} // <-- important: remove default Form.Item margin
|
||||
>
|
||||
<Form.Item labelCol={{ span: 0 }} {...propsFinal} style={{ marginBottom: 0 }}>
|
||||
{(formInput && formInput(record, record.name, propsFinal)) || children}
|
||||
</Form.Item>
|
||||
);
|
||||
@@ -702,10 +703,7 @@ const EditableCell = ({
|
||||
const { style: tdStyle, ...tdRest } = restProps;
|
||||
|
||||
const td = (
|
||||
<td
|
||||
{...tdRest}
|
||||
style={{ ...tdStyle, verticalAlign: "middle" }} // optional but helps consistency
|
||||
>
|
||||
<td {...tdRest} style={{ ...tdStyle, verticalAlign: "middle" }}>
|
||||
{cellInner}
|
||||
</td>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user