IO-3624 Polish config empty states and admin cards

This commit is contained in:
Dave
2026-03-25 10:16:48 -04:00
parent 3aa19ec09f
commit b8246e03c1
22 changed files with 4976 additions and 4967 deletions

View File

@@ -3,6 +3,7 @@ import { Button, Col, Form, Input, Row, Select, Space, Switch } from "antd";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
import ConfigListEmptyState from "../layout-form-row/config-list-empty-state.component.jsx";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import {
INLINE_TITLE_GROUP_STYLE,
@@ -10,7 +11,8 @@ import {
INLINE_TITLE_INPUT_STYLE,
INLINE_TITLE_LABEL_STYLE,
INLINE_TITLE_ROW_STYLE,
INLINE_TITLE_SEPARATOR_STYLE
INLINE_TITLE_SEPARATOR_STYLE,
INLINE_TITLE_SWITCH_GROUP_STYLE
} from "../layout-form-row/inline-form-row-title.utils.js";
import i18n from "i18next";
@@ -76,229 +78,221 @@ export default function ShopInfoPartsScan({ form }) {
return (
<div>
<LayoutFormRow header={t("bodyshop.labels.md_parts_scan")}>
<Form.List name={["md_parts_scan"]}>
{(fields, { add, remove, move }) => (
<Form.List name={["md_parts_scan"]}>
{(fields, { add, remove, move }) => (
<LayoutFormRow
header={t("bodyshop.labels.md_parts_scan")}
actions={[
<Button
key="add-parts-scan-rule"
type="primary"
block
onClick={() =>
add({
field: "line_desc",
operation: "contains",
mark_critical: true,
caseInsensitive: true
})
}
>
{t("bodyshop.actions.addpartsrule")}
</Button>
]}
>
<div>
{fields.map((field, index) => {
const selectedField = watchedFields?.[index]?.field || "line_desc";
const fieldType = getFieldType(selectedField);
{fields.length === 0 ? (
<ConfigListEmptyState actionLabel={t("bodyshop.actions.addpartsrule")} />
) : (
fields.map((field, index) => {
const selectedField = watchedFields?.[index]?.field || "line_desc";
const fieldType = getFieldType(selectedField);
return (
<Form.Item key={field.key}>
<LayoutFormRow
noDivider
title={
<div style={INLINE_TITLE_ROW_STYLE}>
<HolderOutlined style={INLINE_TITLE_HANDLE_STYLE} />
<div
style={{
...INLINE_TITLE_GROUP_STYLE,
flex: "1 1 260px"
}}
>
<div style={INLINE_TITLE_LABEL_STYLE}>{t("bodyshop.fields.md_parts_scan.field")}</div>
return (
<Form.Item key={field.key}>
<LayoutFormRow
noDivider
title={
<div style={INLINE_TITLE_ROW_STYLE}>
<HolderOutlined style={INLINE_TITLE_HANDLE_STYLE} />
<div style={INLINE_TITLE_GROUP_STYLE}>
<div style={INLINE_TITLE_LABEL_STYLE}>{t("bodyshop.fields.md_parts_scan.field")}</div>
<Form.Item
noStyle
name={[field.name, "field"]}
rules={[
{
required: true,
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.field")
})
}
]}
>
<Select
options={fieldSelectOptions}
onChange={() => {
form.setFields([
{ name: ["md_parts_scan", index, "operation"], value: "contains" },
{ name: ["md_parts_scan", index, "value"], value: undefined }
]);
}}
style={{
width: "100%"
}}
styles={{
selector: INLINE_TITLE_INPUT_STYLE
}}
size="small"
/>
</Form.Item>
</div>
{fieldType === "string" && (
<>
<div aria-hidden style={INLINE_TITLE_SEPARATOR_STYLE} />
<div style={INLINE_TITLE_SWITCH_GROUP_STYLE}>
<div style={INLINE_TITLE_LABEL_STYLE}>
{t("bodyshop.fields.md_parts_scan.caseInsensitive")}
</div>
<Form.Item noStyle name={[field.name, "caseInsensitive"]} valuePropName="checked">
<Switch />
</Form.Item>
</div>
</>
)}
<div aria-hidden style={INLINE_TITLE_SEPARATOR_STYLE} />
<div style={INLINE_TITLE_SWITCH_GROUP_STYLE}>
<div style={INLINE_TITLE_LABEL_STYLE}>
{t("bodyshop.fields.md_parts_scan.mark_critical")}
</div>
<Form.Item noStyle name={[field.name, "mark_critical"]} valuePropName="checked">
<Switch />
</Form.Item>
</div>
</div>
}
wrapTitle
extra={
<Space align="center" size="small">
<Button
type="text"
danger
icon={<DeleteFilled />}
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
orientation="horizontal"
/>
</Space>
}
>
<Row gutter={[16, 16]} align="middle">
{/* Operation */}
{fieldType !== "predefined" && fieldType && (
<Col span={6}>
<Form.Item
label={t("bodyshop.fields.md_parts_scan.operation")}
name={[field.name, "operation"]}
rules={[
{
required: true,
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.operation")
})
}
]}
>
<Select options={operationOptions[fieldType]} />
</Form.Item>
</Col>
)}
{/* Value */}
{fieldType && (
<Col span={6}>
<Form.Item
label={t("bodyshop.fields.md_parts_scan.value")}
name={[field.name, "value"]}
rules={[
{
required: true,
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.value")
})
}
]}
>
{fieldType === "predefined" ? (
<Select
options={
selectedField === "part_type"
? predefinedPartTypes.map((type) => ({
label: type,
value: type
}))
: predefinedModLbrTypes.map((type) => ({
label: type,
value: type
}))
}
/>
) : (
<Input />
)}
</Form.Item>
</Col>
)}
{/* Update Field */}
<Col span={4}>
<Form.Item
noStyle
name={[field.name, "field"]}
rules={[
{
required: true,
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.field")
})
}
]}
label={t("bodyshop.fields.md_parts_scan.update_field")}
name={[field.name, "update_field"]}
>
<Select
options={fieldSelectOptions}
onChange={() => {
form.setFields([
{ name: ["md_parts_scan", index, "operation"], value: "contains" },
{ name: ["md_parts_scan", index, "value"], value: undefined }
]);
}}
style={{
width: "100%"
}}
styles={{
selector: INLINE_TITLE_INPUT_STYLE
}}
size="small"
allowClear
onClear={() =>
form.setFields([{ name: ["md_parts_scan", index, "update_field"], value: null }])
}
/>
</Form.Item>
</div>
{fieldType === "string" && (
<>
<div aria-hidden style={INLINE_TITLE_SEPARATOR_STYLE} />
<div
style={{
...INLINE_TITLE_GROUP_STYLE,
flex: "0 0 auto"
}}
>
<div style={INLINE_TITLE_LABEL_STYLE}>
{t("bodyshop.fields.md_parts_scan.caseInsensitive")}
</div>
<Form.Item noStyle name={[field.name, "caseInsensitive"]} valuePropName="checked">
<Switch />
</Form.Item>
</div>
</>
)}
<div aria-hidden style={INLINE_TITLE_SEPARATOR_STYLE} />
<div
style={{
...INLINE_TITLE_GROUP_STYLE,
flex: "0 0 auto"
}}
>
<div style={INLINE_TITLE_LABEL_STYLE}>
{t("bodyshop.fields.md_parts_scan.mark_critical")}
</div>
<Form.Item noStyle name={[field.name, "mark_critical"]} valuePropName="checked">
<Switch />
</Form.Item>
</div>
</div>
}
wrapTitle
extra={
<Space align="center" size="small">
<Button
type="text"
icon={<DeleteFilled />}
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
orientation="horizontal"
/>
</Space>
}
>
<Row gutter={[16, 16]} align="middle">
{/* Operation */}
{fieldType !== "predefined" && fieldType && (
<Col span={6}>
</Col>
{/* Update Field */}
<Col span={4}>
<Form.Item
label={t("bodyshop.fields.md_parts_scan.operation")}
name={[field.name, "operation"]}
label={t("bodyshop.fields.md_parts_scan.update_value")}
name={[field.name, "update_value"]}
dependencies={[["md_parts_scan", index, "update_field"]]}
tooltip={t("bodyshop.tooltips.md_parts_scan.update_value_tooltip")}
rules={[
{
required: true,
required: form.getFieldValue(["md_parts_scan", index, "update_field"]),
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.operation")
label: t("bodyshop.fields.md_parts_scan.update_value")
})
}
]}
>
<Select options={operationOptions[fieldType]} />
<Input />
</Form.Item>
</Col>
)}
{/* Value */}
{fieldType && (
<Col span={6}>
<Form.Item
label={t("bodyshop.fields.md_parts_scan.value")}
name={[field.name, "value"]}
rules={[
{
required: true,
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.value")
})
}
]}
>
{fieldType === "predefined" ? (
<Select
options={
selectedField === "part_type"
? predefinedPartTypes.map((type) => ({
label: type,
value: type
}))
: predefinedModLbrTypes.map((type) => ({
label: type,
value: type
}))
}
/>
) : (
<Input />
)}
</Form.Item>
</Col>
)}
{/* Update Field */}
<Col span={4}>
<Form.Item
label={t("bodyshop.fields.md_parts_scan.update_field")}
name={[field.name, "update_field"]}
>
<Select
options={fieldSelectOptions}
allowClear
onClear={() =>
form.setFields([{ name: ["md_parts_scan", index, "update_field"], value: null }])
}
/>
</Form.Item>
</Col>
{/* Update Field */}
<Col span={4}>
<Form.Item
label={t("bodyshop.fields.md_parts_scan.update_value")}
name={[field.name, "update_value"]}
dependencies={[["md_parts_scan", index, "update_field"]]}
tooltip={t("bodyshop.tooltips.md_parts_scan.update_value_tooltip")}
rules={[
{
required: form.getFieldValue(["md_parts_scan", index, "update_field"]),
message: t("general.validation.required", {
label: t("bodyshop.fields.md_parts_scan.update_value")
})
}
]}
>
<Input />
</Form.Item>
</Col>
</Row>
</LayoutFormRow>
</Form.Item>
);
})}
<Form.Item>
<Button
type="dashed"
onClick={() =>
add({
field: "line_desc",
operation: "contains",
mark_critical: true,
caseInsensitive: true
})
}
style={{ width: "100%" }}
>
{t("bodyshop.actions.addpartsrule")}
</Button>
</Form.Item>
</Row>
</LayoutFormRow>
</Form.Item>
);
})
)}
</div>
)}
</Form.List>
</LayoutFormRow>
</LayoutFormRow>
)}
</Form.List>
</div>
);
}