@rytass/bpm-core-react 0.17.0 → 0.17.2
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/CHANGELOG.md +24 -0
- package/dist/chunks/admin-pickers-BRHk3qKq.cjs +2 -0
- package/dist/chunks/admin-pickers-BRHk3qKq.cjs.map +1 -0
- package/dist/chunks/{admin-pickers-DxhzECkD.js → admin-pickers-Djq3h-UR.js} +41 -39
- package/dist/chunks/admin-pickers-Djq3h-UR.js.map +1 -0
- package/dist/chunks/{categories-DjENouRm.cjs → categories-AxxhqjLZ.cjs} +2 -2
- package/dist/chunks/{categories-DjENouRm.cjs.map → categories-AxxhqjLZ.cjs.map} +1 -1
- package/dist/chunks/{categories-1gKxeEqw.js → categories-riC33J_j.js} +2 -2
- package/dist/chunks/{categories-1gKxeEqw.js.map → categories-riC33J_j.js.map} +1 -1
- package/dist/chunks/{compose-DZ7RKvUp.cjs → compose-B7TtrpQJ.cjs} +2 -2
- package/dist/chunks/{compose-DZ7RKvUp.cjs.map → compose-B7TtrpQJ.cjs.map} +1 -1
- package/dist/chunks/{compose-Crklayzy.js → compose-_pREPtfN.js} +2 -2
- package/dist/chunks/{compose-Crklayzy.js.map → compose-_pREPtfN.js.map} +1 -1
- package/dist/chunks/{designer-D9eFma1W.js → designer-BiywgNXs.js} +2 -2
- package/dist/chunks/{designer-D9eFma1W.js.map → designer-BiywgNXs.js.map} +1 -1
- package/dist/chunks/{designer-sJGTGYOf.cjs → designer-ttAqv859.cjs} +2 -2
- package/dist/chunks/{designer-sJGTGYOf.cjs.map → designer-ttAqv859.cjs.map} +1 -1
- package/dist/chunks/{orgs-Dr0FFoZo.cjs → orgs-C8usknWb.cjs} +2 -2
- package/dist/chunks/{orgs-Dr0FFoZo.cjs.map → orgs-C8usknWb.cjs.map} +1 -1
- package/dist/chunks/{orgs-CY0i1fie.js → orgs-Lg7tXv2u.js} +2 -2
- package/dist/chunks/{orgs-CY0i1fie.js.map → orgs-Lg7tXv2u.js.map} +1 -1
- package/dist/chunks/{users-BCyePbwB.js → users-DRbuDYF1.js} +2 -2
- package/dist/chunks/{users-BCyePbwB.js.map → users-DRbuDYF1.js.map} +1 -1
- package/dist/chunks/{users-DVBJluFR.cjs → users-DVQicZIo.cjs} +2 -2
- package/dist/chunks/{users-DVBJluFR.cjs.map → users-DVQicZIo.cjs.map} +1 -1
- package/dist/components/admin-pickers.d.cts +65 -0
- package/dist/components/approval-instance-list-page.d.cts +17 -0
- package/dist/components/bpm-form-field.d.cts +10 -0
- package/dist/components/bpm-notification-bell-button.d.cts +22 -0
- package/dist/components/dashboard-page.d.cts +7 -0
- package/dist/components/notification-drawer.d.cts +11 -0
- package/dist/components/org-unit-tree-draft-editor.d.cts +24 -0
- package/dist/components/org-unit-tree-draft-editor.d.ts +1 -1
- package/dist/components/pdf-preview.d.cts +12 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -15
- package/dist/index.js +1 -1
- package/dist/lib/auth-provider.d.cts +37 -0
- package/dist/lib/format-date-time.d.cts +5 -0
- package/dist/lib/format-member-label.d.cts +12 -0
- package/dist/lib/member-profile-resolution.d.cts +48 -0
- package/dist/lib/notification-drawer-provider.d.cts +27 -0
- package/dist/lib/notification-unread-provider.d.cts +25 -0
- package/dist/lib/org-tree-draft.d.cts +27 -0
- package/dist/lib/providers.d.cts +31 -0
- package/dist/lib/router-adapter.d.cts +47 -0
- package/dist/lib/routes-config.d.cts +117 -0
- package/dist/lib/task-node-label.d.cts +10 -0
- package/dist/lib/use-bpm-logout.d.cts +12 -0
- package/dist/lib/use-bpm-member.d.cts +17 -0
- package/dist/next/BPMNextProviders.d.cts +51 -0
- package/dist/next/index.d.cts +2 -0
- package/dist/next/index.d.ts +2 -2
- package/dist/next/workflow-chat-route.d.cts +17 -0
- package/dist/pages/admin/delegations/index.d.cts +4 -0
- package/dist/pages/admin/orgs/index.cjs +1 -1
- package/dist/pages/admin/orgs/index.d.cts +4 -0
- package/dist/pages/admin/orgs/index.js +1 -1
- package/dist/pages/admin/users/index.cjs +1 -1
- package/dist/pages/admin/users/index.d.cts +4 -0
- package/dist/pages/admin/users/index.js +1 -1
- package/dist/pages/admin/webhook-endpoints/index.d.cts +4 -0
- package/dist/pages/cc/index.d.cts +16 -0
- package/dist/pages/dashboard/index.d.cts +16 -0
- package/dist/pages/delegations/index.d.cts +4 -0
- package/dist/pages/inbox/index.d.cts +16 -0
- package/dist/pages/instances/detail/index.d.cts +23 -0
- package/dist/pages/instances/new/index.d.cts +20 -0
- package/dist/pages/login/index.d.cts +21 -0
- package/dist/pages/root/index.d.cts +18 -0
- package/dist/pages/search/index.d.cts +16 -0
- package/dist/pages/sent/index.d.cts +16 -0
- package/dist/pages/settings/notifications/index.d.cts +4 -0
- package/dist/pages/templates/categories/index.cjs +1 -1
- package/dist/pages/templates/categories/index.d.cts +4 -0
- package/dist/pages/templates/categories/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +1 -1
- package/dist/pages/templates/compose/index.d.cts +25 -0
- package/dist/pages/templates/compose/index.js +1 -1
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.d.cts +8 -0
- package/dist/pages/templates/designer/index.js +1 -1
- package/dist/pages/templates/index.d.cts +4 -0
- package/dist/pages/templates/versions/index.d.cts +8 -0
- package/dist/views/admin/delegations/AdminDelegationsView.d.cts +2 -0
- package/dist/views/admin/delegations/index.d.cts +1 -0
- package/dist/views/admin/delegations/index.d.ts +1 -1
- package/dist/views/admin/index.cjs +1 -1
- package/dist/views/admin/index.d.cts +4 -0
- package/dist/views/admin/index.d.ts +4 -4
- package/dist/views/admin/index.js +2 -2
- package/dist/views/admin/orgs/AdminOrgsView.d.cts +2 -0
- package/dist/views/admin/orgs/index.cjs +1 -1
- package/dist/views/admin/orgs/index.d.cts +1 -0
- package/dist/views/admin/orgs/index.d.ts +1 -1
- package/dist/views/admin/orgs/index.js +1 -1
- package/dist/views/admin/users/AdminUsersView.d.cts +2 -0
- package/dist/views/admin/users/MemberTaskReassignModal.d.cts +13 -0
- package/dist/views/admin/users/index.cjs +1 -1
- package/dist/views/admin/users/index.d.cts +1 -0
- package/dist/views/admin/users/index.d.ts +1 -1
- package/dist/views/admin/users/index.js +1 -1
- package/dist/views/admin/webhook-endpoints/AdminWebhookEndpointsView.d.cts +8 -0
- package/dist/views/admin/webhook-endpoints/index.d.cts +1 -0
- package/dist/views/admin/webhook-endpoints/index.d.ts +1 -1
- package/dist/views/cc/CcView.d.cts +7 -0
- package/dist/views/cc/index.d.cts +1 -0
- package/dist/views/cc/index.d.ts +1 -1
- package/dist/views/dashboard/DashboardView.d.cts +7 -0
- package/dist/views/dashboard/index.d.cts +1 -0
- package/dist/views/dashboard/index.d.ts +1 -1
- package/dist/views/delegations/DelegationsView.d.cts +2 -0
- package/dist/views/delegations/index.d.cts +1 -0
- package/dist/views/delegations/index.d.ts +1 -1
- package/dist/views/forms/builder/FormBuilderView.d.cts +18 -0
- package/dist/views/forms/builder/index.d.cts +1 -0
- package/dist/views/forms/builder/index.d.ts +1 -1
- package/dist/views/forms/builder/json-code-editor.d.cts +11 -0
- package/dist/views/forms/renderer/FormRendererView.d.cts +24 -0
- package/dist/views/forms/renderer/FormRendererView.d.ts +1 -1
- package/dist/views/forms/renderer/form-data-source-field.d.cts +65 -0
- package/dist/views/forms/renderer/form-field-link.d.cts +16 -0
- package/dist/views/forms/renderer/index.d.cts +2 -0
- package/dist/views/forms/renderer/index.d.ts +2 -2
- package/dist/views/forms/renderer/member-field-options.d.cts +39 -0
- package/dist/views/forms/renderer/member-field.d.cts +21 -0
- package/dist/views/inbox/InboxView.d.cts +7 -0
- package/dist/views/inbox/index.d.cts +1 -0
- package/dist/views/inbox/index.d.ts +1 -1
- package/dist/views/instances/detail/InstanceDetailView.d.cts +27 -0
- package/dist/views/instances/detail/index.d.cts +7 -0
- package/dist/views/instances/detail/index.d.ts +7 -7
- package/dist/views/instances/detail/sections/InstanceAttachmentsSection.d.cts +15 -0
- package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +36 -0
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +1 -1
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.cts +29 -0
- package/dist/views/instances/detail/sections/InstanceSignaturesSection.d.cts +14 -0
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +55 -0
- package/dist/views/instances/detail/sections/InstanceWebhookDeliveriesSection.d.cts +20 -0
- package/dist/views/instances/detail/sections/container-helpers.d.cts +10 -0
- package/dist/views/instances/detail/sections/container-helpers.d.ts +1 -1
- package/dist/views/instances/detail/sections/shared.d.cts +141 -0
- package/dist/views/instances/detail/submitted-by.d.cts +23 -0
- package/dist/views/instances/index.d.cts +1 -0
- package/dist/views/instances/index.d.ts +1 -1
- package/dist/views/instances/new/InstanceNewView.d.cts +15 -0
- package/dist/views/instances/new/index.d.cts +1 -0
- package/dist/views/instances/new/index.d.ts +1 -1
- package/dist/views/login/LoginView.d.cts +47 -0
- package/dist/views/login/index.d.cts +1 -0
- package/dist/views/login/index.d.ts +1 -1
- package/dist/views/root/RootView.d.cts +10 -0
- package/dist/views/root/index.d.cts +1 -0
- package/dist/views/root/index.d.ts +1 -1
- package/dist/views/search/SearchView.d.cts +7 -0
- package/dist/views/search/index.d.cts +1 -0
- package/dist/views/search/index.d.ts +1 -1
- package/dist/views/sent/SentView.d.cts +7 -0
- package/dist/views/sent/index.d.cts +1 -0
- package/dist/views/sent/index.d.ts +1 -1
- package/dist/views/settings/index.d.cts +1 -0
- package/dist/views/settings/index.d.ts +1 -1
- package/dist/views/settings/notifications/SettingsNotificationsView.d.cts +2 -0
- package/dist/views/settings/notifications/index.d.cts +1 -0
- package/dist/views/settings/notifications/index.d.ts +1 -1
- package/dist/views/templates/TemplatesView.d.cts +7 -0
- package/dist/views/templates/categories/TemplateCategoriesView.d.cts +2 -0
- package/dist/views/templates/categories/index.cjs +1 -1
- package/dist/views/templates/categories/index.d.cts +1 -0
- package/dist/views/templates/categories/index.d.ts +1 -1
- package/dist/views/templates/categories/index.js +1 -1
- package/dist/views/templates/compose/TemplateComposeWizardView.d.cts +21 -0
- package/dist/views/templates/compose/index.cjs +1 -1
- package/dist/views/templates/compose/index.d.cts +2 -0
- package/dist/views/templates/compose/index.d.ts +2 -2
- package/dist/views/templates/compose/index.js +1 -1
- package/dist/views/templates/compose/steps/ComposeFormStep.d.cts +15 -0
- package/dist/views/templates/compose/steps/ComposeReviewStep.d.cts +12 -0
- package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.cts +22 -0
- package/dist/views/templates/compose/use-template-compose-wizard.d.cts +46 -0
- package/dist/views/templates/designer/NotifyWebhookTargetsEditor.d.cts +20 -0
- package/dist/views/templates/designer/NotifyWebhookTargetsEditor.d.ts +1 -1
- package/dist/views/templates/designer/TemplateDesignerView.d.cts +65 -0
- package/dist/views/templates/designer/chrome-workflow-chat.d.cts +12 -0
- package/dist/views/templates/designer/chrome-workflow-chat.d.ts +1 -1
- package/dist/views/templates/designer/decision-policy-options.d.cts +8 -0
- package/dist/views/templates/designer/designer-version-labels.d.cts +12 -0
- package/dist/views/templates/designer/dry-run-assignee-label.d.cts +28 -0
- package/dist/views/templates/designer/dry-run-sample-data.d.cts +9 -0
- package/dist/views/templates/designer/dynamic-form-resolver-options.d.cts +35 -0
- package/dist/views/templates/designer/index.cjs +1 -1
- package/dist/views/templates/designer/index.d.cts +1 -0
- package/dist/views/templates/designer/index.d.ts +1 -1
- package/dist/views/templates/designer/index.js +1 -1
- package/dist/views/templates/designer/notify-webhook-designer.d.cts +74 -0
- package/dist/views/templates/designer/position-level-options.d.cts +17 -0
- package/dist/views/templates/designer/use-workflow-chat.d.cts +21 -0
- package/dist/views/templates/designer/use-workflow-chat.d.ts +1 -1
- package/dist/views/templates/designer/use-workflow-designer-controller.d.cts +41 -0
- package/dist/views/templates/designer/workflow-chat-drawer.d.cts +16 -0
- package/dist/views/templates/designer/workflow-chat-drawer.d.ts +1 -1
- package/dist/views/templates/index.cjs +1 -1
- package/dist/views/templates/index.d.cts +3 -0
- package/dist/views/templates/index.d.ts +3 -3
- package/dist/views/templates/index.js +1 -1
- package/dist/views/templates/versions/TemplateVersionsView.d.cts +5 -0
- package/dist/views/templates/versions/index.d.cts +1 -0
- package/dist/views/templates/versions/index.d.ts +1 -1
- package/dist/views/workflow/index.d.cts +4 -0
- package/dist/views/workflow/index.d.ts +4 -4
- package/package.json +387 -147
- package/dist/chunks/admin-pickers-DxhzECkD.js.map +0 -1
- package/dist/chunks/admin-pickers-qe3j--gX.cjs +0 -2
- package/dist/chunks/admin-pickers-qe3j--gX.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 0.17.2 (2026-10-18)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **client:** add notification sync wrappers ([c89d759](https://github.com/Rytass/BPMCore/commit/c89d759))
|
|
6
|
+
- **notification:** page and sync notifications without rescanning ([f03f981](https://github.com/Rytass/BPMCore/commit/f03f981))
|
|
7
|
+
|
|
8
|
+
### ❤️ Thank You
|
|
9
|
+
|
|
10
|
+
- Chia Yu Pai @fantasywind
|
|
11
|
+
|
|
12
|
+
## 0.17.1 (2026-10-16)
|
|
13
|
+
|
|
14
|
+
### 🩹 Fixes
|
|
15
|
+
|
|
16
|
+
- **react:** give the require condition CommonJS declarations ([ab0121b](https://github.com/Rytass/BPMCore/commit/ab0121b))
|
|
17
|
+
- **template:** say a category in use cannot be deleted ([ab4236b](https://github.com/Rytass/BPMCore/commit/ab4236b))
|
|
18
|
+
- **react:** keep org unit and position picker menus on screen ([bb5cbaa](https://github.com/Rytass/BPMCore/commit/bb5cbaa))
|
|
19
|
+
- **react:** fully specify relative imports in emitted declarations ([022b3e2](https://github.com/Rytass/BPMCore/commit/022b3e2))
|
|
20
|
+
|
|
21
|
+
### ❤️ Thank You
|
|
22
|
+
|
|
23
|
+
- Chia Yu Pai @fantasywind
|
|
24
|
+
|
|
1
25
|
## 0.17.0 (2026-10-15)
|
|
2
26
|
|
|
3
27
|
### 🚀 Features
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";require('../admin-pickers.css');const e=require("./format-member-label-t7ANTF62.cjs");let t=require("react"),n=require("@mezzanine-ui/react"),r=require("@rytass/bpm-core-client"),i=require("react/jsx-runtime");var a={pickerHost:`bpm_pickerHost_Sw6gz`},o=320;function s({disabled:e=!1,name:o,onChange:s,placeholder:c=`搜尋姓名或信箱`,size:l,value:d}){let[f,m]=(0,t.useState)(!1),[h,v]=(0,t.useState)(d?[d]:[]);async function y(e){m(!0);try{v((await(0,r.searchMembers)(e)).map(u))}finally{m(!1)}}return(0,i.jsx)(`div`,{className:a.pickerHost,children:(0,i.jsx)(n.AutoComplete,{asyncData:!0,disabled:e,disabledOptionsFilter:!0,emptyText:`沒有符合的會員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:o,spellCheck:!1},loading:f,loadingText:`搜尋會員中...`,mode:`single`,onChange:e=>s(p(e)),onSearch:y,onSearchTextChange:e=>s(g(e,h)),onVisibilityChange:e=>{e&&y(``)},options:[..._(d?[d]:[],h)],placeholder:c,searchDebounceTime:300,size:l,value:d})})}function c({disabled:e=!1,onChange:r,orgUnits:s,placeholder:c=`選擇組織`,size:l,value:u}){let f=(0,t.useMemo)(()=>s.map(d),[s]);return(0,i.jsx)(`div`,{className:a.pickerHost,children:(0,i.jsx)(n.Select,{clearable:!0,disabled:e,flip:!0,fullWidth:!0,menuMaxHeight:o,onChange:e=>r(m(e)),options:[...f],placeholder:c,size:l,value:u})})}function l({disabled:e=!1,onChange:r,placeholder:s=`選擇職位`,positions:c,size:l,value:u}){let d=(0,t.useMemo)(()=>c.map(f),[c]);return(0,i.jsx)(`div`,{className:a.pickerHost,children:(0,i.jsx)(n.Select,{clearable:!0,disabled:e,flip:!0,fullWidth:!0,menuMaxHeight:o,onChange:e=>r(h(e)),options:[...d],placeholder:s,size:l,value:u})})}function u(t){return{email:t.email,id:t.memberId,name:e.t(t.name,t.email,`dot`)}}function d(e){return{id:e.id,name:`${e.name} · ${e.code}`}}function f(e){return{id:e.id,name:`${e.name} · ${e.code}`}}function p(e){if(!v(e))return null;let t=e.email,n=e.id,r=e.name;return typeof t==`string`&&typeof n==`string`&&typeof r==`string`?{email:t,id:n,name:r}:null}function m(e){if(!v(e))return null;let t=e.id,n=e.name;return typeof t==`string`&&typeof n==`string`?{id:t,name:n}:null}function h(e){if(!v(e))return null;let t=e.id,n=e.name;return typeof t==`string`&&typeof n==`string`?{id:t,name:n}:null}function g(e,t){let n=e.trim().toLocaleLowerCase();if(!n)return null;let r=t.filter(e=>e.id.toLocaleLowerCase()===n||e.email.toLocaleLowerCase()===n||e.name.toLocaleLowerCase()===n);return r.length===1?r[0]:null}function _(e,t){return[...new Map([...e,...t].map(e=>[e.id,e])).values()]}function v(e){return typeof e==`object`&&!!e}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return s}});
|
|
2
|
+
//# sourceMappingURL=admin-pickers-BRHk3qKq.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-pickers-BRHk3qKq.cjs","names":["useState","searchMembers","styles","AutoComplete","useMemo","Select","formatMemberLabel","require_format_member_label","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","admin_pickers_module_default","PICKER_MENU_MAX_HEIGHT","MemberPicker","loading","setLoading","options","setOptions","value","handleSearch","searchText","readMemberOption","onChange","readMemberOptionFromValue","option","readUniqueOption","open","mergeMemberOptions","OrgUnitPicker","orgUnits","readOrgUnitOption","readOrgUnitOptionFromValue","PositionPicker","positions","readPositionOption","readPositionOptionFromValue","member","orgUnit","position","isRecord","email","id","name","normalized","matched","selected"],"sources":["../../src/components/admin-pickers.module.scss","../../src/components/admin-pickers.tsx"],"sourcesContent":[".pickerHost {\n width: 100%;\n min-width: 0;\n\n :global(.mzn-auto-complete),\n :global(.mzn-input),\n :global(.mzn-input-container),\n :global(.mzn-select),\n :global(.mzn-select-trigger),\n :global(.mzn-text-field) {\n width: 100%;\n min-width: 0 !important;\n }\n}\n","'use client';\n\nimport { useMemo, useState, type ReactElement } from 'react';\nimport { AutoComplete, Select } from '@mezzanine-ui/react';\nimport { searchMembers } from '@rytass/bpm-core-client';\nimport type {\n OrgUnitRecord,\n PositionRecord,\n} from '@rytass/bpm-core-client/organization';\nimport { formatMemberLabel } from '../lib/format-member-label';\nimport styles from './admin-pickers.module.scss';\n\nexport type MemberOption = Readonly<{\n email: string;\n id: string;\n name: string;\n}>;\n\nexport type OrgUnitOption = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport type PositionOption = Readonly<{\n id: string;\n name: string;\n}>;\n\n// Without a cap the Mezzanine dropdown grows with its options and never\n// mounts its scrollbar, so a long org-unit or position list runs off the\n// viewport with no way to reach the items below the fold. The pickers also\n// set `flip`: near the bottom of a modal the capped menu still overflows\n// unless it may open upwards.\nconst PICKER_MENU_MAX_HEIGHT = 320;\n\ninterface MemberPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: MemberOption | null) => void;\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: MemberOption | null;\n}\n\ninterface OrgUnitPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: OrgUnitOption | null) => void;\n readonly orgUnits: readonly OrgUnitRecord[];\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: OrgUnitOption | null;\n}\n\ninterface PositionPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: PositionOption | null) => void;\n readonly placeholder?: string;\n readonly positions: readonly PositionRecord[];\n readonly size?: 'main' | 'sub';\n readonly value: PositionOption | null;\n}\n\n/**\n * AutoComplete-backed picker that searches the BPM member directory via\n * `searchMembers()`. Emits a {@link MemberOption} `{ id, name, email }`\n * on selection (or `null` when cleared).\n */\nexport function MemberPicker({\n disabled = false,\n name,\n onChange,\n placeholder = '搜尋姓名或信箱',\n size,\n value,\n}: MemberPickerProps): ReactElement {\n const [loading, setLoading] = useState(false);\n const [options, setOptions] = useState<readonly MemberOption[]>(\n value ? [value] : [],\n );\n\n async function handleSearch(searchText: string): Promise<void> {\n setLoading(true);\n try {\n setOptions((await searchMembers(searchText)).map(readMemberOption));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className={styles.pickerHost}>\n <AutoComplete\n asyncData\n disabled={disabled}\n disabledOptionsFilter\n emptyText=\"沒有符合的會員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name,\n spellCheck: false,\n }}\n loading={loading}\n loadingText=\"搜尋會員中...\"\n mode=\"single\"\n onChange={(option): void => onChange(readMemberOptionFromValue(option))}\n onSearch={handleSearch}\n onSearchTextChange={(searchText): void =>\n onChange(readUniqueOption(searchText, options))\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearch('');\n }\n }}\n options={[...mergeMemberOptions(value ? [value] : [], options)]}\n placeholder={placeholder}\n searchDebounceTime={300}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of org units. Caller is\n * responsible for fetching the org units (typically via\n * `readOrganizationDashboard` from `@rytass/bpm-core-client/organization`).\n */\nexport function OrgUnitPicker({\n disabled = false,\n onChange,\n orgUnits,\n placeholder = '選擇組織',\n size,\n value,\n}: OrgUnitPickerProps): ReactElement {\n const options = useMemo(\n (): readonly OrgUnitOption[] => orgUnits.map(readOrgUnitOption),\n [orgUnits],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readOrgUnitOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of positions.\n */\nexport function PositionPicker({\n disabled = false,\n onChange,\n placeholder = '選擇職位',\n positions,\n size,\n value,\n}: PositionPickerProps): ReactElement {\n const options = useMemo(\n (): readonly PositionOption[] => positions.map(readPositionOption),\n [positions],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readPositionOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\nexport function readMemberOption(member: {\n readonly email: string;\n readonly memberId: string;\n readonly name: string;\n}): MemberOption {\n return {\n email: member.email,\n id: member.memberId,\n name: formatMemberLabel(member.name, member.email, 'dot'),\n };\n}\n\nexport function readOrgUnitOption(orgUnit: OrgUnitRecord): OrgUnitOption {\n return { id: orgUnit.id, name: `${orgUnit.name} · ${orgUnit.code}` };\n}\n\nexport function readPositionOption(position: PositionRecord): PositionOption {\n return { id: position.id, name: `${position.name} · ${position.code}` };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) return null;\n const email = value.email;\n const id = value.id;\n const name = value.name;\n return typeof email === 'string' &&\n typeof id === 'string' &&\n typeof name === 'string'\n ? { email, id, name }\n : null;\n}\n\nfunction readOrgUnitOptionFromValue(value: unknown): OrgUnitOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readPositionOptionFromValue(value: unknown): PositionOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readUniqueOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalized = searchText.trim().toLocaleLowerCase();\n if (!normalized) return null;\n const matched = options.filter(\n (option) =>\n option.id.toLocaleLowerCase() === normalized ||\n option.email.toLocaleLowerCase() === normalized ||\n option.name.toLocaleLowerCase() === normalized,\n );\n return matched.length === 1 ? matched[0] : null;\n}\n\nfunction mergeMemberOptions(\n selected: readonly MemberOption[],\n options: readonly MemberOption[],\n): readonly MemberOption[] {\n const byId = new Map(\n [...selected, ...options].map(\n (option): readonly [string, MemberOption] => [option.id, option],\n ),\n );\n return [...byId.values()];\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
|
|
@@ -4,15 +4,13 @@ import { useMemo as t, useState as n } from "react";
|
|
|
4
4
|
import { AutoComplete as r, Select as i } from "@mezzanine-ui/react";
|
|
5
5
|
import { searchMembers as a } from "@rytass/bpm-core-client";
|
|
6
6
|
import { jsx as o } from "react/jsx-runtime";
|
|
7
|
-
import '../admin-pickers.css';var s = { pickerHost: "bpm_pickerHost_Sw6gz" };
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function
|
|
11
|
-
let [f, p] = n(!1), [h, g] = n(u ? [u] : []);
|
|
12
|
-
async function y(e) {
|
|
7
|
+
import '../admin-pickers.css';var s = { pickerHost: "bpm_pickerHost_Sw6gz" }, c = 320;
|
|
8
|
+
function l({ disabled: e = !1, name: t, onChange: i, placeholder: c = "搜尋姓名或信箱", size: l, value: u }) {
|
|
9
|
+
let [d, p] = n(!1), [m, g] = n(u ? [u] : []);
|
|
10
|
+
async function _(e) {
|
|
13
11
|
p(!0);
|
|
14
12
|
try {
|
|
15
|
-
g((await a(e)).map(
|
|
13
|
+
g((await a(e)).map(f));
|
|
16
14
|
} finally {
|
|
17
15
|
p(!1);
|
|
18
16
|
}
|
|
@@ -30,16 +28,16 @@ function c({ disabled: e = !1, name: t, onChange: i, placeholder: c = "搜尋姓
|
|
|
30
28
|
name: t,
|
|
31
29
|
spellCheck: !1
|
|
32
30
|
},
|
|
33
|
-
loading:
|
|
31
|
+
loading: d,
|
|
34
32
|
loadingText: "搜尋會員中...",
|
|
35
33
|
mode: "single",
|
|
36
|
-
onChange: (e) => i(
|
|
37
|
-
onSearch:
|
|
38
|
-
onSearchTextChange: (e) => i(
|
|
34
|
+
onChange: (e) => i(h(e)),
|
|
35
|
+
onSearch: _,
|
|
36
|
+
onSearchTextChange: (e) => i(v(e, m)),
|
|
39
37
|
onVisibilityChange: (e) => {
|
|
40
|
-
e &&
|
|
38
|
+
e && _("");
|
|
41
39
|
},
|
|
42
|
-
options: [...
|
|
40
|
+
options: [...y(u ? [u] : [], m)],
|
|
43
41
|
placeholder: c,
|
|
44
42
|
searchDebounceTime: 300,
|
|
45
43
|
size: l,
|
|
@@ -47,59 +45,63 @@ function c({ disabled: e = !1, name: t, onChange: i, placeholder: c = "搜尋姓
|
|
|
47
45
|
})
|
|
48
46
|
});
|
|
49
47
|
}
|
|
50
|
-
function
|
|
51
|
-
let
|
|
48
|
+
function u({ disabled: e = !1, onChange: n, orgUnits: r, placeholder: a = "選擇組織", size: l, value: u }) {
|
|
49
|
+
let d = t(() => r.map(p), [r]);
|
|
52
50
|
return /* @__PURE__ */ o("div", {
|
|
53
51
|
className: s.pickerHost,
|
|
54
52
|
children: /* @__PURE__ */ o(i, {
|
|
55
53
|
clearable: !0,
|
|
56
54
|
disabled: e,
|
|
55
|
+
flip: !0,
|
|
57
56
|
fullWidth: !0,
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
menuMaxHeight: c,
|
|
58
|
+
onChange: (e) => n(g(e)),
|
|
59
|
+
options: [...d],
|
|
60
60
|
placeholder: a,
|
|
61
|
-
size:
|
|
62
|
-
value:
|
|
61
|
+
size: l,
|
|
62
|
+
value: u
|
|
63
63
|
})
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
|
-
function
|
|
67
|
-
let
|
|
66
|
+
function d({ disabled: e = !1, onChange: n, placeholder: r = "選擇職位", positions: a, size: l, value: u }) {
|
|
67
|
+
let d = t(() => a.map(m), [a]);
|
|
68
68
|
return /* @__PURE__ */ o("div", {
|
|
69
69
|
className: s.pickerHost,
|
|
70
70
|
children: /* @__PURE__ */ o(i, {
|
|
71
71
|
clearable: !0,
|
|
72
72
|
disabled: e,
|
|
73
|
+
flip: !0,
|
|
73
74
|
fullWidth: !0,
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
menuMaxHeight: c,
|
|
76
|
+
onChange: (e) => n(_(e)),
|
|
77
|
+
options: [...d],
|
|
76
78
|
placeholder: r,
|
|
77
|
-
size:
|
|
78
|
-
value:
|
|
79
|
+
size: l,
|
|
80
|
+
value: u
|
|
79
81
|
})
|
|
80
82
|
});
|
|
81
83
|
}
|
|
82
|
-
function
|
|
84
|
+
function f(t) {
|
|
83
85
|
return {
|
|
84
86
|
email: t.email,
|
|
85
87
|
id: t.memberId,
|
|
86
88
|
name: e(t.name, t.email, "dot")
|
|
87
89
|
};
|
|
88
90
|
}
|
|
89
|
-
function
|
|
91
|
+
function p(e) {
|
|
90
92
|
return {
|
|
91
93
|
id: e.id,
|
|
92
94
|
name: `${e.name} · ${e.code}`
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
|
-
function
|
|
97
|
+
function m(e) {
|
|
96
98
|
return {
|
|
97
99
|
id: e.id,
|
|
98
100
|
name: `${e.name} · ${e.code}`
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
|
-
function
|
|
102
|
-
if (!
|
|
103
|
+
function h(e) {
|
|
104
|
+
if (!b(e)) return null;
|
|
103
105
|
let t = e.email, n = e.id, r = e.name;
|
|
104
106
|
return typeof t == "string" && typeof n == "string" && typeof r == "string" ? {
|
|
105
107
|
email: t,
|
|
@@ -107,35 +109,35 @@ function m(e) {
|
|
|
107
109
|
name: r
|
|
108
110
|
} : null;
|
|
109
111
|
}
|
|
110
|
-
function
|
|
111
|
-
if (!
|
|
112
|
+
function g(e) {
|
|
113
|
+
if (!b(e)) return null;
|
|
112
114
|
let t = e.id, n = e.name;
|
|
113
115
|
return typeof t == "string" && typeof n == "string" ? {
|
|
114
116
|
id: t,
|
|
115
117
|
name: n
|
|
116
118
|
} : null;
|
|
117
119
|
}
|
|
118
|
-
function
|
|
119
|
-
if (!
|
|
120
|
+
function _(e) {
|
|
121
|
+
if (!b(e)) return null;
|
|
120
122
|
let t = e.id, n = e.name;
|
|
121
123
|
return typeof t == "string" && typeof n == "string" ? {
|
|
122
124
|
id: t,
|
|
123
125
|
name: n
|
|
124
126
|
} : null;
|
|
125
127
|
}
|
|
126
|
-
function
|
|
128
|
+
function v(e, t) {
|
|
127
129
|
let n = e.trim().toLocaleLowerCase();
|
|
128
130
|
if (!n) return null;
|
|
129
131
|
let r = t.filter((e) => e.id.toLocaleLowerCase() === n || e.email.toLocaleLowerCase() === n || e.name.toLocaleLowerCase() === n);
|
|
130
132
|
return r.length === 1 ? r[0] : null;
|
|
131
133
|
}
|
|
132
|
-
function
|
|
134
|
+
function y(e, t) {
|
|
133
135
|
return [...new Map([...e, ...t].map((e) => [e.id, e])).values()];
|
|
134
136
|
}
|
|
135
|
-
function
|
|
137
|
+
function b(e) {
|
|
136
138
|
return typeof e == "object" && !!e;
|
|
137
139
|
}
|
|
138
140
|
//#endregion
|
|
139
|
-
export {
|
|
141
|
+
export { p as a, f as i, u as n, m as o, d as r, l as t };
|
|
140
142
|
|
|
141
|
-
//# sourceMappingURL=admin-pickers-
|
|
143
|
+
//# sourceMappingURL=admin-pickers-Djq3h-UR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-pickers-Djq3h-UR.js","names":["styles","formatMemberLabel","admin_pickers_module_default","PICKER_MENU_MAX_HEIGHT","MemberPicker","loading","setLoading","useState","options","setOptions","value","handleSearch","searchMembers","searchText","readMemberOption","AutoComplete","onChange","readMemberOptionFromValue","option","readUniqueOption","open","mergeMemberOptions","OrgUnitPicker","useMemo","orgUnits","readOrgUnitOption","Select","readOrgUnitOptionFromValue","PositionPicker","positions","readPositionOption","readPositionOptionFromValue","member","orgUnit","position","isRecord","email","id","name","normalized","matched","selected"],"sources":["../../src/components/admin-pickers.module.scss","../../src/components/admin-pickers.tsx"],"sourcesContent":[".pickerHost {\n width: 100%;\n min-width: 0;\n\n :global(.mzn-auto-complete),\n :global(.mzn-input),\n :global(.mzn-input-container),\n :global(.mzn-select),\n :global(.mzn-select-trigger),\n :global(.mzn-text-field) {\n width: 100%;\n min-width: 0 !important;\n }\n}\n","'use client';\n\nimport { useMemo, useState, type ReactElement } from 'react';\nimport { AutoComplete, Select } from '@mezzanine-ui/react';\nimport { searchMembers } from '@rytass/bpm-core-client';\nimport type {\n OrgUnitRecord,\n PositionRecord,\n} from '@rytass/bpm-core-client/organization';\nimport { formatMemberLabel } from '../lib/format-member-label';\nimport styles from './admin-pickers.module.scss';\n\nexport type MemberOption = Readonly<{\n email: string;\n id: string;\n name: string;\n}>;\n\nexport type OrgUnitOption = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport type PositionOption = Readonly<{\n id: string;\n name: string;\n}>;\n\n// Without a cap the Mezzanine dropdown grows with its options and never\n// mounts its scrollbar, so a long org-unit or position list runs off the\n// viewport with no way to reach the items below the fold. The pickers also\n// set `flip`: near the bottom of a modal the capped menu still overflows\n// unless it may open upwards.\nconst PICKER_MENU_MAX_HEIGHT = 320;\n\ninterface MemberPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: MemberOption | null) => void;\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: MemberOption | null;\n}\n\ninterface OrgUnitPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: OrgUnitOption | null) => void;\n readonly orgUnits: readonly OrgUnitRecord[];\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: OrgUnitOption | null;\n}\n\ninterface PositionPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: PositionOption | null) => void;\n readonly placeholder?: string;\n readonly positions: readonly PositionRecord[];\n readonly size?: 'main' | 'sub';\n readonly value: PositionOption | null;\n}\n\n/**\n * AutoComplete-backed picker that searches the BPM member directory via\n * `searchMembers()`. Emits a {@link MemberOption} `{ id, name, email }`\n * on selection (or `null` when cleared).\n */\nexport function MemberPicker({\n disabled = false,\n name,\n onChange,\n placeholder = '搜尋姓名或信箱',\n size,\n value,\n}: MemberPickerProps): ReactElement {\n const [loading, setLoading] = useState(false);\n const [options, setOptions] = useState<readonly MemberOption[]>(\n value ? [value] : [],\n );\n\n async function handleSearch(searchText: string): Promise<void> {\n setLoading(true);\n try {\n setOptions((await searchMembers(searchText)).map(readMemberOption));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className={styles.pickerHost}>\n <AutoComplete\n asyncData\n disabled={disabled}\n disabledOptionsFilter\n emptyText=\"沒有符合的會員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name,\n spellCheck: false,\n }}\n loading={loading}\n loadingText=\"搜尋會員中...\"\n mode=\"single\"\n onChange={(option): void => onChange(readMemberOptionFromValue(option))}\n onSearch={handleSearch}\n onSearchTextChange={(searchText): void =>\n onChange(readUniqueOption(searchText, options))\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearch('');\n }\n }}\n options={[...mergeMemberOptions(value ? [value] : [], options)]}\n placeholder={placeholder}\n searchDebounceTime={300}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of org units. Caller is\n * responsible for fetching the org units (typically via\n * `readOrganizationDashboard` from `@rytass/bpm-core-client/organization`).\n */\nexport function OrgUnitPicker({\n disabled = false,\n onChange,\n orgUnits,\n placeholder = '選擇組織',\n size,\n value,\n}: OrgUnitPickerProps): ReactElement {\n const options = useMemo(\n (): readonly OrgUnitOption[] => orgUnits.map(readOrgUnitOption),\n [orgUnits],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readOrgUnitOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of positions.\n */\nexport function PositionPicker({\n disabled = false,\n onChange,\n placeholder = '選擇職位',\n positions,\n size,\n value,\n}: PositionPickerProps): ReactElement {\n const options = useMemo(\n (): readonly PositionOption[] => positions.map(readPositionOption),\n [positions],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readPositionOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\nexport function readMemberOption(member: {\n readonly email: string;\n readonly memberId: string;\n readonly name: string;\n}): MemberOption {\n return {\n email: member.email,\n id: member.memberId,\n name: formatMemberLabel(member.name, member.email, 'dot'),\n };\n}\n\nexport function readOrgUnitOption(orgUnit: OrgUnitRecord): OrgUnitOption {\n return { id: orgUnit.id, name: `${orgUnit.name} · ${orgUnit.code}` };\n}\n\nexport function readPositionOption(position: PositionRecord): PositionOption {\n return { id: position.id, name: `${position.name} · ${position.code}` };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) return null;\n const email = value.email;\n const id = value.id;\n const name = value.name;\n return typeof email === 'string' &&\n typeof id === 'string' &&\n typeof name === 'string'\n ? { email, id, name }\n : null;\n}\n\nfunction readOrgUnitOptionFromValue(value: unknown): OrgUnitOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readPositionOptionFromValue(value: unknown): PositionOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readUniqueOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalized = searchText.trim().toLocaleLowerCase();\n if (!normalized) return null;\n const matched = options.filter(\n (option) =>\n option.id.toLocaleLowerCase() === normalized ||\n option.email.toLocaleLowerCase() === normalized ||\n option.name.toLocaleLowerCase() === normalized,\n );\n return matched.length === 1 ? matched[0] : null;\n}\n\nfunction mergeMemberOptions(\n selected: readonly MemberOption[],\n options: readonly MemberOption[],\n): readonly MemberOption[] {\n const byId = new Map(\n [...selected, ...options].map(\n (option): readonly [string, MemberOption] => [option.id, option],\n ),\n );\n return [...byId.values()];\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";require('../categories.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./format-date-time-D-cx5M8z.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/core/form"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let c=require("@mezzanine-ui/icons"),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(){let[e,n]=(0,r.useState)([]),[p,y]=(0,r.useState)(1),[b,x]=(0,r.useState)(10),[S,C]=(0,r.useState)(`ALL`),[w,T]=(0,r.useState)(0),[E,D]=(0,r.useState)(null),[O,k]=(0,r.useState)(null),[A,j]=(0,r.useState)(!0),[M,N]=(0,r.useState)(null),[P,F]=(0,r.useState)(!1),[I,L]=(0,r.useState)(``),R=(0,r.useCallback)(async()=>{j(!0),k(null);try{let e=await(0,l.listApprovalTemplateCategoriesPage)({page:p,pageSize:b,searchText:I,status:_(S)});n(e.categories),T(e.totalCount)}catch(e){k(v(e))}finally{j(!1)}},[p,b,S,I]);(0,r.useEffect)(()=>{R()},[R]);let z=(0,r.useMemo)(()=>e.map(e=>({...e,key:e.id,updatedAtLabel:t.t(e.updatedAt)})),[e]),B=(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 V(e){F(!0),k(null);try{M?.type===`EDIT`&&M.record?await(0,l.updateApprovalTemplateCategory)({...e,id:M.record.id}):await(0,l.createApprovalTemplateCategory)(e),N(null),await R()}catch(e){throw k(v(e)),e}finally{F(!1)}}async function H(e){F(!0),k(null);try{await(0,l.updateApprovalTemplateCategory)({description:e.description,id:e.id,isActive:!e.isActive,name:e.name,sortOrder:e.sortOrder}),await R()}catch(e){k(v(e))}finally{F(!1)}}async function U(){if(E){F(!0),k(null);try{await(0,l.deleteApprovalTemplateCategory)(E.id),D(null),await R()}catch(e){k(v(e))}finally{F(!1)}}}let W=(0,r.useMemo)(()=>({render:e=>[{name:`編輯`,onClick:()=>N({record:e,type:`EDIT`})},{name:e.isActive?`停用`:`啟用`,onClick:()=>void H(e),variant:e.isActive?`destructive-secondary`:`base-secondary`},{name:`刪除`,onClick:()=>D({id:e.id,name:e.name}),variant:`destructive-secondary`}],variant:`base-secondary`,width:192}),[R]);return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.PageHeader,{children:(0,a.jsx)(s.default,{description:`維護簽核模板分類,供模板建立、篩選與列表標示使用。`,title:`簽核模板分類`,children:(0,a.jsx)(i.Button,{icon:c.PlusIcon,iconType:`leading`,onClick:()=>N({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:o.FormFieldLayout.VERTICAL,name:`categorySearchText`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{L(e.target.value),y(1)},placeholder:`關鍵字:搜尋分類名稱或說明`,size:`sub`,value:I,variant:`base`})})})})}),tab:(0,a.jsx)(i.Tab,{activeKey:S,onChange:e=>{C(g(e)),y(1)},children:f.map(e=>(0,a.jsx)(i.TabItem,{children:e.label},e.key))}),children:[O?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:O}):null,(0,a.jsx)(i.Table,{actions:W,columns:B,dataSource:z,fullWidth:!0,loading:A||P,pagination:{current:p,onChange:e=>{y(e)},onChangePageSize:e=>{y(1),x(e)},pageSize:b,pageSizeLabel:`每頁筆數`,pageSizeOptions:d,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:w}})]})})]}),(0,a.jsx)(m,{loading:P,modal:M,onClose:()=>N(null),onSubmit:V}),(0,a.jsx)(i.Modal,{cancelText:`取消`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`刪除`,loading:P,modalStatusType:`error`,modalType:`standard`,onCancel:()=>D(null),onClose:()=>D(null),onConfirm:()=>void U(),open:!!E,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText
|
|
2
|
-
//# sourceMappingURL=categories-
|
|
1
|
+
"use client";require('../categories.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./format-date-time-D-cx5M8z.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/core/form"),s=require("@mezzanine-ui/react/ContentHeader");s=e.t(s,1);let c=require("@mezzanine-ui/icons"),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(){let[e,n]=(0,r.useState)([]),[p,y]=(0,r.useState)(1),[b,x]=(0,r.useState)(10),[S,C]=(0,r.useState)(`ALL`),[w,T]=(0,r.useState)(0),[E,D]=(0,r.useState)(null),[O,k]=(0,r.useState)(null),[A,j]=(0,r.useState)(!0),[M,N]=(0,r.useState)(null),[P,F]=(0,r.useState)(!1),[I,L]=(0,r.useState)(``),R=(0,r.useCallback)(async()=>{j(!0),k(null);try{let e=await(0,l.listApprovalTemplateCategoriesPage)({page:p,pageSize:b,searchText:I,status:_(S)});n(e.categories),T(e.totalCount)}catch(e){k(v(e))}finally{j(!1)}},[p,b,S,I]);(0,r.useEffect)(()=>{R()},[R]);let z=(0,r.useMemo)(()=>e.map(e=>({...e,key:e.id,updatedAtLabel:t.t(e.updatedAt)})),[e]),B=(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 V(e){F(!0),k(null);try{M?.type===`EDIT`&&M.record?await(0,l.updateApprovalTemplateCategory)({...e,id:M.record.id}):await(0,l.createApprovalTemplateCategory)(e),N(null),await R()}catch(e){throw k(v(e)),e}finally{F(!1)}}async function H(e){F(!0),k(null);try{await(0,l.updateApprovalTemplateCategory)({description:e.description,id:e.id,isActive:!e.isActive,name:e.name,sortOrder:e.sortOrder}),await R()}catch(e){k(v(e))}finally{F(!1)}}async function U(){if(E){F(!0),k(null);try{await(0,l.deleteApprovalTemplateCategory)(E.id),D(null),await R()}catch(e){k(v(e))}finally{F(!1)}}}let W=(0,r.useMemo)(()=>({render:e=>[{name:`編輯`,onClick:()=>N({record:e,type:`EDIT`})},{name:e.isActive?`停用`:`啟用`,onClick:()=>void H(e),variant:e.isActive?`destructive-secondary`:`base-secondary`},{name:`刪除`,onClick:()=>D({id:e.id,name:e.name}),variant:`destructive-secondary`}],variant:`base-secondary`,width:192}),[R]);return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(i.PageHeader,{children:(0,a.jsx)(s.default,{description:`維護簽核模板分類,供模板建立、篩選與列表標示使用。`,title:`簽核模板分類`,children:(0,a.jsx)(i.Button,{icon:c.PlusIcon,iconType:`leading`,onClick:()=>N({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:o.FormFieldLayout.VERTICAL,name:`categorySearchText`,children:(0,a.jsx)(i.Input,{fullWidth:!0,onChange:e=>{L(e.target.value),y(1)},placeholder:`關鍵字:搜尋分類名稱或說明`,size:`sub`,value:I,variant:`base`})})})})}),tab:(0,a.jsx)(i.Tab,{activeKey:S,onChange:e=>{C(g(e)),y(1)},children:f.map(e=>(0,a.jsx)(i.TabItem,{children:e.label},e.key))}),children:[O?(0,a.jsx)(i.Typography,{color:`text-error`,variant:`body`,children:O}):null,(0,a.jsx)(i.Table,{actions:W,columns:B,dataSource:z,fullWidth:!0,loading:A||P,pagination:{current:p,onChange:e=>{y(e)},onChangePageSize:e=>{y(1),x(e)},pageSize:b,pageSizeLabel:`每頁筆數`,pageSizeOptions:d,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:w}})]})})]}),(0,a.jsx)(m,{loading:P,modal:M,onClose:()=>N(null),onSubmit:V}),(0,a.jsx)(i.Modal,{cancelText:`取消`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`刪除`,loading:P,modalStatusType:`error`,modalType:`standard`,onCancel:()=>D(null),onClose:()=>D(null),onConfirm:()=>void U(),open:!!E,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`已被模板使用的分類無法刪除,請改用「停用」。`,title:`刪除分類`,children:(0,a.jsxs)(i.Typography,{color:`text-neutral`,variant:`body`,children:[`確定要刪除「`,E?.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(`請輸入分類名稱`);else if(!Number.isInteger(n))f(`排序必須是整數`);else 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-AxxhqjLZ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories-DjENouRm.cjs","names":["useState","useCallback","listApprovalTemplateCategoriesPage","useMemo","formatDateTime","Typography","updateApprovalTemplateCategory","createApprovalTemplateCategory","deleteApprovalTemplateCategory","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Tab","TabItem","Table","Modal","BPMFormField","Textarea","Badge","require_rolldown_runtime","require_format_date_time","require_bpm_form_field","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_template","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","categoryPageResult","readCategoryStatus","requestError","readErrorMessage","rows","category","columns","CategoryStatusBadge","record","handleSaveCategory","input","handleToggleCategory","handleConfirmDelete","tableActions","event","readCategoryStatusTabKey","activeKey","statusTab","page","pageSize","from","to","total","CategoryModal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","isActive","status"],"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 {\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\n\nexport function TemplateCategoriesView(): 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 <>\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 </>\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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"}
|
|
1
|
+
{"version":3,"file":"categories-AxxhqjLZ.cjs","names":["useState","useCallback","listApprovalTemplateCategoriesPage","useMemo","formatDateTime","Typography","updateApprovalTemplateCategory","createApprovalTemplateCategory","deleteApprovalTemplateCategory","_Fragment","PageHeader","ContentHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Tab","TabItem","Table","Modal","BPMFormField","Textarea","Badge","require_rolldown_runtime","require_format_date_time","require_bpm_form_field","react","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","_mezzanine_ui_icons","_rytass_bpm_core_client_template","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","categoryPageResult","readCategoryStatus","requestError","readErrorMessage","rows","category","columns","CategoryStatusBadge","record","handleSaveCategory","input","handleToggleCategory","handleConfirmDelete","tableActions","event","readCategoryStatusTabKey","activeKey","statusTab","page","pageSize","from","to","total","CategoryModal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","isActive","status"],"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 {\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\n\nexport function TemplateCategoriesView(): 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 <>\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 </>\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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"}
|
|
@@ -252,7 +252,7 @@ function N() {
|
|
|
252
252
|
showModalFooter: !0,
|
|
253
253
|
showModalHeader: !0,
|
|
254
254
|
size: "regular",
|
|
255
|
-
supportingText: "
|
|
255
|
+
supportingText: "已被模板使用的分類無法刪除,請改用「停用」。",
|
|
256
256
|
title: "刪除分類",
|
|
257
257
|
children: /* @__PURE__ */ w(x, {
|
|
258
258
|
color: "text-neutral",
|
|
@@ -373,4 +373,4 @@ function P(e) {
|
|
|
373
373
|
//#endregion
|
|
374
374
|
export { A as n, N as t };
|
|
375
375
|
|
|
376
|
-
//# sourceMappingURL=categories-
|
|
376
|
+
//# sourceMappingURL=categories-riC33J_j.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories-1gKxeEqw.js","names":["_Fragment","styles","formatDateTime","Fragment$1","ContentHeader","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","useState","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","useCallback","categoryPageResult","listApprovalTemplateCategoriesPage","readCategoryStatus","requestError","readErrorMessage","rows","useMemo","category","columns","CategoryStatusBadge","record","Typography","handleSaveCategory","updateApprovalTemplateCategory","input","createApprovalTemplateCategory","handleToggleCategory","handleConfirmDelete","deleteApprovalTemplateCategory","tableActions","PageHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","Tab","readCategoryStatusTabKey","activeKey","TabItem","statusTab","Table","page","pageSize","from","to","total","CategoryModal","Modal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","BPMFormField","Textarea","isActive","Badge","status"],"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 {\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\n\nexport function TemplateCategoriesView(): 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 <>\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 </>\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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"}
|
|
1
|
+
{"version":3,"file":"categories-riC33J_j.js","names":["_Fragment","styles","formatDateTime","Fragment$1","ContentHeader","templates_module_default","CATEGORY_PAGE_SIZE_OPTIONS","CATEGORY_STATUS_TABS","TemplateCategoriesView","categories","setCategories","useState","categoryPage","setCategoryPage","categoryPageSize","setCategoryPageSize","categoryStatus","setCategoryStatus","categoryTotalCount","setCategoryTotalCount","deleteConfirmation","setDeleteConfirmation","error","setError","loading","setLoading","modalState","setModalState","saving","setSaving","searchText","setSearchText","refreshCategories","useCallback","categoryPageResult","listApprovalTemplateCategoriesPage","readCategoryStatus","requestError","readErrorMessage","rows","useMemo","category","columns","CategoryStatusBadge","record","Typography","handleSaveCategory","updateApprovalTemplateCategory","input","createApprovalTemplateCategory","handleToggleCategory","handleConfirmDelete","deleteApprovalTemplateCategory","tableActions","PageHeader","Button","PlusIcon","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","Tab","readCategoryStatusTabKey","activeKey","TabItem","statusTab","Table","page","pageSize","from","to","total","CategoryModal","Modal","description","setDescription","name","setName","sortOrder","setSortOrder","modal","handleConfirm","trimmedName","parsedSortOrder","onSubmit","submitError","onClose","BPMFormField","Textarea","isActive","Badge","status"],"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 {\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\n\nexport function TemplateCategoriesView(): 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 <>\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 </>\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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"}
|