@rytass/bpm-core-react 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/chunks/{app-navigation-BRRFCkxZ.cjs → app-navigation-C_mbz7jx.cjs} +2 -2
- package/dist/chunks/app-navigation-C_mbz7jx.cjs.map +1 -0
- package/dist/chunks/{app-navigation-rxhpHCch.js → app-navigation-uwbNEw9P.js} +65 -65
- package/dist/chunks/app-navigation-uwbNEw9P.js.map +1 -0
- package/dist/chunks/approval-instance-list-page-Mo6wpDPb.cjs +2 -0
- package/dist/chunks/approval-instance-list-page-Mo6wpDPb.cjs.map +1 -0
- package/dist/chunks/approval-instance-list-page-nmzMrj0b.js +281 -0
- package/dist/chunks/approval-instance-list-page-nmzMrj0b.js.map +1 -0
- package/dist/chunks/builder-DPhAH381.cjs +3 -0
- package/dist/chunks/builder-DPhAH381.cjs.map +1 -0
- package/dist/chunks/{builder-Du_0apkh.js → builder-DqZskyXC.js} +333 -330
- package/dist/chunks/builder-DqZskyXC.js.map +1 -0
- package/dist/chunks/categories-DEijUOnw.cjs +2 -0
- package/dist/chunks/categories-DEijUOnw.cjs.map +1 -0
- package/dist/chunks/{categories-DG4k7S8V.js → categories-DTEl182t.js} +129 -126
- package/dist/chunks/categories-DTEl182t.js.map +1 -0
- package/dist/chunks/{dashboard-page-DcDiWQp2.cjs → dashboard-page-DCmuB0Rw.cjs} +2 -2
- package/dist/chunks/dashboard-page-DCmuB0Rw.cjs.map +1 -0
- package/dist/chunks/dashboard-page-Dx5PeEeN.js +117 -0
- package/dist/chunks/dashboard-page-Dx5PeEeN.js.map +1 -0
- package/dist/chunks/delegations-C-ZrwzvU.js +572 -0
- package/dist/chunks/delegations-C-ZrwzvU.js.map +1 -0
- package/dist/chunks/delegations-C5PzZ5Kn.js +645 -0
- package/dist/chunks/delegations-C5PzZ5Kn.js.map +1 -0
- package/dist/chunks/delegations-DOGDvybX.cjs +2 -0
- package/dist/chunks/delegations-DOGDvybX.cjs.map +1 -0
- package/dist/chunks/delegations-DkDBWOQ7.cjs +2 -0
- package/dist/chunks/delegations-DkDBWOQ7.cjs.map +1 -0
- package/dist/chunks/detail-B2gcOPkd.cjs +2 -0
- package/dist/chunks/detail-B2gcOPkd.cjs.map +1 -0
- package/dist/chunks/{detail-DilI0PPe.js → detail-CfFyU5zC.js} +667 -664
- package/dist/chunks/detail-CfFyU5zC.js.map +1 -0
- package/dist/chunks/{format-date-time-hKLVMxq4.cjs → format-date-time-isOa3e9q.cjs} +2 -2
- package/dist/chunks/{format-date-time-hKLVMxq4.cjs.map → format-date-time-isOa3e9q.cjs.map} +1 -1
- package/dist/chunks/notifications-CPQ-nVar.cjs +2 -0
- package/dist/chunks/notifications-CPQ-nVar.cjs.map +1 -0
- package/dist/chunks/notifications-DweexUVy.js +197 -0
- package/dist/chunks/notifications-DweexUVy.js.map +1 -0
- package/dist/chunks/orgs-DgZ0DQ3-.cjs +2 -0
- package/dist/chunks/orgs-DgZ0DQ3-.cjs.map +1 -0
- package/dist/chunks/{orgs-c29y74w2.js → orgs-xrdhb3hS.js} +668 -665
- package/dist/chunks/orgs-xrdhb3hS.js.map +1 -0
- package/dist/chunks/templates-PK_VYvcy.js +383 -0
- package/dist/chunks/templates-PK_VYvcy.js.map +1 -0
- package/dist/chunks/{templates-Cd0WFheA.cjs → templates-x1OJZmsG.cjs} +2 -2
- package/dist/chunks/templates-x1OJZmsG.cjs.map +1 -0
- package/dist/chunks/users-CY4-NK3j.js +218 -0
- package/dist/chunks/users-CY4-NK3j.js.map +1 -0
- package/dist/chunks/users-DHnu_056.cjs +2 -0
- package/dist/chunks/users-DHnu_056.cjs.map +1 -0
- package/dist/components/app-navigation.d.ts +17 -10
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/notification-drawer-provider.d.ts +1 -1
- package/dist/lib/notification-unread-provider.d.ts +1 -1
- package/dist/lib/providers.d.ts +1 -1
- package/dist/pages/admin/delegations/index.cjs +1 -1
- package/dist/pages/admin/delegations/index.js +1 -1
- package/dist/pages/admin/orgs/index.cjs +1 -1
- package/dist/pages/admin/orgs/index.js +1 -1
- package/dist/pages/admin/users/index.cjs +1 -1
- package/dist/pages/admin/users/index.js +1 -1
- package/dist/pages/delegations/index.cjs +1 -1
- package/dist/pages/delegations/index.js +1 -1
- package/dist/pages/forms/builder/index.cjs +1 -1
- package/dist/pages/forms/builder/index.js +1 -1
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/settings/notifications/index.cjs +1 -1
- package/dist/pages/settings/notifications/index.js +1 -1
- package/dist/pages/templates/categories/index.cjs +1 -1
- package/dist/pages/templates/categories/index.js +1 -1
- package/dist/pages/templates/index.cjs +1 -1
- package/dist/pages/templates/index.js +1 -1
- package/dist/views/admin/delegations/index.cjs +1 -1
- package/dist/views/admin/delegations/index.js +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.js +3 -3
- package/dist/views/admin/orgs/index.cjs +1 -1
- package/dist/views/admin/orgs/index.js +1 -1
- package/dist/views/admin/users/index.cjs +1 -1
- package/dist/views/admin/users/index.js +1 -1
- package/dist/views/cc/index.cjs +1 -1
- package/dist/views/cc/index.js +1 -1
- package/dist/views/dashboard/index.cjs +1 -1
- package/dist/views/dashboard/index.js +1 -1
- package/dist/views/delegations/index.cjs +1 -1
- package/dist/views/delegations/index.js +1 -1
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/index.cjs +1 -1
- package/dist/views/forms/index.cjs.map +1 -1
- package/dist/views/forms/index.js +93 -90
- package/dist/views/forms/index.js.map +1 -1
- package/dist/views/inbox/index.cjs +1 -1
- package/dist/views/inbox/index.cjs.map +1 -1
- package/dist/views/inbox/index.js +127 -124
- package/dist/views/inbox/index.js.map +1 -1
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.js +1 -1
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.cjs.map +1 -1
- package/dist/views/instances/new/index.js +120 -114
- package/dist/views/instances/new/index.js.map +1 -1
- package/dist/views/search/index.cjs +1 -1
- package/dist/views/search/index.js +1 -1
- package/dist/views/sent/index.cjs +1 -1
- package/dist/views/sent/index.js +1 -1
- package/dist/views/settings/index.cjs +1 -1
- package/dist/views/settings/index.js +1 -1
- package/dist/views/settings/notifications/index.cjs +1 -1
- package/dist/views/settings/notifications/index.js +1 -1
- package/dist/views/templates/categories/index.cjs +1 -1
- package/dist/views/templates/categories/index.js +1 -1
- package/dist/views/templates/designer/index.cjs +2 -2
- package/dist/views/templates/designer/index.cjs.map +1 -1
- package/dist/views/templates/designer/index.js +573 -570
- package/dist/views/templates/designer/index.js.map +1 -1
- package/dist/views/templates/index.cjs +1 -1
- package/dist/views/templates/index.js +2 -2
- package/dist/views/templates/versions/index.cjs +1 -1
- package/dist/views/templates/versions/index.cjs.map +1 -1
- package/dist/views/templates/versions/index.js +50 -47
- package/dist/views/templates/versions/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/app-navigation-BRRFCkxZ.cjs.map +0 -1
- package/dist/chunks/app-navigation-rxhpHCch.js.map +0 -1
- package/dist/chunks/approval-instance-list-page-2vUWc5-c.cjs +0 -2
- package/dist/chunks/approval-instance-list-page-2vUWc5-c.cjs.map +0 -1
- package/dist/chunks/approval-instance-list-page-BgE4vQw8.js +0 -278
- package/dist/chunks/approval-instance-list-page-BgE4vQw8.js.map +0 -1
- package/dist/chunks/builder-B8X-m6C5.cjs +0 -3
- package/dist/chunks/builder-B8X-m6C5.cjs.map +0 -1
- package/dist/chunks/builder-Du_0apkh.js.map +0 -1
- package/dist/chunks/categories-DG4k7S8V.js.map +0 -1
- package/dist/chunks/categories-DshBQG33.cjs +0 -2
- package/dist/chunks/categories-DshBQG33.cjs.map +0 -1
- package/dist/chunks/dashboard-page-CTBwpu_D.js +0 -114
- package/dist/chunks/dashboard-page-CTBwpu_D.js.map +0 -1
- package/dist/chunks/dashboard-page-DcDiWQp2.cjs.map +0 -1
- package/dist/chunks/delegations-BAZQbElH.js +0 -642
- package/dist/chunks/delegations-BAZQbElH.js.map +0 -1
- package/dist/chunks/delegations-DzrckrPp.js +0 -569
- package/dist/chunks/delegations-DzrckrPp.js.map +0 -1
- package/dist/chunks/delegations-Z8hTajLj.cjs +0 -2
- package/dist/chunks/delegations-Z8hTajLj.cjs.map +0 -1
- package/dist/chunks/delegations-hb9JoVZe.cjs +0 -2
- package/dist/chunks/delegations-hb9JoVZe.cjs.map +0 -1
- package/dist/chunks/detail-DilI0PPe.js.map +0 -1
- package/dist/chunks/detail-DuRg3Y7b.cjs +0 -2
- package/dist/chunks/detail-DuRg3Y7b.cjs.map +0 -1
- package/dist/chunks/notifications-B2Lk3grg.js +0 -194
- package/dist/chunks/notifications-B2Lk3grg.js.map +0 -1
- package/dist/chunks/notifications-C8ADhnxF.cjs +0 -2
- package/dist/chunks/notifications-C8ADhnxF.cjs.map +0 -1
- package/dist/chunks/orgs-CGv3VNDR.cjs +0 -2
- package/dist/chunks/orgs-CGv3VNDR.cjs.map +0 -1
- package/dist/chunks/orgs-c29y74w2.js.map +0 -1
- package/dist/chunks/templates-Cd0WFheA.cjs.map +0 -1
- package/dist/chunks/templates-Dn9QHFSy.js +0 -380
- package/dist/chunks/templates-Dn9QHFSy.js.map +0 -1
- package/dist/chunks/users-B-trMu0E.cjs +0 -2
- package/dist/chunks/users-B-trMu0E.cjs.map +0 -1
- package/dist/chunks/users-itVXXRj7.js +0 -215
- package/dist/chunks/users-itVXXRj7.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-DqZskyXC.js","names":[],"sources":["../../src/views/forms/builder/json-code-editor.tsx","../../src/views/forms/builder/FormBuilderView.tsx"],"sourcesContent":["'use client';\n\nimport { CSSProperties, ReactElement } from 'react';\nimport dynamic from 'next/dynamic';\nimport { json } from '@codemirror/lang-json';\nimport { EditorView } from '@codemirror/view';\nimport type { Extension, ReactCodeMirrorProps } from '@uiw/react-codemirror';\n\nconst EDITOR_FALLBACK_STYLE: CSSProperties = {\n alignItems: 'center',\n border: '1px solid var(--mzn-color-border-neutral)',\n borderRadius: 4,\n color: 'var(--mzn-color-text-neutral)',\n display: 'flex',\n minHeight: 160,\n padding: 12,\n width: '100%',\n};\n\nconst JSON_EDITOR_EXTENSIONS: readonly Extension[] = [\n json(),\n EditorView.lineWrapping,\n EditorView.theme({\n '&': {\n border: '1px solid var(--mzn-color-border-neutral)',\n borderRadius: '4px',\n fontSize: '13px',\n width: '100%',\n },\n '&.cm-focused': {\n outline: '1px solid var(--mzn-color-border-primary)',\n },\n '.cm-content': {\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace',\n minHeight: '100%',\n },\n '.cm-editor': {\n width: '100%',\n },\n '.cm-gutters': {\n borderRight: '1px solid var(--mzn-color-border-neutral)',\n },\n '.cm-scroller': {\n fontFamily:\n 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace',\n },\n }),\n];\n\nconst CodeMirror = dynamic<ReactCodeMirrorProps>(\n () => import('@uiw/react-codemirror'),\n {\n loading: (): ReactElement => (\n <div style={EDITOR_FALLBACK_STYLE}>載入 JSON 編輯器</div>\n ),\n ssr: false,\n },\n);\n\ninterface JsonCodeEditorProps {\n readonly disabled: boolean;\n readonly height: string;\n readonly name: string;\n readonly onChange: (value: string) => void;\n readonly placeholder: string;\n readonly value: string;\n}\n\nexport function JsonCodeEditor({\n disabled,\n height,\n name,\n onChange,\n placeholder,\n value,\n}: JsonCodeEditorProps): ReactElement {\n return (\n <CodeMirror\n aria-label={name}\n basicSetup={{\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n defaultKeymap: true,\n foldGutter: true,\n highlightActiveLine: true,\n highlightSelectionMatches: true,\n lineNumbers: true,\n syntaxHighlighting: true,\n }}\n editable={!disabled}\n extensions={[...JSON_EDITOR_EXTENSIONS]}\n height={height}\n indentWithTab={false}\n onChange={onChange}\n placeholder={placeholder}\n readOnly={disabled}\n theme=\"light\"\n value={value}\n width=\"100%\"\n />\n );\n}\n","'use client';\n\nimport {\n ChangeEvent,\n CSSProperties,\n Key,\n ReactElement,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n DragDropContext,\n Draggable,\n DraggableProvided,\n Droppable,\n DropResult,\n} from '@hello-pangea/dnd';\nimport {\n Accordion,\n BaseCard,\n Badge,\n Button,\n DatePicker,\n DateTimePicker,\n Icon,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Tab,\n TabItem,\n Table,\n Textarea,\n Toggle,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n AlignLeftIcon,\n CalendarIcon,\n CheckedOutlineIcon,\n CheckedIcon,\n CurrencyDollarIcon,\n DotDragVerticalIcon,\n DotGridIcon,\n EditIcon,\n FileAttachmentIcon,\n FileIcon,\n ListIcon,\n PlusIcon,\n SaveIcon,\n TrashIcon,\n} from '@mezzanine-ui/icons';\nimport type { IconDefinition } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n BooleanFieldDefinition,\n DateFieldDefinition,\n FileUploadFieldDefinition,\n FormDefinitionSchema,\n FormFieldDefinition,\n FormFieldOption,\n FormUiSchema,\n NumberFieldDefinition,\n SelectFieldDefinition,\n TextFieldDefinition,\n} from '@rytass/bpm-core-shared/form';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { AppLayout } from '../../../components/app-navigation';\nimport {\n createFieldDefinition,\n FormBuilderRecord,\n FormDefinitionVersionRecord,\n forkFormDefinition,\n publishFormDefinitionVersion,\n readFormBuilder,\n updateFormDefinition,\n updateFormDefinitionDraft,\n} from '@rytass/bpm-core-client/form';\nimport {\n buildConditionExpression,\n buildFormRendererValues,\n clampOptionalNumber,\n formatDatePickerValue,\n formatDateTimePickerValue,\n FormRendererValues,\n isDateFieldDefinition,\n isNumberFieldDefinition,\n isSelectFieldDefinition,\n parseConditionRule,\n parseOptionalNumberInput,\n readConditionOperatorOption,\n readConditionOperatorOptions,\n readDatePickerValue,\n readDefaultConditionOperator,\n readDefaultConditionValue,\n readFieldOptionAsSelectOption,\n readSelectOption,\n} from '@rytass/bpm-core-client/form';\nimport { useRouterAdapter } from '../../../lib/router-adapter';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { FormRenderer } from '../renderer/FormRendererView';\nimport { FormNameModal } from '../form-name-modal';\nimport { JsonCodeEditor } from './json-code-editor';\n\ntype FieldType = FormFieldDefinition['type'];\ntype BuilderTabKey = 'design' | 'preview' | 'versions' | 'advanced';\ntype FieldOptionRow = Readonly<\n Record<string, unknown> & {\n index: number;\n key: string;\n label: string;\n value: string;\n }\n>;\n\ntype VersionRow = Readonly<\n Record<string, unknown> & {\n key: string;\n publishedAt: string;\n status: FormDefinitionVersionRecord['status'];\n updatedAt: string;\n version: string;\n }\n>;\n\ntype BuilderSnapshot = Readonly<{\n schemaJson: string;\n uiSchemaJson: string;\n}>;\n\ntype FieldTypeOption = Readonly<{\n description: string;\n icon: IconDefinition;\n label: string;\n type: FieldType;\n}>;\n\ntype ConditionRuleTarget = 'readonlyWhen' | 'requiredWhen' | 'visibleWhen';\n\ntype ConditionRuleConfig = Readonly<{\n label: string;\n name: string;\n supportingText: string;\n target: ConditionRuleTarget;\n}>;\n\nconst FIELD_TYPE_OPTIONS: readonly FieldTypeOption[] = [\n {\n description: '單行文字、姓名、編號',\n icon: AlignLeftIcon,\n label: '文字',\n type: 'text',\n },\n {\n description: '多行補充內容',\n icon: FileIcon,\n label: '長文字',\n type: 'textarea',\n },\n {\n description: '金額、數量、分數',\n icon: CurrencyDollarIcon,\n label: '數字',\n type: 'number',\n },\n {\n description: '金額與費用',\n icon: CurrencyDollarIcon,\n label: '金額',\n type: 'money',\n },\n {\n description: '日期或到期日',\n icon: CalendarIcon,\n label: '日期',\n type: 'date',\n },\n {\n description: '日期與時間',\n icon: CalendarIcon,\n label: '日期時間',\n type: 'datetime',\n },\n {\n description: '是 / 否狀態',\n icon: CheckedIcon,\n label: '開關',\n type: 'boolean',\n },\n {\n description: '固定選項擇一',\n icon: ListIcon,\n label: '下拉選單',\n type: 'select',\n },\n {\n description: '固定選項單選',\n icon: DotGridIcon,\n label: '單選',\n type: 'radio',\n },\n {\n description: '固定選項複選',\n icon: CheckedOutlineIcon,\n label: '複選',\n type: 'checkbox',\n },\n {\n description: '附件或佐證資料',\n icon: FileAttachmentIcon,\n label: '附件',\n type: 'file_upload',\n },\n];\n\nconst WORKSPACE_GRID_STYLE: CSSProperties = {\n alignItems: 'start',\n display: 'flex',\n flexWrap: 'wrap',\n gap: 16,\n};\n\nconst CANVAS_COLUMN_STYLE: CSSProperties = {\n flex: '0.55 1 300px',\n minWidth: 0,\n};\n\nconst SETTINGS_COLUMN_STYLE: CSSProperties = {\n flex: '1.45 1 720px',\n minWidth: 620,\n};\n\nconst STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n};\n\nconst FIELD_LIBRARY_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 6,\n};\n\nconst FIELD_LIBRARY_BUTTON_STYLE: CSSProperties = {\n flex: '0 0 auto',\n whiteSpace: 'nowrap',\n};\n\nconst FIELD_LIBRARY_HEADER_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n};\n\nconst FIELD_BLOCK_ROW_STYLE: CSSProperties = {\n alignItems: 'center',\n cursor: 'grab',\n display: 'flex',\n gap: 12,\n touchAction: 'none',\n};\n\nconst FIELD_BLOCK_TEXT_STYLE: CSSProperties = {\n display: 'grid',\n flex: '1 1 auto',\n gap: 2,\n minWidth: 0,\n};\n\nconst FIELD_BLOCK_ACTIONS_STYLE: CSSProperties = {\n alignItems: 'center',\n display: 'flex',\n flex: '0 0 auto',\n gap: 4,\n};\n\nconst FIELD_BLOCK_REQUIRED_STYLE: CSSProperties = {\n alignItems: 'center',\n display: 'flex',\n gap: 6,\n};\n\nconst FIELD_BLOCK_STYLE: CSSProperties = {\n userSelect: 'none',\n};\n\nconst FIELD_BLOCK_DRAGGING_STYLE: CSSProperties = {\n filter: 'drop-shadow(0 8px 18px rgba(0, 0, 0, 0.12))',\n};\n\nconst EMPTY_CANVAS_STYLE: CSSProperties = {\n alignItems: 'center',\n border: '1px dashed var(--mzn-color-border-neutral)',\n borderRadius: 6,\n display: 'grid',\n gap: 12,\n minHeight: 240,\n padding: 32,\n textAlign: 'center',\n};\n\nconst EMPTY_CANVAS_ACTIONS_STYLE: CSSProperties = {\n display: 'flex',\n gap: 8,\n justifyContent: 'center',\n};\n\nconst FIELD_SETTINGS_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 14,\n};\n\nconst FIELD_SETTINGS_SECTION_STYLE: CSSProperties = {\n display: 'grid',\n columnGap: 16,\n gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',\n rowGap: 8,\n};\n\nconst FIELD_SETTINGS_SECTION_TITLE_STYLE: CSSProperties = {\n gridColumn: '1 / -1',\n};\n\nconst FIELD_SETTINGS_BADGE_ROW_STYLE: CSSProperties = {\n alignItems: 'center',\n display: 'flex',\n gap: 8,\n gridColumn: '1 / -1',\n justifyContent: 'flex-end',\n};\n\nconst FIELD_SETTINGS_HINT_STYLE: CSSProperties = {\n gridColumn: '1 / -1',\n};\n\nconst FIELD_SETTINGS_ROW_STYLE: CSSProperties = {\n alignItems: 'start',\n display: 'block',\n width: '100%',\n};\n\nconst FIELD_SETTINGS_ROW_WIDE_STYLE: CSSProperties = {\n ...FIELD_SETTINGS_ROW_STYLE,\n gridColumn: '1 / -1',\n};\n\nconst FIELD_SETTINGS_VALUE_STYLE: CSSProperties = {\n minWidth: 0,\n width: '100%',\n};\n\nconst FIELD_SETTINGS_TEXTAREA_STYLE: CSSProperties = {\n minWidth: '100%',\n width: '100%',\n};\n\nconst ADVANCED_SCHEMA_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 14,\n};\n\nconst ADVANCED_SCHEMA_ROW_STYLE: CSSProperties = {\n alignItems: 'start',\n display: 'block',\n width: '100%',\n};\n\nconst ADVANCED_SCHEMA_VALUE_STYLE: CSSProperties = {\n minWidth: 0,\n width: '100%',\n};\n\nconst ADVANCED_SCHEMA_MESSAGE_STYLE: CSSProperties = {\n gridColumn: '2 / -1',\n};\n\nconst CONDITION_RULE_CONTROL_STYLE: CSSProperties = {\n display: 'grid',\n gap: 10,\n width: '100%',\n};\n\nconst CONDITION_RULE_GRID_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))',\n};\n\nconst DRAG_HANDLE_STYLE: CSSProperties = {\n display: 'inline-flex',\n};\n\nconst WORKBENCH_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst COMPACT_STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 8,\n};\n\nconst OPTION_ACTIONS_STYLE: CSSProperties = {\n display: 'flex',\n justifyContent: 'flex-end',\n};\n\nconst REQUIRED_ASTERISK_STYLE: CSSProperties = {\n color: 'var(--mzn-color-text-error)',\n fontSize: '0.72em',\n lineHeight: 0,\n marginLeft: 2,\n verticalAlign: 'super',\n};\n\nfunction applyFullWidthTextareaHost(element: HTMLDivElement | null): void {\n if (!element) {\n return;\n }\n\n element.style.width = '100%';\n}\n\nconst EMPTY_SCHEMA: FormDefinitionSchema = {\n fields: [],\n schemaVersion: 1,\n};\n\nconst EMPTY_UI_SCHEMA: FormUiSchema = {\n layout: [],\n schemaVersion: 1,\n};\n\nconst BOOLEAN_DEFAULT_OPTIONS: readonly {\n readonly id: string;\n readonly name: string;\n}[] = [\n { id: 'unset', name: '不預設' },\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\nconst BOOLEAN_CONDITION_VALUE_OPTIONS: readonly {\n readonly id: string;\n readonly name: string;\n}[] = [\n { id: 'true', name: '是' },\n { id: 'false', name: '否' },\n];\n\nconst CONDITION_RULE_CONFIGS: readonly ConditionRuleConfig[] = [\n {\n label: '顯示',\n name: 'fieldVisibleWhen',\n supportingText: '符合條件時才顯示這個欄位。',\n target: 'visibleWhen',\n },\n {\n label: '必填',\n name: 'fieldRequiredWhen',\n supportingText: '符合條件時才要求填寫這個欄位。',\n target: 'requiredWhen',\n },\n {\n label: '唯讀',\n name: 'fieldReadonlyWhen',\n supportingText: '符合條件時不允許修改這個欄位。',\n target: 'readonlyWhen',\n },\n];\n\nexport interface FormBuilderViewProps {\n /**\n * The id of the form definition being edited. Routed via the host's\n * dynamic segment (e.g. `[id]` in Next.js).\n */\n readonly formId: string;\n}\n\nexport function FormBuilderView({ formId }: FormBuilderViewProps): ReactElement {\n const router = useRouterAdapter();\n const formDefinitionId = formId;\n const [record, setRecord] = useState<FormBuilderRecord | null>(null);\n const [draft, setDraft] = useState<FormDefinitionVersionRecord | null>(null);\n const [schema, setSchema] = useState<FormDefinitionSchema>(EMPTY_SCHEMA);\n const [uiSchema, setUiSchema] = useState<FormUiSchema>(EMPTY_UI_SCHEMA);\n const [schemaJsonText, setSchemaJsonText] = useState(\n stringifyJson(EMPTY_SCHEMA),\n );\n const [uiSchemaJsonText, setUiSchemaJsonText] = useState(\n stringifyJson(EMPTY_UI_SCHEMA),\n );\n const [previewValues, setPreviewValues] = useState<FormRendererValues>({});\n const [advancedSchemaMessage, setAdvancedSchemaMessage] = useState<\n string | null\n >(null);\n const [activeTab, setActiveTab] = useState<BuilderTabKey>('design');\n const [selectedFieldKey, setSelectedFieldKey] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [renameModalOpen, setRenameModalOpen] = useState(false);\n const [loadedSnapshot, setLoadedSnapshot] = useState<BuilderSnapshot>(\n readBuilderSnapshot(EMPTY_SCHEMA, EMPTY_UI_SCHEMA),\n );\n const [loading, setLoading] = useState(true);\n const [renaming, setRenaming] = useState(false);\n const [saving, setSaving] = useState(false);\n\n useEffect((): void => {\n void refreshBuilder();\n }, [formDefinitionId]);\n\n useEffect((): void => {\n const hasSelectedField = schema.fields.some(\n (field) => field.fieldKey === selectedFieldKey,\n );\n\n if (hasSelectedField) {\n return;\n }\n\n setSelectedFieldKey(schema.fields[0]?.fieldKey ?? null);\n }, [schema.fields, selectedFieldKey]);\n\n useEffect((): void => {\n setPreviewValues((currentValues) =>\n buildFormRendererValues(schema.fields, currentValues),\n );\n }, [schema.fields]);\n\n useEffect((): void => {\n if (activeTab === 'advanced') {\n return;\n }\n\n setSchemaJsonText(stringifyJson(schema));\n setUiSchemaJsonText(stringifyJson(uiSchema));\n }, [activeTab, schema, uiSchema]);\n\n const selectedField = useMemo(\n (): FormFieldDefinition | null =>\n schema.fields.find((field) => field.fieldKey === selectedFieldKey) ??\n schema.fields[0] ??\n null,\n [schema.fields, selectedFieldKey],\n );\n const versionRows = useMemo(\n (): VersionRow[] =>\n (record?.versions ?? []).map((version) => ({\n key: version.id,\n publishedAt: formatDateTime(version.publishedAt),\n status: version.status,\n updatedAt: formatDateTime(version.updatedAt),\n version: `v${version.version}`,\n })),\n [record],\n );\n const versionColumns = useMemo(\n (): TableColumn<VersionRow>[] => [\n { dataIndex: 'version', key: 'version', title: '版本', width: 120 },\n {\n key: 'status',\n render: (record: VersionRow): ReactElement => (\n <FormVersionStatusBadge status={record.status} />\n ),\n title: '狀態',\n width: 140,\n },\n {\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n title: '最後更新',\n width: 180,\n },\n {\n dataIndex: 'publishedAt',\n key: 'publishedAt',\n title: '發布時間',\n width: 180,\n },\n ],\n [],\n );\n const currentSnapshot = useMemo(\n (): BuilderSnapshot => readBuilderSnapshot(schema, uiSchema),\n [schema, uiSchema],\n );\n const hasUnsavedChanges =\n currentSnapshot.schemaJson !== loadedSnapshot.schemaJson ||\n currentSnapshot.uiSchemaJson !== loadedSnapshot.uiSchemaJson;\n\n useEffect((): (() => void) => {\n function handleBeforeUnload(event: BeforeUnloadEvent): void {\n if (!hasUnsavedChanges) {\n return;\n }\n\n event.preventDefault();\n event.returnValue = '';\n }\n\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return (): void => {\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [hasUnsavedChanges]);\n\n function handleBackToForms(): void {\n if (\n hasUnsavedChanges &&\n !window.confirm('目前有尚未儲存的表單草稿,確定要離開嗎?')\n ) {\n return;\n }\n\n router.push('/forms');\n }\n const latestPublishedVersion = useMemo(\n (): FormDefinitionVersionRecord | null =>\n readPublishedVersion(\n record?.versions ?? [],\n record?.definition.currentVersionId,\n ),\n [record?.definition.currentVersionId, record?.versions],\n );\n const openedVersion =\n draft ?? latestPublishedVersion ?? record?.versions[0] ?? null;\n const openedContentPublished =\n !hasUnsavedChanges && openedVersion?.status === 'PUBLISHED';\n const headerDescription = readHeaderDescription({\n hasUnsavedChanges,\n latestPublishedVersion,\n openedContentPublished,\n openedVersion,\n });\n const publishDisabled =\n saving || (!hasUnsavedChanges && openedContentPublished && !draft);\n const publishButtonText = hasUnsavedChanges\n ? '保存並發布'\n : draft\n ? '發布草稿'\n : openedContentPublished\n ? '已發布'\n : '發布版本';\n\n async function refreshBuilder(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n const nextRecord = await readFormBuilder(formDefinitionId);\n const nextDraft =\n nextRecord.versions.find((version) => version.status === 'DRAFT') ??\n null;\n\n setRecord(nextRecord);\n setDraft(nextDraft);\n const nextSchema =\n nextDraft?.schema ?? nextRecord.versions[0]?.schema ?? EMPTY_SCHEMA;\n const nextUiSchema =\n nextDraft?.uiSchema ??\n nextRecord.versions[0]?.uiSchema ??\n EMPTY_UI_SCHEMA;\n\n setSchema(nextSchema);\n setUiSchema(nextUiSchema);\n setLoadedSnapshot(readBuilderSnapshot(nextSchema, nextUiSchema));\n setSchemaJsonText(stringifyJson(nextSchema));\n setUiSchemaJsonText(stringifyJson(nextUiSchema));\n setSelectedFieldKey(\n nextDraft?.schema.fields[0]?.fieldKey ??\n nextRecord.versions[0]?.schema.fields[0]?.fieldKey ??\n null,\n );\n setAdvancedSchemaMessage(null);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function saveCurrentDraft(): Promise<FormDefinitionVersionRecord> {\n const targetDraft = draft ?? (await forkFormDefinition(formDefinitionId));\n const nextDraft = await updateFormDefinitionDraft(\n targetDraft.id,\n schema,\n uiSchema,\n );\n\n setDraft(nextDraft);\n\n return nextDraft;\n }\n\n async function handleSaveDraft(): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n await saveCurrentDraft();\n await refreshBuilder();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handlePublish(): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n const savedDraft = await saveCurrentDraft();\n await publishFormDefinitionVersion(savedDraft.id);\n await refreshBuilder();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handleRenameForm(name: string): Promise<void> {\n if (!record) {\n throw new Error('尚未載入表單資料');\n }\n\n setRenaming(true);\n\n try {\n const updatedDefinition = await updateFormDefinition(\n record.definition.id,\n name,\n );\n\n setRecord({\n ...record,\n definition: updatedDefinition,\n });\n setRenameModalOpen(false);\n } finally {\n setRenaming(false);\n }\n }\n\n function handleAddField(type: FieldType): void {\n const nextIndex = schema.fields.length + 1;\n const field = createFieldDefinition(type, nextIndex);\n\n setSchema({\n ...schema,\n fields: [...schema.fields, field],\n });\n setUiSchema({\n ...uiSchema,\n layout: [\n ...uiSchema.layout,\n {\n fieldKey: field.fieldKey,\n width:\n type === 'textarea' || type === 'file_upload' ? 'FULL' : 'HALF',\n },\n ],\n });\n setSelectedFieldKey(field.fieldKey);\n setActiveTab('design');\n setAdvancedSchemaMessage(null);\n }\n\n function handleTabChange(activeKey: Key): void {\n const nextTab = activeKey as BuilderTabKey;\n\n if (nextTab === 'advanced' && activeTab !== 'advanced') {\n setSchemaJsonText(stringifyJson(schema));\n setUiSchemaJsonText(stringifyJson(uiSchema));\n }\n\n setActiveTab(nextTab);\n }\n\n function handleRemoveField(fieldKey: string): void {\n const remainingFields = schema.fields.filter(\n (field) => field.fieldKey !== fieldKey,\n );\n\n setSchema({\n ...schema,\n fields: remainingFields,\n });\n setUiSchema({\n ...uiSchema,\n layout: uiSchema.layout.filter((item) => item.fieldKey !== fieldKey),\n });\n setSelectedFieldKey(\n selectedFieldKey === fieldKey\n ? (remainingFields[0]?.fieldKey ?? null)\n : selectedFieldKey,\n );\n setAdvancedSchemaMessage(null);\n }\n\n function handleFieldDragEnd(result: DropResult): void {\n const destination = result.destination;\n\n if (!destination) {\n return;\n }\n\n if (result.source.index === destination.index) {\n return;\n }\n\n setSchema((currentSchema) => ({\n ...currentSchema,\n fields: moveItemByIndex(\n currentSchema.fields,\n result.source.index,\n destination.index,\n ),\n }));\n setUiSchema((currentUiSchema) => ({\n ...currentUiSchema,\n layout: moveItemByIndex(\n currentUiSchema.layout,\n result.source.index,\n destination.index,\n ),\n }));\n setAdvancedSchemaMessage(null);\n }\n\n function updateSelectedField(\n patch: Partial<\n Pick<\n FormFieldDefinition,\n | 'defaultValue'\n | 'fieldKey'\n | 'label'\n | 'placeholder'\n | 'readonlyWhen'\n | 'required'\n | 'requiredWhen'\n | 'visibleWhen'\n >\n >,\n ): void {\n updateSelectedFieldWith(\n (field) => ({ ...field, ...patch }) as FormFieldDefinition,\n );\n }\n\n function updateSelectedFieldWith(\n updater: (field: FormFieldDefinition) => FormFieldDefinition,\n ): void {\n if (!selectedField) {\n return;\n }\n\n const previousFieldKey = selectedField.fieldKey;\n const nextField = updater(selectedField);\n const nextFieldKey = nextField.fieldKey;\n\n setSchema({\n ...schema,\n fields: schema.fields.map(\n (field): FormFieldDefinition =>\n field.fieldKey === previousFieldKey ? nextField : field,\n ),\n });\n setUiSchema({\n ...uiSchema,\n layout: uiSchema.layout.map((item) =>\n item.fieldKey === previousFieldKey\n ? { ...item, fieldKey: nextFieldKey }\n : item,\n ),\n });\n setSelectedFieldKey(nextFieldKey);\n setAdvancedSchemaMessage(null);\n }\n\n function updateSelectedTextField(\n patch: Partial<\n Pick<TextFieldDefinition, 'defaultValue' | 'maxLength' | 'minLength'>\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n isTextFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedNumberField(\n patch: Partial<\n Pick<NumberFieldDefinition, 'defaultValue' | 'maximum' | 'minimum'>\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n isNumberFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedDateField(\n patch: Partial<Pick<DateFieldDefinition, 'defaultValue'>>,\n ): void {\n updateSelectedFieldWith((field) =>\n isDateFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedSelectField(\n patch: Partial<Pick<SelectFieldDefinition, 'defaultValue' | 'options'>>,\n ): void {\n updateSelectedFieldWith((field) =>\n isSelectFieldDefinition(field) ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedBooleanField(\n patch: Partial<Pick<BooleanFieldDefinition, 'defaultValue'>>,\n ): void {\n updateSelectedFieldWith((field) =>\n field.type === 'boolean' ? { ...field, ...patch } : field,\n );\n }\n\n function updateSelectedFileUploadField(\n patch: Partial<\n Pick<\n FileUploadFieldDefinition,\n 'acceptedMimeTypes' | 'defaultValue' | 'maxFiles'\n >\n >,\n ): void {\n updateSelectedFieldWith((field) =>\n field.type === 'file_upload' ? { ...field, ...patch } : field,\n );\n }\n\n function updatePreviewValues(values: FormRendererValues): void {\n setPreviewValues(values);\n }\n\n function updateFieldRequired(fieldKey: string, required: boolean): void {\n setSchema((currentSchema) => ({\n ...currentSchema,\n fields: currentSchema.fields.map(\n (field): FormFieldDefinition =>\n field.fieldKey === fieldKey\n ? ({ ...field, required } as FormFieldDefinition)\n : field,\n ),\n }));\n setAdvancedSchemaMessage(null);\n }\n\n function updateSchemaJson(value: string): void {\n setSchemaJsonText(value);\n\n try {\n setSchema(JSON.parse(value) as FormDefinitionSchema);\n setAdvancedSchemaMessage(null);\n } catch {\n setAdvancedSchemaMessage('Form Schema JSON 格式不正確');\n }\n }\n\n function updateUiSchemaJson(value: string): void {\n setUiSchemaJsonText(value);\n\n try {\n setUiSchema(JSON.parse(value) as FormUiSchema);\n setAdvancedSchemaMessage(null);\n } catch {\n setAdvancedSchemaMessage('UI Schema JSON 格式不正確');\n }\n }\n\n return (\n <>\n <AppLayout activeHref=\"/forms\">\n <PageHeader>\n <ContentHeader\n description={headerDescription}\n onBackClick={handleBackToForms}\n title={record?.definition.name ?? '表單設計器'}\n >\n <Button\n aria-label=\"修改表單名稱\"\n disabled={renaming || !record}\n icon={EditIcon}\n iconType=\"icon-only\"\n onClick={(): void => setRenameModalOpen(true)}\n variant=\"base-ghost\"\n >\n 修改表單名稱\n </Button>\n <Button\n aria-label=\"儲存草稿\"\n disabled={saving || !hasUnsavedChanges}\n icon={SaveIcon}\n iconType=\"icon-only\"\n onClick={(): void => void handleSaveDraft()}\n variant=\"base-secondary\"\n >\n 儲存草稿\n </Button>\n <Button\n disabled={publishDisabled}\n icon={CheckedIcon}\n iconType=\"leading\"\n onClick={(): void => void handlePublish()}\n variant=\"base-primary\"\n >\n {publishButtonText}\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section>\n <div style={WORKBENCH_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Tab\n activeKey={activeTab}\n onChange={handleTabChange}\n size=\"sub\"\n >\n <TabItem key=\"design\">設計</TabItem>\n <TabItem key=\"preview\">預覽</TabItem>\n <TabItem key=\"versions\">版本</TabItem>\n <TabItem key=\"advanced\">進階</TabItem>\n </Tab>\n\n {activeTab === 'design' ? renderDesignTab() : null}\n {activeTab === 'preview' ? renderPreviewTab() : null}\n {activeTab === 'versions' ? renderVersionsTab() : null}\n {activeTab === 'advanced' ? renderAdvancedTab() : null}\n </div>\n </Section>\n </SectionGroup>\n </AppLayout>\n\n <FormNameModal\n confirmText=\"儲存\"\n initialName={record?.definition.name ?? ''}\n loading={renaming}\n onClose={(): void => setRenameModalOpen(false)}\n onSubmit={handleRenameForm}\n open={renameModalOpen}\n title=\"修改表單名稱\"\n />\n </>\n );\n\n function renderDesignTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <div style={FIELD_LIBRARY_HEADER_STYLE}>\n <Typography component=\"h2\" variant=\"label-primary\">\n 新增欄位\n </Typography>\n <div style={FIELD_LIBRARY_STYLE}>\n {FIELD_TYPE_OPTIONS.map((option) => (\n <Button\n disabled={saving}\n icon={option.icon}\n iconType=\"leading\"\n key={option.type}\n onClick={(): void => handleAddField(option.type)}\n size=\"sub\"\n style={FIELD_LIBRARY_BUTTON_STYLE}\n type=\"button\"\n variant=\"base-secondary\"\n >\n {option.label}\n </Button>\n ))}\n </div>\n </div>\n\n <div style={WORKSPACE_GRID_STYLE}>\n <div style={{ ...STACK_STYLE, ...CANVAS_COLUMN_STYLE }}>\n <Typography component=\"h2\" variant=\"label-primary\">\n 表單畫布\n </Typography>\n {schema.fields.length > 0 ? (\n <DragDropContext onDragEnd={handleFieldDragEnd}>\n <Droppable droppableId=\"form-builder-fields\">\n {(droppableProvided): ReactElement => (\n <div\n {...droppableProvided.droppableProps}\n ref={droppableProvided.innerRef}\n style={STACK_STYLE}\n >\n {schema.fields.map((field, index) => (\n <Draggable\n draggableId={field.fieldKey}\n index={index}\n isDragDisabled={saving}\n key={field.fieldKey}\n >\n {(draggableProvided, snapshot): ReactElement =>\n renderFieldBlock(\n field,\n draggableProvided,\n snapshot.isDragging,\n )\n }\n </Draggable>\n ))}\n {droppableProvided.placeholder}\n </div>\n )}\n </Droppable>\n </DragDropContext>\n ) : (\n <div style={EMPTY_CANVAS_STYLE}>\n <div style={STACK_STYLE}>\n <Typography component=\"h3\" variant=\"h3\">\n 尚未建立欄位\n </Typography>\n <Typography color=\"text-neutral\" variant=\"body\">\n 從上方新增第一個欄位,或直接建立常用文字欄位開始設計。\n </Typography>\n </div>\n <div style={EMPTY_CANVAS_ACTIONS_STYLE}>\n <Button\n disabled={saving}\n onClick={(): void => handleAddField('text')}\n variant=\"base-primary\"\n >\n 新增文字欄位\n </Button>\n <Button\n disabled={saving}\n onClick={(): void => handleAddField('textarea')}\n variant=\"base-secondary\"\n >\n 新增長文字\n </Button>\n </div>\n </div>\n )}\n </div>\n\n <div style={{ ...STACK_STYLE, ...SETTINGS_COLUMN_STYLE }}>\n <Typography component=\"h2\" variant=\"label-primary\">\n 欄位設定\n </Typography>\n {selectedField ? (\n renderFieldSettings(selectedField)\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 請先新增或選取欄位。\n </Typography>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n function renderFieldSettings(field: FormFieldDefinition): ReactElement {\n return (\n <div style={FIELD_SETTINGS_FORM_STYLE}>\n {renderMainFieldSettings(field)}\n {renderAdvancedFieldSettings(field)}\n </div>\n );\n }\n\n function renderMainFieldSettings(field: FormFieldDefinition): ReactElement {\n return (\n <div style={FIELD_SETTINGS_SECTION_STYLE}>\n <div style={FIELD_SETTINGS_BADGE_ROW_STYLE}>\n <Badge\n size=\"main\"\n text={readFieldTypeLabel(field.type)}\n variant=\"text-info\"\n />\n </div>\n {renderSettingsFormRow(\n '標題',\n 'fieldLabel',\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedField({ label: event.target.value })\n }\n placeholder=\"例如:申請金額\"\n value={field.label}\n variant=\"base\"\n />,\n saving,\n )}\n {renderSettingsFormRow(\n '欄位 Key',\n 'fieldKey',\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedField({ fieldKey: event.target.value })\n }\n placeholder=\"例如:amount\"\n value={field.fieldKey}\n variant=\"base\"\n />,\n saving,\n )}\n {renderSettingsFormRow(\n '提示文字',\n 'fieldPlaceholder',\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedField({\n placeholder: event.target.value || undefined,\n })\n }\n placeholder=\"例如:請輸入申請金額\"\n value={field.placeholder ?? ''}\n variant=\"base\"\n />,\n saving,\n )}\n {renderTypeSpecificSettings(field)}\n </div>\n );\n }\n\n function renderAdvancedFieldSettings(\n field: FormFieldDefinition,\n ): ReactElement {\n return (\n <Accordion\n defaultExpanded={hasConditionRules(field)}\n size=\"sub\"\n title=\"進階設定\"\n >\n <div style={FIELD_SETTINGS_SECTION_STYLE}>\n <Typography\n component=\"h3\"\n style={FIELD_SETTINGS_SECTION_TITLE_STYLE}\n variant=\"label-primary\"\n >\n 條件規則\n </Typography>\n <Typography\n color=\"text-neutral\"\n style={FIELD_SETTINGS_HINT_STYLE}\n variant=\"body\"\n >\n 只有需要根據其他欄位改變顯示、必填或唯讀狀態時才需要設定。\n </Typography>\n {renderConditionSettings(field)}\n </div>\n </Accordion>\n );\n }\n\n function renderTypeSpecificSettings(\n field: FormFieldDefinition,\n ): ReactElement {\n if (isTextFieldDefinition(field)) {\n return renderTextFieldSettings(field);\n }\n\n if (isNumberFieldDefinition(field)) {\n return renderNumberFieldSettings(field);\n }\n\n if (isDateFieldDefinition(field)) {\n return renderDateFieldSettings(field);\n }\n\n if (isSelectFieldDefinition(field)) {\n return renderSelectFieldSettings(field);\n }\n\n if (field.type === 'boolean') {\n return renderBooleanFieldSettings(field);\n }\n\n return renderFileUploadFieldSettings(field);\n }\n\n function renderTextFieldSettings(field: TextFieldDefinition): ReactElement {\n return (\n <>\n {renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n field.type === 'textarea' ? (\n renderSettingsTextarea({\n disabled: saving,\n name: 'fieldDefaultValue',\n onChange: (value): void =>\n updateSelectedTextField({ defaultValue: value || undefined }),\n placeholder: '輸入此欄位的預設文字',\n rows: 3,\n value: readStringDefaultValue(field.defaultValue),\n })\n ) : (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedTextField({\n defaultValue: event.target.value || undefined,\n })\n }\n placeholder=\"輸入此欄位的預設文字\"\n value={readStringDefaultValue(field.defaultValue)}\n variant=\"base\"\n />\n ),\n saving,\n )}\n {renderSettingsFormRow(\n '最小長度',\n 'fieldMinLength',\n renderNumberInput(\n field.minLength,\n (value): void => updateSelectedTextField({ minLength: value }),\n '例如:2',\n { min: 0 },\n ),\n saving,\n )}\n {renderSettingsFormRow(\n '最大長度',\n 'fieldMaxLength',\n renderNumberInput(\n field.maxLength,\n (value): void => updateSelectedTextField({ maxLength: value }),\n '例如:100',\n { min: 1 },\n ),\n saving,\n )}\n </>\n );\n }\n\n function renderNumberFieldSettings(\n field: NumberFieldDefinition,\n ): ReactElement {\n return (\n <>\n {renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n renderNumberInput(\n typeof field.defaultValue === 'number'\n ? field.defaultValue\n : undefined,\n (value): void => updateSelectedNumberField({ defaultValue: value }),\n field.type === 'money' ? '例如:1000' : '輸入預設數值',\n { max: field.maximum, min: field.minimum },\n ),\n saving,\n )}\n {renderSettingsFormRow(\n '最小值',\n 'fieldMinimum',\n renderNumberInput(\n field.minimum,\n (value): void => updateSelectedNumberField({ minimum: value }),\n '例如:0',\n ),\n saving,\n )}\n {renderSettingsFormRow(\n '最大值',\n 'fieldMaximum',\n renderNumberInput(\n field.maximum,\n (value): void => updateSelectedNumberField({ maximum: value }),\n '例如:999999',\n ),\n saving,\n )}\n </>\n );\n }\n\n function renderDateFieldSettings(field: DateFieldDefinition): ReactElement {\n return renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n renderDateValuePicker(\n field,\n readStringDefaultValue(field.defaultValue),\n (value): void => updateSelectedDateField({ defaultValue: value }),\n ),\n saving,\n );\n }\n\n function renderSelectFieldSettings(\n field: SelectFieldDefinition,\n ): ReactElement {\n const defaultValues = Array.isArray(field.defaultValue)\n ? field.defaultValue\n : [];\n const selectedValues = field.options\n .filter((option) => defaultValues.includes(option.value))\n .map(readFieldOptionAsSelectOption);\n\n return (\n <>\n {renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n field.type === 'checkbox' ? (\n <Select\n clearable\n mode=\"multiple\"\n onChange={(options): void =>\n updateSelectedSelectField({\n defaultValue: options.length\n ? options.map((option) => option.id)\n : undefined,\n })\n }\n options={field.options.map(readFieldOptionAsSelectOption)}\n placeholder=\"選擇一或多個預設選項\"\n value={selectedValues}\n />\n ) : (\n <Select\n clearable\n onChange={(option): void =>\n updateSelectedSelectField({\n defaultValue: option?.id || undefined,\n })\n }\n options={field.options.map(readFieldOptionAsSelectOption)}\n placeholder=\"選擇預設選項\"\n value={\n typeof field.defaultValue === 'string'\n ? readSelectOption(\n field.options.map(readFieldOptionAsSelectOption),\n field.defaultValue,\n )\n : null\n }\n />\n ),\n saving,\n )}\n {renderSettingsFormRow(\n '選項',\n 'fieldOptions',\n renderFieldOptionsTable(field),\n saving,\n true,\n )}\n </>\n );\n }\n\n function renderBooleanFieldSettings(\n field: BooleanFieldDefinition,\n ): ReactElement {\n const defaultValue =\n typeof field.defaultValue === 'boolean'\n ? String(field.defaultValue)\n : 'unset';\n\n return renderSettingsFormRow(\n '預設值',\n 'fieldDefaultValue',\n <Select\n clearable={false}\n onChange={(option): void =>\n updateSelectedBooleanField({\n defaultValue:\n option?.id === 'true'\n ? true\n : option?.id === 'false'\n ? false\n : undefined,\n })\n }\n options={[...BOOLEAN_DEFAULT_OPTIONS]}\n placeholder=\"選擇預設狀態\"\n value={readSelectOption(BOOLEAN_DEFAULT_OPTIONS, defaultValue)}\n />,\n saving,\n );\n }\n\n function renderFileUploadFieldSettings(\n field: FileUploadFieldDefinition,\n ): ReactElement {\n return (\n <>\n {renderSettingsFormRow(\n '檔案數',\n 'fieldMaxFiles',\n renderNumberInput(\n field.maxFiles,\n (value): void => updateSelectedFileUploadField({ maxFiles: value }),\n '例如:1',\n { min: 1 },\n ),\n saving,\n )}\n {renderSettingsFormRow(\n 'MIME',\n 'fieldAcceptedMimeTypes',\n renderSettingsTextarea({\n disabled: saving,\n name: 'fieldAcceptedMimeTypes',\n onChange: (value): void =>\n updateSelectedFileUploadField({\n acceptedMimeTypes: parseStringList(value),\n }),\n placeholder: '每行一個 MIME type,例如:application/pdf',\n rows: 3,\n value: readStringListInput(field.acceptedMimeTypes),\n }),\n false,\n )}\n </>\n );\n }\n\n function renderConditionSettings(field: FormFieldDefinition): ReactElement {\n const conditionFieldOptions = schema.fields.filter(\n (schemaField) => schemaField.fieldKey !== field.fieldKey,\n );\n\n if (!conditionFieldOptions.length) {\n return (\n <Typography\n color=\"text-neutral\"\n style={FIELD_SETTINGS_HINT_STYLE}\n variant=\"body\"\n >\n 目前沒有其他欄位可作為條件來源。新增更多欄位後即可設定條件規則。\n </Typography>\n );\n }\n\n return (\n <>\n {CONDITION_RULE_CONFIGS.map((config) =>\n renderConditionRule(field, config, conditionFieldOptions),\n )}\n </>\n );\n }\n\n function renderConditionRule(\n field: FormFieldDefinition,\n config: ConditionRuleConfig,\n conditionFieldOptions: readonly FormFieldDefinition[],\n ): ReactElement {\n const expression = field[config.target];\n const parsedRule = expression ? parseConditionRule(expression) : null;\n const parsedConditionField = conditionFieldOptions.find(\n (conditionField) => conditionField.fieldKey === parsedRule?.fieldKey,\n );\n const selectedConditionField =\n parsedConditionField ?? conditionFieldOptions[0];\n const conditionFieldSelectOptions = conditionFieldOptions.map(\n readFieldAsConditionSelectOption,\n );\n const conditionOperatorOptions = readConditionOperatorOptions(\n selectedConditionField,\n );\n const selectedOperator =\n parsedRule &&\n conditionOperatorOptions.some(\n (option) => option.id === parsedRule.operator,\n )\n ? parsedRule.operator\n : readDefaultConditionOperator(selectedConditionField);\n const selectedValue =\n parsedRule?.value ?? readDefaultConditionValue(selectedConditionField);\n const enabled = Boolean(expression);\n const unsupportedRule = enabled && (!parsedRule || !parsedConditionField);\n\n return renderSettingsFormRow(\n config.label,\n config.name,\n <div style={CONDITION_RULE_CONTROL_STYLE}>\n <Toggle\n checked={enabled}\n disabled={saving}\n label={enabled ? '已啟用' : '不啟用'}\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedConditionRule(\n config.target,\n event.target.checked\n ? buildConditionExpression(\n selectedConditionField,\n readDefaultConditionOperator(selectedConditionField),\n readDefaultConditionValue(selectedConditionField),\n )\n : undefined,\n )\n }\n size=\"sub\"\n supportingText={config.supportingText}\n />\n {enabled ? (\n unsupportedRule ? (\n <Typography color=\"text-warning\" variant=\"body\">\n 這個規則不是目前 UI 支援的格式。重新選擇條件後會取代既有規則。\n </Typography>\n ) : (\n <div style={CONDITION_RULE_GRID_STYLE}>\n <Select\n clearable={false}\n onChange={(option): void => {\n const nextField =\n conditionFieldOptions.find(\n (conditionField) =>\n conditionField.fieldKey === option?.id,\n ) ?? selectedConditionField;\n\n updateSelectedConditionRule(\n config.target,\n buildConditionExpression(\n nextField,\n readDefaultConditionOperator(nextField),\n readDefaultConditionValue(nextField),\n ),\n );\n }}\n options={conditionFieldSelectOptions}\n placeholder=\"選擇欄位\"\n value={readSelectOption(\n conditionFieldSelectOptions,\n selectedConditionField.fieldKey,\n )}\n />\n <Select\n clearable={false}\n onChange={(option): void =>\n updateSelectedConditionRule(\n config.target,\n buildConditionExpression(\n selectedConditionField,\n readConditionOperatorOption(option?.id) ??\n selectedOperator,\n selectedValue,\n ),\n )\n }\n options={[...conditionOperatorOptions]}\n placeholder=\"判斷方式\"\n value={readSelectOption(\n conditionOperatorOptions,\n selectedOperator,\n )}\n />\n {renderConditionValueControl(\n selectedConditionField,\n selectedValue,\n (nextValue): void =>\n updateSelectedConditionRule(\n config.target,\n buildConditionExpression(\n selectedConditionField,\n selectedOperator,\n nextValue,\n ),\n ),\n )}\n </div>\n )\n ) : null}\n </div>,\n saving,\n true,\n );\n }\n\n function updateSelectedConditionRule(\n target: ConditionRuleTarget,\n expression: string | undefined,\n ): void {\n updateSelectedField({ [target]: expression });\n }\n\n function renderConditionValueControl(\n conditionField: FormFieldDefinition,\n value: string,\n onChange: (value: string) => void,\n ): ReactElement {\n if (conditionField.type === 'boolean') {\n return (\n <Select\n clearable={false}\n onChange={(option): void => onChange(option?.id ?? 'true')}\n options={[...BOOLEAN_CONDITION_VALUE_OPTIONS]}\n placeholder=\"比較值\"\n value={readSelectOption(\n BOOLEAN_CONDITION_VALUE_OPTIONS,\n value === 'false' ? 'false' : 'true',\n )}\n />\n );\n }\n\n if (isSelectFieldDefinition(conditionField)) {\n const options = conditionField.options.map(readFieldOptionAsSelectOption);\n\n return (\n <Select\n clearable={false}\n onChange={(option): void =>\n onChange(option?.id ?? options[0]?.id ?? '')\n }\n options={options}\n placeholder=\"比較值\"\n value={readSelectOption(options, value)}\n />\n );\n }\n\n if (isNumberFieldDefinition(conditionField)) {\n return renderNumberInput(\n parseOptionalNumberInput(value),\n (nextValue): void => onChange(String(nextValue ?? 0)),\n '比較值',\n );\n }\n\n if (isDateFieldDefinition(conditionField)) {\n return renderDateValuePicker(conditionField, value, (nextValue): void =>\n onChange(nextValue ?? ''),\n );\n }\n\n return (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onChange(event.target.value)\n }\n placeholder=\"比較值\"\n value={value}\n variant=\"base\"\n />\n );\n }\n\n function renderSettingsTextarea({\n disabled,\n name,\n onChange,\n placeholder,\n rows,\n value,\n }: {\n readonly disabled: boolean;\n readonly name: string;\n readonly onChange: (value: string) => void;\n readonly placeholder: string;\n readonly rows: number;\n readonly value: string;\n }): ReactElement {\n return (\n <Textarea\n aria-label={name}\n disabled={disabled}\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n onChange(event.target.value)\n }\n placeholder={placeholder}\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={rows}\n style={FIELD_SETTINGS_TEXTAREA_STYLE}\n value={value}\n />\n );\n }\n\n function renderNumberInput(\n value: number | undefined,\n onChange: (value: number | undefined) => void,\n placeholder: string,\n options: {\n readonly max?: number;\n readonly min?: number;\n readonly step?: number;\n } = {},\n ): ReactElement {\n return (\n <Input\n max={options.max}\n min={options.min}\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n onChange(\n clampOptionalNumber(\n parseOptionalNumberInput(event.target.value),\n options,\n ),\n )\n }\n placeholder={placeholder}\n showSpinner\n step={options.step ?? 1}\n value={typeof value === 'number' ? String(value) : ''}\n variant=\"measure\"\n />\n );\n }\n\n function renderDateValuePicker(\n field: DateFieldDefinition,\n value: string,\n onChange: (value: string | undefined) => void,\n ): ReactElement {\n if (field.type === 'datetime') {\n return (\n <DateTimePicker\n formatDate=\"YYYY-MM-DD\"\n formatTime=\"HH:mm\"\n hideSecond\n onChange={(nextValue): void =>\n onChange(formatDateTimePickerValue(nextValue))\n }\n placeholderLeft=\"選擇日期\"\n placeholderRight=\"選擇時間\"\n value={readDatePickerValue(value)}\n />\n );\n }\n\n return (\n <DatePicker\n format=\"YYYY-MM-DD\"\n onChange={(nextValue): void =>\n onChange(formatDatePickerValue(nextValue))\n }\n placeholder=\"選擇日期\"\n value={readDatePickerValue(value)}\n />\n );\n }\n\n function renderFieldOptionsTable(field: SelectFieldDefinition): ReactElement {\n const optionRows: FieldOptionRow[] = field.options.map((option, index) => ({\n index,\n key: `${field.fieldKey}-${index}`,\n label: option.label,\n value: option.value,\n }));\n const optionColumns: TableColumn<FieldOptionRow>[] = [\n {\n key: 'label',\n render: (row): ReactElement => (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedSelectField({\n options: updateFieldOption(field.options, row.index, {\n label: event.target.value,\n }),\n })\n }\n placeholder=\"例如:主管\"\n size=\"sub\"\n value={row.label}\n variant=\"base\"\n />\n ),\n title: 'Label',\n },\n {\n key: 'value',\n render: (row): ReactElement => (\n <Input\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateSelectedSelectField({\n options: updateFieldOption(field.options, row.index, {\n value: event.target.value,\n }),\n })\n }\n placeholder=\"例如:manager\"\n size=\"sub\"\n value={row.value}\n variant=\"base\"\n />\n ),\n title: 'Value',\n },\n ];\n const optionActions: TableActions<FieldOptionRow> = {\n render: (row): ReturnType<TableActions<FieldOptionRow>['render']> => [\n {\n disabled: (): boolean => saving || field.options.length <= 1,\n icon: TrashIcon,\n iconType: 'icon-only',\n name: '移除選項',\n onClick: (): void =>\n updateSelectedSelectField({\n options: field.options.filter((_, index) => index !== row.index),\n }),\n variant: 'destructive-ghost',\n },\n ],\n width: 56,\n };\n\n return (\n <div style={COMPACT_STACK_STYLE}>\n <Table\n actions={optionActions}\n columns={optionColumns}\n dataSource={optionRows}\n showHeader\n size=\"sub\"\n />\n <div style={OPTION_ACTIONS_STYLE}>\n <Button\n disabled={saving}\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n updateSelectedSelectField({\n options: [\n ...field.options,\n createNextFieldOption(field.options),\n ],\n })\n }\n variant=\"base-secondary\"\n >\n 新增選項\n </Button>\n </div>\n </div>\n );\n }\n\n function renderFieldBlock(\n field: FormFieldDefinition,\n draggableProvided: DraggableProvided,\n isDragging: boolean,\n ): ReactElement {\n return (\n <div\n {...draggableProvided.draggableProps}\n data-form-builder-field-key={field.fieldKey}\n ref={draggableProvided.innerRef}\n style={{\n ...FIELD_BLOCK_STYLE,\n ...(isDragging ? FIELD_BLOCK_DRAGGING_STYLE : null),\n ...draggableProvided.draggableProps.style,\n }}\n >\n <BaseCard>\n {renderFieldBlockContent(field, draggableProvided, isDragging)}\n </BaseCard>\n </div>\n );\n }\n\n function renderSettingsFormRow(\n label: string,\n name: string,\n control: ReactElement,\n disabled: boolean,\n wide = false,\n ): ReactElement {\n return (\n <div\n style={wide ? FIELD_SETTINGS_ROW_WIDE_STYLE : FIELD_SETTINGS_ROW_STYLE}\n >\n <div style={FIELD_SETTINGS_VALUE_STYLE}>\n <BPMFormField disabled={disabled} label={label} name={name}>\n {control}\n </BPMFormField>\n </div>\n </div>\n );\n }\n\n function renderFieldBlockContent(\n field: FormFieldDefinition,\n draggableProvided: DraggableProvided,\n isDragging: boolean,\n ): ReactElement {\n return (\n <div\n {...(draggableProvided.dragHandleProps ?? {})}\n aria-label=\"拖曳排序欄位\"\n style={FIELD_BLOCK_ROW_STYLE}\n title=\"拖曳排序\"\n >\n <span\n aria-label=\"拖曳排序\"\n role=\"img\"\n style={DRAG_HANDLE_STYLE}\n title=\"拖曳排序\"\n >\n <Icon icon={DotDragVerticalIcon} size={20} />\n </span>\n <div style={FIELD_BLOCK_TEXT_STYLE}>\n <Typography component=\"span\" ellipsis variant=\"label-primary\">\n {field.label}\n {field.required ? (\n <sup aria-label=\"必填\" style={REQUIRED_ASTERISK_STYLE}>\n *\n </sup>\n ) : null}\n </Typography>\n <Typography\n color=\"text-neutral\"\n component=\"span\"\n ellipsis\n variant=\"caption\"\n >\n {readFieldTypeLabel(field.type)} ·\n {field.required ? ' 必填' : ' 選填'} ·{field.fieldKey}\n </Typography>\n </div>\n <div style={FIELD_BLOCK_ACTIONS_STYLE}>\n <div style={FIELD_BLOCK_REQUIRED_STYLE}>\n <Toggle\n checked={Boolean(field.required)}\n disabled={saving || isDragging}\n label=\"必填\"\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n updateFieldRequired(field.fieldKey, event.target.checked)\n }\n />\n </div>\n <Button\n disabled={isDragging}\n icon={EditIcon}\n iconType=\"icon-only\"\n onClick={(): void => setSelectedFieldKey(field.fieldKey)}\n variant={\n field.fieldKey === selectedField?.fieldKey\n ? 'base-primary'\n : 'base-ghost'\n }\n >\n 編輯欄位\n </Button>\n <Button\n disabled={saving || isDragging}\n icon={TrashIcon}\n iconType=\"icon-only\"\n onClick={(): void => handleRemoveField(field.fieldKey)}\n variant=\"destructive-ghost\"\n >\n 移除欄位\n </Button>\n </div>\n </div>\n );\n }\n\n function renderPreviewTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 填寫預覽\n </Typography>\n <FormRenderer\n onChange={updatePreviewValues}\n schema={schema}\n uiSchema={uiSchema}\n value={previewValues}\n />\n </div>\n );\n }\n\n function renderVersionsTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 版本紀錄\n </Typography>\n <Table\n columns={versionColumns}\n dataSource={versionRows}\n loading={loading}\n />\n </div>\n );\n }\n\n function renderAdvancedTab(): ReactElement {\n return (\n <div style={STACK_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n Schema\n </Typography>\n <div style={ADVANCED_SCHEMA_FORM_STYLE}>\n {renderAdvancedSchemaRow(\n 'Form Schema',\n 'schemaJson',\n <JsonCodeEditor\n disabled={saving}\n height=\"360px\"\n name=\"schemaJson\"\n onChange={updateSchemaJson}\n placeholder=\"輸入 Form Schema JSON\"\n value={schemaJsonText}\n />,\n )}\n {renderAdvancedSchemaRow(\n 'UI Schema',\n 'uiSchemaJson',\n <JsonCodeEditor\n disabled={saving}\n height=\"240px\"\n name=\"uiSchemaJson\"\n onChange={updateUiSchemaJson}\n placeholder=\"輸入 UI Schema JSON\"\n value={uiSchemaJsonText}\n />,\n )}\n {advancedSchemaMessage ? (\n <Typography\n color=\"text-error\"\n style={ADVANCED_SCHEMA_MESSAGE_STYLE}\n variant=\"body\"\n >\n {advancedSchemaMessage}\n </Typography>\n ) : null}\n </div>\n </div>\n );\n }\n\n function renderAdvancedSchemaRow(\n label: string,\n name: string,\n control: ReactElement,\n ): ReactElement {\n return (\n <div style={ADVANCED_SCHEMA_ROW_STYLE}>\n <div style={ADVANCED_SCHEMA_VALUE_STYLE}>\n <BPMFormField disabled={saving} label={label} name={name}>\n {control}\n </BPMFormField>\n </div>\n </div>\n );\n }\n}\n\nfunction readFieldTypeLabel(type: FieldType): string {\n return (\n FIELD_TYPE_OPTIONS.find((option) => option.type === type)?.label ?? type\n );\n}\n\nfunction hasConditionRules(field: FormFieldDefinition): boolean {\n return Boolean(field.visibleWhen || field.requiredWhen || field.readonlyWhen);\n}\n\nfunction readFieldAsConditionSelectOption(field: FormFieldDefinition): {\n readonly id: string;\n readonly name: string;\n} {\n return {\n id: field.fieldKey,\n name: field.label,\n };\n}\n\nfunction isTextFieldDefinition(\n field: FormFieldDefinition,\n): field is TextFieldDefinition {\n return field.type === 'text' || field.type === 'textarea';\n}\n\nfunction readStringDefaultValue(\n value: FormFieldDefinition['defaultValue'],\n): string {\n return typeof value === 'string' ? value : '';\n}\n\nfunction parseStringList(value: string): readonly string[] | undefined {\n const values = value\n .split(/[\\n,]/u)\n .map((item) => item.trim())\n .filter(Boolean);\n\n return values.length ? values : undefined;\n}\n\nfunction readStringListInput(value: readonly string[] | undefined): string {\n return value?.join('\\n') ?? '';\n}\n\nfunction stringifyJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction updateFieldOption(\n options: readonly FormFieldOption[],\n targetIndex: number,\n patch: Partial<FormFieldOption>,\n): readonly FormFieldOption[] {\n return options.map((option, index) =>\n index === targetIndex ? { ...option, ...patch } : option,\n );\n}\n\nfunction createNextFieldOption(\n options: readonly FormFieldOption[],\n): FormFieldOption {\n const nextIndex = options.length + 1;\n\n return {\n label: `選項 ${nextIndex}`,\n value: readNextOptionValue(options, nextIndex),\n };\n}\n\nfunction readNextOptionValue(\n options: readonly FormFieldOption[],\n index: number,\n): string {\n const value = `option_${index}`;\n\n return options.some((option) => option.value === value)\n ? readNextOptionValue(options, index + 1)\n : value;\n}\n\nfunction readBuilderSnapshot(\n schema: FormDefinitionSchema,\n uiSchema: FormUiSchema,\n): BuilderSnapshot {\n return {\n schemaJson: stringifyJson(schema),\n uiSchemaJson: stringifyJson(uiSchema),\n };\n}\n\nfunction readPublishedVersion(\n versions: readonly FormDefinitionVersionRecord[],\n currentVersionId: string | null | undefined,\n): FormDefinitionVersionRecord | null {\n return (\n (currentVersionId\n ? versions.find((version) => version.id === currentVersionId)\n : null) ??\n versions.find((version) => version.status === 'PUBLISHED') ??\n null\n );\n}\n\nfunction readHeaderDescription({\n hasUnsavedChanges,\n latestPublishedVersion,\n openedContentPublished,\n openedVersion,\n}: {\n readonly hasUnsavedChanges: boolean;\n readonly latestPublishedVersion: FormDefinitionVersionRecord | null;\n readonly openedContentPublished: boolean;\n readonly openedVersion: FormDefinitionVersionRecord | null;\n}): string {\n const editState = hasUnsavedChanges ? '有未儲存修改' : '沒有未儲存修改';\n const openedState = readOpenedVersionState({\n hasUnsavedChanges,\n openedContentPublished,\n openedVersion,\n });\n const publishedState = latestPublishedVersion\n ? `目前發布 v${latestPublishedVersion.version}:${formatDateTime(\n latestPublishedVersion.publishedAt,\n )}`\n : '目前沒有已發布版本';\n\n return `${editState} · ${openedState} · ${publishedState}`;\n}\n\nfunction readOpenedVersionState({\n hasUnsavedChanges,\n openedContentPublished,\n openedVersion,\n}: {\n readonly hasUnsavedChanges: boolean;\n readonly openedContentPublished: boolean;\n readonly openedVersion: FormDefinitionVersionRecord | null;\n}): string {\n if (hasUnsavedChanges) {\n return openedVersion\n ? `修改尚未發布,來源 v${openedVersion.version}`\n : '修改尚未發布';\n }\n\n if (openedContentPublished && openedVersion) {\n return `當前內容已發布 v${openedVersion.version}`;\n }\n\n if (openedVersion) {\n return `當前內容尚未發布 v${openedVersion.version}`;\n }\n\n return '當前內容尚未發布';\n}\n\nfunction moveItemByIndex<TItem>(\n items: readonly TItem[],\n sourceIndex: number,\n destinationIndex: number,\n): TItem[] {\n const sourceItem = items[sourceIndex];\n\n if (!sourceItem || sourceIndex === destinationIndex) {\n return [...items];\n }\n\n const remainingItems = items.filter((_, index) => index !== sourceIndex);\n\n return [\n ...remainingItems.slice(0, destinationIndex),\n sourceItem,\n ...remainingItems.slice(destinationIndex),\n ];\n}\n\nfunction FormVersionStatusBadge({\n status,\n}: {\n readonly status: FormDefinitionVersionRecord['status'];\n}): ReactElement {\n if (status === 'PUBLISHED') {\n return <Badge size=\"sub\" text=\"已發布\" variant=\"dot-success\" />;\n }\n\n if (status === 'ARCHIVED') {\n return <Badge size=\"sub\" text=\"已封存\" variant=\"dot-inactive\" />;\n }\n\n return <Badge size=\"sub\" text=\"草稿\" variant=\"dot-warning\" />;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAQA,IAAM,KAAuC;CAC3C,YAAY;CACZ,QAAQ;CACR,cAAc;CACd,OAAO;CACP,SAAS;CACT,WAAW;CACX,SAAS;CACT,OAAO;AACT,GAEM,IAA+C;CACnD,EAAK;CACL,EAAW;CACX,EAAW,MAAM;EACf,KAAK;GACH,QAAQ;GACR,cAAc;GACd,UAAU;GACV,OAAO;EACT;EACA,gBAAgB,EACd,SAAS,4CACX;EACA,eAAe;GACb,YACE;GACF,WAAW;EACb;EACA,cAAc,EACZ,OAAO,OACT;EACA,eAAe,EACb,aAAa,4CACf;EACA,gBAAgB,EACd,YACE,wFACJ;CACF,CAAC;AACH,GAEM,KAAa,QACX,OAAO,0BACb;CACE,eACE,kBAAC,OAAD;EAAK,OAAO;YAAuB;CAAgB,CAAA;CAErD,KAAK;AACP,CACF;AAWA,SAAgB,GAAe,EAC7B,aACA,WACA,SACA,aACA,gBACA,YACoC;CACpC,OACE,kBAAC,IAAD;EACE,cAAY;EACZ,YAAY;GACV,gBAAgB;GAChB,iBAAiB;GACjB,eAAe;GACf,eAAe;GACf,YAAY;GACZ,qBAAqB;GACrB,2BAA2B;GAC3B,aAAa;GACb,oBAAoB;EACtB;EACA,UAAU,CAAC;EACX,YAAY,CAAC,GAAG,CAAsB;EAC9B;EACR,eAAe;EACL;EACG;EACb,UAAU;EACV,OAAM;EACC;EACP,OAAM;CACP,CAAA;AAEL;;;AC8CA,IAAM,KAAiD;CACrD;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAAO;EACP,MAAM;CACR;CACA;EACE,aAAa;EACb,MAAM;EACN,OAA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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";require('../categories.css');const e=require("./app-navigation-C_mbz7jx.cjs"),t=require("./format-date-time-isOa3e9q.cjs"),n=require("./bpm-form-field-Bc6k4ZEO.cjs");let r=require("react"),i=require("@mezzanine-ui/react"),a=require("react/jsx-runtime"),o=require("@mezzanine-ui/icons"),s=require("@mezzanine-ui/react/ContentHeader");s=e.o(s,1);let c=require("@mezzanine-ui/core/form"),l=require("@rytass/bpm-core-client/template");var u={templateFilterArea:`bpm_templateFilterArea_nUL-R`,templateModalFields:`bpm_templateModalFields_hUxWp`},d=[10,20,50],f=[{key:`ALL`,label:`全部`},{key:`ACTIVE`,label:`啟用`},{key:`INACTIVE`,label:`停用`}];function p({activeHref:n=`/templates/categories`}={}){let[p,y]=(0,r.useState)([]),[b,x]=(0,r.useState)(1),[S,C]=(0,r.useState)(10),[w,T]=(0,r.useState)(`ALL`),[E,D]=(0,r.useState)(0),[O,k]=(0,r.useState)(null),[A,j]=(0,r.useState)(null),[M,N]=(0,r.useState)(!0),[P,F]=(0,r.useState)(null),[I,L]=(0,r.useState)(!1),[R,z]=(0,r.useState)(``),B=(0,r.useCallback)(async()=>{N(!0),j(null);try{let e=await(0,l.listApprovalTemplateCategoriesPage)({page:b,pageSize:S,searchText:R,status:_(w)});y(e.categories),D(e.totalCount)}catch(e){j(v(e))}finally{N(!1)}},[b,S,w,R]);(0,r.useEffect)(()=>{B()},[B]);let V=(0,r.useMemo)(()=>p.map(e=>({...e,key:e.id,updatedAtLabel:t.t(e.updatedAt)})),[p]),H=(0,r.useMemo)(()=>[{dataIndex:`name`,key:`name`,title:`分類名稱`,width:180},{key:`status`,render:e=>(0,a.jsx)(h,{isActive:e.isActive}),title:`狀態`,width:120},{dataIndex:`sortOrder`,key:`sortOrder`,title:`排序`,width:100},{key:`description`,render:e=>(0,a.jsx)(i.Typography,{component:`span`,variant:`body`,children:e.description||`無`}),title:`說明`,width:260},{dataIndex:`updatedAtLabel`,key:`updatedAtLabel`,title:`更新時間`,width:220}],[]);async function U(e){L(!0),j(null);try{P?.type===`EDIT`&&P.record?await(0,l.updateApprovalTemplateCategory)({...e,id:P.record.id}):await(0,l.createApprovalTemplateCategory)(e),F(null),await B()}catch(e){throw j(v(e)),e}finally{L(!1)}}async function W(e){L(!0),j(null);try{await(0,l.updateApprovalTemplateCategory)({description:e.description,id:e.id,isActive:!e.isActive,name:e.name,sortOrder:e.sortOrder}),await B()}catch(e){j(v(e))}finally{L(!1)}}async function G(){if(O){L(!0),j(null);try{await(0,l.deleteApprovalTemplateCategory)(O.id),k(null),await B()}catch(e){j(v(e))}finally{L(!1)}}}let K=(0,r.useMemo)(()=>({render:e=>[{name:`編輯`,onClick:()=>F({record:e,type:`EDIT`})},{name:e.isActive?`停用`:`啟用`,onClick:()=>void W(e),variant:e.isActive?`destructive-secondary`:`base-secondary`},{name:`刪除`,onClick:()=>k({id:e.id,name:e.name}),variant:`destructive-secondary`}],variant:`base-secondary`,width:192}),[B]);return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(e.t,{activeHref:n,children:[(0,a.jsx)(i.PageHeader,{children:(0,a.jsx)(s.default,{description:`維護簽核模板分類,供模板建立、篩選與列表標示使用。`,title:`簽核模板分類`,children:(0,a.jsx)(i.Button,{icon:o.PlusIcon,iconType:`leading`,onClick:()=>F({record:null,type:`CREATE`}),variant:`base-primary`,children:`建立分類`})})}),(0,a.jsx)(i.SectionGroup,{children:(0,a.jsxs)(i.Section,{filterArea:(0,a.jsx)(i.FilterArea,{className:u.templateFilterArea,size:`sub`,children:(0,a.jsx)(i.FilterLine,{children:(0,a.jsx)(i.Filter,{span:3,children:(0,a.jsx)(i.FormField,{fullWidth:!0,layout:c.FormFieldLayout.VERTICAL,name:`categorySearchText`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{z(e.target.value),x(1)},placeholder:`關鍵字:搜尋分類名稱或說明`,size:`sub`,value:R,variant:`base`})})})})}),tab:(0,a.jsx)(i.Tab,{activeKey:w,onChange:e=>{T(g(e)),x(1)},children:f.map(e=>(0,a.jsx)(i.TabItem,{children:e.label},e.key))}),children:[A?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:A}):null,(0,a.jsx)(i.Table,{actions:K,columns:H,dataSource:V,fullWidth:!0,loading:M||I,pagination:{current:b,onChange:e=>{x(e)},onChangePageSize:e=>{x(1),C(e)},pageSize:S,pageSizeLabel:`每頁筆數`,pageSizeOptions:d,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:E}})]})})]}),(0,a.jsx)(m,{loading:I,modal:P,onClose:()=>F(null),onSubmit:U}),(0,a.jsx)(i.Modal,{cancelText:`取消`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`刪除`,loading:I,modalStatusType:`error`,modalType:`standard`,onCancel:()=>k(null),onClose:()=>k(null),onConfirm:()=>void G(),open:!!O,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`若分類已被模板使用,系統會改為停用分類並保留既有模板關聯。`,title:`刪除分類`,children:(0,a.jsxs)(i.Typography,{color:`text-neutral`,variant:`body`,children:[`確定要刪除「`,O?.name??``,`」嗎?`]})})]})}function m({loading:e,modal:t,onClose:o,onSubmit:s}){let[c,l]=(0,r.useState)(``),[d,f]=(0,r.useState)(null),[p,m]=(0,r.useState)(``),[h,g]=(0,r.useState)(`0`);(0,r.useEffect)(()=>{t&&(l(t.record?.description??``),f(null),m(t.record?.name??``),g(String(t.record?.sortOrder??0)))},[t]);async function _(){let e=p.trim(),n=Number(h);if(!e){f(`請輸入分類名稱`);return}if(!Number.isInteger(n)){f(`排序必須是整數`);return}try{await s({description:c.trim()||null,isActive:t?.record?.isActive??!0,name:e,sortOrder:n})}catch(e){f(v(e))}}return(0,a.jsxs)(i.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!p.trim()},confirmText:t?.type===`EDIT`?`儲存`:`建立`,loading:e,modalType:`standard`,onCancel:o,onClose:o,onConfirm:()=>void _(),open:!!t,showModalFooter:!0,showModalHeader:!0,size:`regular`,title:t?.type===`EDIT`?`編輯分類`:`建立分類`,children:[(0,a.jsxs)(`div`,{className:u.templateModalFields,children:[(0,a.jsx)(n.t,{label:`分類名稱`,name:`categoryName`,required:!0,children:(0,a.jsx)(i.Input,{autoFocus:!0,fullWidth:!0,onChange:e=>{m(e.target.value),f(null)},placeholder:`例如:行政管理`,value:p,variant:`base`})}),(0,a.jsx)(n.t,{label:`排序`,name:`categorySortOrder`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{g(e.target.value),f(null)},placeholder:`0`,value:h,variant:`base`})}),(0,a.jsx)(n.t,{label:`說明`,name:`categoryDescription`,children:(0,a.jsx)(i.Textarea,{onChange:e=>{l(e.target.value),f(null)},placeholder:`補充分類用途`,value:c})})]}),d?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:d}):null]})}function h({isActive:e}){return e?(0,a.jsx)(i.Badge,{size:`sub`,text:`啟用`,variant:`dot-success`}):(0,a.jsx)(i.Badge,{size:`sub`,text:`停用`,variant:`dot-inactive`})}function g(e){return e===`ACTIVE`||e===`INACTIVE`?e:`ALL`}function _(e){return e}function v(e){return e instanceof Error?e.message:`發生未知錯誤`}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return p}});
|
|
2
|
+
//# sourceMappingURL=categories-DEijUOnw.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"categories-DEijUOnw.cjs","names":[],"sources":["../../src/views/templates/templates.module.scss","../../src/views/templates/categories/TemplateCategoriesView.tsx"],"sourcesContent":[".templateFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n\n.templateModalFields {\n display: grid;\n gap: 16px;\n}\n","'use client';\n\nimport type { ChangeEvent, Key, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Tab,\n TabItem,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { PlusIcon } from '@mezzanine-ui/icons';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { AppLayout } from '../../../components/app-navigation';\nimport {\n ApprovalTemplateCategoryRecord,\n ApprovalTemplateCategoryStatus,\n createApprovalTemplateCategory,\n deleteApprovalTemplateCategory,\n listApprovalTemplateCategoriesPage,\n updateApprovalTemplateCategory,\n} from '@rytass/bpm-core-client/template';\nimport styles from '../templates.module.scss';\n\nconst CATEGORY_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst CATEGORY_STATUS_TABS: readonly {\n readonly key: CategoryStatusTabKey;\n readonly label: string;\n}[] = [\n { key: 'ALL', label: '全部' },\n { key: 'ACTIVE', label: '啟用' },\n { key: 'INACTIVE', label: '停用' },\n];\ntype CategoryStatusTabKey = 'ACTIVE' | 'ALL' | 'INACTIVE';\n\ntype CategoryRow = Readonly<\n Record<string, unknown> &\n ApprovalTemplateCategoryRecord & {\n key: string;\n updatedAtLabel: string;\n }\n>;\n\ntype CategoryModalState = Readonly<{\n record: ApprovalTemplateCategoryRecord | null;\n type: 'CREATE' | 'EDIT';\n}>;\n\ntype DeleteConfirmationState = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport interface TemplateCategoriesViewProps {\n readonly activeHref?: string;\n}\n\nexport function TemplateCategoriesView({\n activeHref = '/templates/categories',\n}: TemplateCategoriesViewProps = {}): ReactElement {\n const [categories, setCategories] = useState<\n readonly ApprovalTemplateCategoryRecord[]\n >([]);\n const [categoryPage, setCategoryPage] = useState(1);\n const [categoryPageSize, setCategoryPageSize] = useState(10);\n const [categoryStatus, setCategoryStatus] =\n useState<CategoryStatusTabKey>('ALL');\n const [categoryTotalCount, setCategoryTotalCount] = useState(0);\n const [deleteConfirmation, setDeleteConfirmation] =\n useState<DeleteConfirmationState | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [modalState, setModalState] = useState<CategoryModalState | null>(null);\n const [saving, setSaving] = useState(false);\n const [searchText, setSearchText] = useState('');\n\n const refreshCategories = useCallback(async (): Promise<void> => {\n setLoading(true);\n setError(null);\n\n try {\n const categoryPageResult = await listApprovalTemplateCategoriesPage({\n page: categoryPage,\n pageSize: categoryPageSize,\n searchText,\n status: readCategoryStatus(categoryStatus),\n });\n\n setCategories(categoryPageResult.categories);\n setCategoryTotalCount(categoryPageResult.totalCount);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }, [categoryPage, categoryPageSize, categoryStatus, searchText]);\n\n useEffect((): void => {\n void refreshCategories();\n }, [refreshCategories]);\n\n const rows = useMemo(\n (): CategoryRow[] =>\n categories.map((category) => ({\n ...category,\n key: category.id,\n updatedAtLabel: formatDateTime(category.updatedAt),\n })),\n [categories],\n );\n\n const columns = useMemo(\n (): TableColumn<CategoryRow>[] => [\n { dataIndex: 'name', key: 'name', title: '分類名稱', width: 180 },\n {\n key: 'status',\n render: (record: CategoryRow): ReactElement => (\n <CategoryStatusBadge isActive={record.isActive} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n dataIndex: 'sortOrder',\n key: 'sortOrder',\n title: '排序',\n width: 100,\n },\n {\n key: 'description',\n render: (record: CategoryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.description || '無'}\n </Typography>\n ),\n title: '說明',\n width: 260,\n },\n {\n dataIndex: 'updatedAtLabel',\n key: 'updatedAtLabel',\n title: '更新時間',\n width: 220,\n },\n ],\n [],\n );\n\n async function handleSaveCategory(input: CategoryFormInput): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n if (modalState?.type === 'EDIT' && modalState.record) {\n await updateApprovalTemplateCategory({\n ...input,\n id: modalState.record.id,\n });\n } else {\n await createApprovalTemplateCategory(input);\n }\n\n setModalState(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n throw requestError;\n } finally {\n setSaving(false);\n }\n }\n\n async function handleToggleCategory(\n record: ApprovalTemplateCategoryRecord,\n ): Promise<void> {\n setSaving(true);\n setError(null);\n\n try {\n await updateApprovalTemplateCategory({\n description: record.description,\n id: record.id,\n isActive: !record.isActive,\n name: record.name,\n sortOrder: record.sortOrder,\n });\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n async function handleConfirmDelete(): Promise<void> {\n if (!deleteConfirmation) {\n return;\n }\n\n setSaving(true);\n setError(null);\n\n try {\n await deleteApprovalTemplateCategory(deleteConfirmation.id);\n setDeleteConfirmation(null);\n await refreshCategories();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setSaving(false);\n }\n }\n\n const tableActions = useMemo(\n (): TableActions<CategoryRow> => ({\n render: (record): ReturnType<TableActions<CategoryRow>['render']> => [\n {\n name: '編輯',\n onClick: (): void => setModalState({ record, type: 'EDIT' }),\n },\n {\n name: record.isActive ? '停用' : '啟用',\n onClick: (): void => void handleToggleCategory(record),\n variant: record.isActive ? 'destructive-secondary' : 'base-secondary',\n },\n {\n name: '刪除',\n onClick: (): void =>\n setDeleteConfirmation({ id: record.id, name: record.name }),\n variant: 'destructive-secondary',\n },\n ],\n variant: 'base-secondary',\n width: 192,\n }),\n [refreshCategories],\n );\n\n return (\n <>\n <AppLayout activeHref={activeHref}>\n <PageHeader>\n <ContentHeader\n description=\"維護簽核模板分類,供模板建立、篩選與列表標示使用。\"\n title=\"簽核模板分類\"\n >\n <Button\n icon={PlusIcon}\n iconType=\"leading\"\n onClick={(): void =>\n setModalState({ record: null, type: 'CREATE' })\n }\n variant=\"base-primary\"\n >\n 建立分類\n </Button>\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.templateFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"categorySearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setCategoryPage(1);\n }}\n placeholder=\"關鍵字:搜尋分類名稱或說明\"\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n tab={\n <Tab\n activeKey={categoryStatus}\n onChange={(activeKey): void => {\n setCategoryStatus(readCategoryStatusTabKey(activeKey));\n setCategoryPage(1);\n }}\n >\n {CATEGORY_STATUS_TABS.map((statusTab) => (\n <TabItem key={statusTab.key}>{statusTab.label}</TabItem>\n ))}\n </Tab>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={rows}\n fullWidth\n loading={loading || saving}\n pagination={{\n current: categoryPage,\n onChange: (page): void => {\n setCategoryPage(page);\n },\n onChangePageSize: (pageSize): void => {\n setCategoryPage(1);\n setCategoryPageSize(pageSize);\n },\n pageSize: categoryPageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: CATEGORY_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: categoryTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </AppLayout>\n\n <CategoryModal\n loading={saving}\n modal={modalState}\n onClose={(): void => setModalState(null)}\n onSubmit={handleSaveCategory}\n />\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"刪除\"\n loading={saving}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setDeleteConfirmation(null)}\n onClose={(): void => setDeleteConfirmation(null)}\n onConfirm={(): void => void handleConfirmDelete()}\n open={Boolean(deleteConfirmation)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"若分類已被模板使用,系統會改為停用分類並保留既有模板關聯。\"\n title=\"刪除分類\"\n >\n <Typography color=\"text-neutral\" variant=\"body\">\n 確定要刪除「{deleteConfirmation?.name ?? ''}」嗎?\n </Typography>\n </Modal>\n </>\n );\n}\n\ninterface CategoryFormInput {\n readonly description: string | null;\n readonly isActive: boolean;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nfunction CategoryModal({\n loading,\n modal,\n onClose,\n onSubmit,\n}: {\n readonly loading: boolean;\n readonly modal: CategoryModalState | null;\n readonly onClose: () => void;\n readonly onSubmit: (input: CategoryFormInput) => Promise<void>;\n}): ReactElement {\n const [description, setDescription] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [sortOrder, setSortOrder] = useState('0');\n\n useEffect((): void => {\n if (!modal) {\n return;\n }\n\n setDescription(modal.record?.description ?? '');\n setError(null);\n setName(modal.record?.name ?? '');\n setSortOrder(String(modal.record?.sortOrder ?? 0));\n }, [modal]);\n\n async function handleConfirm(): Promise<void> {\n const trimmedName = name.trim();\n const parsedSortOrder = Number(sortOrder);\n\n if (!trimmedName) {\n setError('請輸入分類名稱');\n return;\n }\n\n if (!Number.isInteger(parsedSortOrder)) {\n setError('排序必須是整數');\n return;\n }\n\n try {\n await onSubmit({\n description: description.trim() || null,\n isActive: modal?.record?.isActive ?? true,\n name: trimmedName,\n sortOrder: parsedSortOrder,\n });\n } catch (submitError: unknown) {\n setError(readErrorMessage(submitError));\n }\n }\n\n return (\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{ disabled: !name.trim() }}\n confirmText={modal?.type === 'EDIT' ? '儲存' : '建立'}\n loading={loading}\n modalType=\"standard\"\n onCancel={onClose}\n onClose={onClose}\n onConfirm={(): void => void handleConfirm()}\n open={Boolean(modal)}\n showModalFooter\n showModalHeader\n size=\"regular\"\n title={modal?.type === 'EDIT' ? '編輯分類' : '建立分類'}\n >\n <div className={styles.templateModalFields}>\n <BPMFormField label=\"分類名稱\" name=\"categoryName\" required>\n <Input\n autoFocus\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setName(event.target.value);\n setError(null);\n }}\n placeholder=\"例如:行政管理\"\n value={name}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"排序\" name=\"categorySortOrder\">\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void => {\n setSortOrder(event.target.value);\n setError(null);\n }}\n placeholder=\"0\"\n value={sortOrder}\n variant=\"base\"\n />\n </BPMFormField>\n <BPMFormField label=\"說明\" name=\"categoryDescription\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setDescription(event.target.value);\n setError(null);\n }}\n placeholder=\"補充分類用途\"\n value={description}\n />\n </BPMFormField>\n </div>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n </Modal>\n );\n}\n\nfunction CategoryStatusBadge({\n isActive,\n}: {\n readonly isActive: boolean;\n}): ReactElement {\n return isActive ? (\n <Badge size=\"sub\" text=\"啟用\" variant=\"dot-success\" />\n ) : (\n <Badge size=\"sub\" text=\"停用\" variant=\"dot-inactive\" />\n );\n}\n\nfunction readCategoryStatusTabKey(activeKey: Key): CategoryStatusTabKey {\n if (activeKey === 'ACTIVE' || activeKey === 'INACTIVE') {\n return activeKey;\n }\n\n return 'ALL';\n}\n\nfunction readCategoryStatus(\n status: CategoryStatusTabKey,\n): ApprovalTemplateCategoryStatus {\n return status;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n"],"mappings":"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"}
|