@rytass/bpm-core-react 0.4.1 → 0.6.0
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 +85 -0
- package/README.md +21 -0
- package/dist/chunks/FormBuilderView-B_KGPjlp.cjs +3 -0
- package/dist/chunks/FormBuilderView-B_KGPjlp.cjs.map +1 -0
- package/dist/chunks/FormBuilderView-D8DrQOXD.js +1090 -0
- package/dist/chunks/FormBuilderView-D8DrQOXD.js.map +1 -0
- package/dist/chunks/{approval-instance-list-page-C5ZKPHdA.cjs → approval-instance-list-page-BMUKxzcz.cjs} +2 -2
- package/dist/chunks/{approval-instance-list-page-C5ZKPHdA.cjs.map → approval-instance-list-page-BMUKxzcz.cjs.map} +1 -1
- package/dist/chunks/{approval-instance-list-page-BF2r5D2-.js → approval-instance-list-page-YZcGGDD8.js} +2 -2
- package/dist/chunks/{approval-instance-list-page-BF2r5D2-.js.map → approval-instance-list-page-YZcGGDD8.js.map} +1 -1
- package/dist/chunks/compose-PMrmi-LE.js +451 -0
- package/dist/chunks/compose-PMrmi-LE.js.map +1 -0
- package/dist/chunks/compose-ziVbRYdo.cjs +2 -0
- package/dist/chunks/compose-ziVbRYdo.cjs.map +1 -0
- package/dist/chunks/{dashboard-page-Ib8srCMy.js → dashboard-page-DJ9vOPga.js} +2 -2
- package/dist/chunks/{dashboard-page-Ib8srCMy.js.map → dashboard-page-DJ9vOPga.js.map} +1 -1
- package/dist/chunks/{dashboard-page-CddG1MnK.cjs → dashboard-page-DwHQY6Ki.cjs} +2 -2
- package/dist/chunks/{dashboard-page-CddG1MnK.cjs.map → dashboard-page-DwHQY6Ki.cjs.map} +1 -1
- package/dist/chunks/designer-DCn6_v4b.cjs +65 -0
- package/dist/chunks/designer-DCn6_v4b.cjs.map +1 -0
- package/dist/chunks/designer-mOMxJ0Py.js +2576 -0
- package/dist/chunks/designer-mOMxJ0Py.js.map +1 -0
- package/dist/chunks/detail-Cci9tnoC.cjs +2 -0
- package/dist/chunks/detail-Cci9tnoC.cjs.map +1 -0
- package/dist/chunks/detail-kyolfdBu.js +1957 -0
- package/dist/chunks/detail-kyolfdBu.js.map +1 -0
- package/dist/chunks/{routes-config-dxahImVe.js → routes-config-RBYQtUd0.js} +2 -3
- package/dist/chunks/routes-config-RBYQtUd0.js.map +1 -0
- package/dist/chunks/routes-config-fDVHmvXi.cjs +2 -0
- package/dist/chunks/routes-config-fDVHmvXi.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +268 -128
- package/dist/index.js.map +1 -1
- package/dist/lib/routes-config.d.ts +6 -4
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.js +1 -1
- package/dist/next/workflow-chat-route.cjs +19 -0
- package/dist/next/workflow-chat-route.cjs.map +1 -0
- package/dist/next/workflow-chat-route.d.ts +17 -0
- package/dist/next/workflow-chat-route.js +31 -0
- package/dist/next/workflow-chat-route.js.map +1 -0
- package/dist/pages/instances/detail/index.cjs +1 -1
- package/dist/pages/instances/detail/index.js +1 -1
- package/dist/pages/templates/compose/index.cjs +2 -0
- package/dist/pages/templates/compose/index.cjs.map +1 -0
- package/dist/pages/templates/compose/index.d.ts +13 -0
- package/dist/pages/templates/compose/index.js +14 -0
- package/dist/pages/templates/compose/index.js.map +1 -0
- package/dist/pages/templates/designer/index.cjs +1 -1
- package/dist/pages/templates/designer/index.cjs.map +1 -1
- package/dist/pages/templates/designer/index.js +7 -2
- package/dist/pages/templates/designer/index.js.map +1 -1
- package/dist/pages/templates/index.cjs +1 -1
- package/dist/pages/templates/index.cjs.map +1 -1
- package/dist/pages/templates/index.js +3 -3
- package/dist/pages/templates/index.js.map +1 -1
- package/dist/views/cc/index.cjs +1 -1
- package/dist/views/cc/index.js +1 -1
- package/dist/views/dashboard/index.cjs +1 -1
- package/dist/views/dashboard/index.js +1 -1
- package/dist/views/forms/builder/FormBuilderView.d.ts +13 -4
- package/dist/views/forms/builder/index.cjs +1 -1
- package/dist/views/forms/builder/index.js +1 -1
- package/dist/views/forms/builder/json-code-editor.d.ts +1 -1
- package/dist/views/inbox/index.cjs +1 -1
- package/dist/views/inbox/index.js +1 -1
- package/dist/views/instances/detail/InstanceDetailView.d.ts +11 -1
- package/dist/views/instances/detail/index.cjs +1 -1
- package/dist/views/instances/detail/index.d.ts +5 -0
- package/dist/views/instances/detail/index.js +2 -2
- package/dist/views/instances/detail/sections/InstanceAttachmentsSection.d.ts +15 -0
- package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +33 -0
- package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +29 -0
- package/dist/views/instances/detail/sections/InstanceSignaturesSection.d.ts +14 -0
- package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +51 -0
- package/dist/views/instances/detail/sections/container-helpers.d.ts +9 -0
- package/dist/views/instances/detail/sections/shared.d.ts +103 -0
- package/dist/views/instances/new/index.cjs +1 -1
- package/dist/views/instances/new/index.js +1 -1
- package/dist/views/search/index.cjs +1 -1
- package/dist/views/search/index.js +1 -1
- package/dist/views/sent/index.cjs +1 -1
- package/dist/views/sent/index.js +1 -1
- package/dist/views/templates/TemplatesView.d.ts +5 -0
- package/dist/views/templates/compose/TemplateComposeWizardView.d.ts +8 -0
- package/dist/views/templates/compose/index.cjs +1 -0
- package/dist/views/templates/compose/index.d.ts +2 -0
- package/dist/views/templates/compose/index.js +2 -0
- package/dist/views/templates/compose/steps/ComposeFormStep.d.ts +15 -0
- package/dist/views/templates/compose/steps/ComposeReviewStep.d.ts +12 -0
- package/dist/views/templates/compose/steps/ComposeWorkflowStep.d.ts +11 -0
- package/dist/views/templates/compose/use-template-compose-wizard.d.ts +46 -0
- package/dist/views/templates/designer/TemplateDesignerView.d.ts +60 -2
- package/dist/views/templates/designer/chrome-workflow-chat.d.ts +12 -0
- package/dist/views/templates/designer/index.cjs +1 -51
- package/dist/views/templates/designer/index.js +2 -2272
- package/dist/views/templates/designer/use-workflow-chat.d.ts +21 -0
- package/dist/views/templates/designer/use-workflow-designer-controller.d.ts +41 -0
- package/dist/views/templates/designer/workflow-chat-drawer.d.ts +16 -0
- package/dist/views/templates/index.cjs +2 -1
- package/dist/views/templates/index.cjs.map +1 -0
- package/dist/views/templates/index.js +265 -4
- package/dist/views/templates/index.js.map +1 -0
- package/dist/views/templates/versions/index.cjs +1 -1
- package/dist/views/templates/versions/index.cjs.map +1 -1
- package/dist/views/templates/versions/index.js +38 -42
- package/dist/views/templates/versions/index.js.map +1 -1
- package/package.json +22 -19
- package/dist/chunks/builder-BLVnnpnP.js +0 -1300
- package/dist/chunks/builder-BLVnnpnP.js.map +0 -1
- package/dist/chunks/builder-DVE9zIKH.cjs +0 -3
- package/dist/chunks/builder-DVE9zIKH.cjs.map +0 -1
- package/dist/chunks/detail-Dcr5mM8g.cjs +0 -2
- package/dist/chunks/detail-Dcr5mM8g.cjs.map +0 -1
- package/dist/chunks/detail-u9DdLhDW.js +0 -1518
- package/dist/chunks/detail-u9DdLhDW.js.map +0 -1
- package/dist/chunks/form-name-modal-C3OEvkCV.js +0 -64
- package/dist/chunks/form-name-modal-C3OEvkCV.js.map +0 -1
- package/dist/chunks/form-name-modal-uZCHbtRH.cjs +0 -2
- package/dist/chunks/form-name-modal-uZCHbtRH.cjs.map +0 -1
- package/dist/chunks/routes-config-2aKbWq2H.cjs +0 -2
- package/dist/chunks/routes-config-2aKbWq2H.cjs.map +0 -1
- package/dist/chunks/routes-config-dxahImVe.js.map +0 -1
- package/dist/chunks/templates-D44FSB46.js +0 -380
- package/dist/chunks/templates-D44FSB46.js.map +0 -1
- package/dist/chunks/templates-w96t83N-.cjs +0 -2
- package/dist/chunks/templates-w96t83N-.cjs.map +0 -1
- package/dist/pages/forms/builder/index.cjs +0 -2
- package/dist/pages/forms/builder/index.cjs.map +0 -1
- package/dist/pages/forms/builder/index.d.ts +0 -21
- package/dist/pages/forms/builder/index.js +0 -15
- package/dist/pages/forms/builder/index.js.map +0 -1
- package/dist/pages/forms/index.cjs +0 -2
- package/dist/pages/forms/index.cjs.map +0 -1
- package/dist/pages/forms/index.d.ts +0 -17
- package/dist/pages/forms/index.js +0 -14
- package/dist/pages/forms/index.js.map +0 -1
- package/dist/views/forms/FormsView.d.ts +0 -2
- package/dist/views/forms/form-name-modal.d.ts +0 -12
- package/dist/views/forms/index.cjs +0 -2
- package/dist/views/forms/index.cjs.map +0 -1
- package/dist/views/forms/index.d.ts +0 -2
- package/dist/views/forms/index.js +0 -186
- package/dist/views/forms/index.js.map +0 -1
- package/dist/views/templates/designer/index.cjs.map +0 -1
- package/dist/views/templates/designer/index.js.map +0 -1
- package/dist/views/templates/template-name-modal.d.ts +0 -22
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";require('../detail.css');const e=require("./chunk-CMqjfN_6.cjs"),t=require("./auth-provider-4BeCw7cI.cjs"),n=require("./format-date-time-XxBzF0F5.cjs"),r=require("./bpm-form-field-Bc6k4ZEO.cjs"),i=require("./FormRendererView-BwVsH2eX.cjs");let a=require("react"),o=require("@mezzanine-ui/react"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/react/ContentHeader");l=e.t(l,1);let u=require("@mezzanine-ui/icons"),d=require("@rytass/bpm-core-client/form"),f=require("@xyflow/react"),p=require("dagre");p=e.t(p,1);let m=require("react-pdf"),h=require("@mezzanine-ui/core/stepper");var g={root:`bpm_root_ehm7w`,toolbar:`bpm_toolbar_R-tis`,pageControls:`bpm_pageControls_jM-rC`,zoomControls:`bpm_zoomControls_7RAbJ`,counter:`bpm_counter_ILUsD`,viewport:`bpm_viewport_DQXms`,page:`bpm_page_Cv5Rg`,state:`bpm_state_bpgp3`},ee=760,_=920,te=320,v=32,y=.75,b=1.75,ne=.25;function re({filename:e,fileUrl:t,onDownload:n}){let r=(0,a.useRef)(null),[i,c]=(0,a.useState)(null),[l,d]=(0,a.useState)(1),[f,p]=(0,a.useState)(1),[h,re]=(0,a.useState)(ee);(0,a.useEffect)(()=>{let e=r.current;if(!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(e=>{let t=e[0]?.contentRect.width;t&&re(t)});return t.observe(e),()=>t.disconnect()},[]),(0,a.useEffect)(()=>{c(null),d(1),p(1)},[t]);let S=(0,a.useMemo)(()=>{let e=Math.max(te,h-v);return Math.round(Math.min(_,e)*f)},[f,h]),ie=(0,a.useCallback)(e=>{c(e.numPages),d(1)},[]),C=l>1,ae=i!==null&&l<i,w=f>y,T=f<b,E=i===null?`第 ${l} 頁`:`第 ${l} / ${i} 頁`,oe=`${Math.round(f*100)}%`;return(0,s.jsxs)(`section`,{"aria-label":`${e} PDF 預覽`,className:g.root,children:[(0,s.jsxs)(`div`,{className:g.toolbar,children:[(0,s.jsxs)(`div`,{className:g.pageControls,"aria-label":`頁面切換`,children:[(0,s.jsx)(o.Button,{"aria-label":`上一頁`,disabled:!C,icon:u.ChevronLeftIcon,onClick:()=>{d(e=>Math.max(1,e-1))},size:`minor`,variant:`base-secondary`}),(0,s.jsx)(o.Typography,{className:g.counter,component:`span`,variant:`body`,children:E}),(0,s.jsx)(o.Button,{"aria-label":`下一頁`,disabled:!ae,icon:u.ChevronRightIcon,onClick:()=>{d(e=>i===null?e:Math.min(i,e+1))},size:`minor`,variant:`base-secondary`})]}),(0,s.jsxs)(`div`,{className:g.zoomControls,"aria-label":`縮放`,children:[(0,s.jsx)(o.Button,{"aria-label":`縮小`,disabled:!w,icon:u.ZoomOutIcon,onClick:()=>{p(e=>Math.max(y,e-ne))},size:`minor`,variant:`base-secondary`}),(0,s.jsx)(o.Typography,{className:g.counter,component:`span`,variant:`body`,children:oe}),(0,s.jsx)(o.Button,{"aria-label":`放大`,disabled:!T,icon:u.ZoomInIcon,onClick:()=>{p(e=>Math.min(b,e+ne))},size:`minor`,variant:`base-secondary`})]}),n?(0,s.jsx)(o.Button,{icon:u.DownloadIcon,iconType:`leading`,onClick:n,size:`minor`,variant:`base-primary`,children:`下載`}):null]}),(0,s.jsx)(`div`,{className:g.viewport,ref:r,children:(0,s.jsx)(m.Document,{error:(0,s.jsx)(x,{message:`PDF 無法載入。`}),file:t,loading:(0,s.jsx)(x,{message:`正在載入 PDF...`}),noData:(0,s.jsx)(x,{message:`沒有可預覽的 PDF。`}),onLoadSuccess:ie,children:(0,s.jsx)(m.Page,{className:g.page,loading:(0,s.jsx)(x,{message:`正在載入頁面...`}),pageNumber:l,renderAnnotationLayer:!0,renderTextLayer:!0,width:S})})})]})}function x({message:e}){return(0,s.jsx)(`div`,{className:g.state,children:(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:e})})}function S(e){let t=C(e,`from`),n=C(e,`to`),r=C(e,`reason`);return!t||!n||!r?null:{from:t,reason:r,ruleId:C(e,`ruleId`),to:n}}function ie(e){try{let t=JSON.parse(e);return Array.isArray(t)?t.map(e=>E(e)?S(e):null).filter(e=>e!==null):[]}catch{return[]}}function C(e,t){let n=e[t];return typeof n==`string`?n:null}function ae(e,t){let n=e[t];return Array.isArray(n)?n.filter(e=>typeof e==`string`):[]}function w(e,t){let n=e[t];return typeof n==`number`?n:null}function T(e){return typeof e==`string`&&e.trim().length>0}function E(e){return typeof e==`object`&&!!e}function oe(e){return e.status===`PENDING`||e.status===`IN_PROGRESS`}function D(e){return e instanceof Error?e.message:`發生未知錯誤`}function se(e){return!Number.isFinite(e)||e<=0?`-`:e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function O(e){return e.length>16?`${e.slice(0,12)}...`:e}function ce(e){return e===`APPROVED`?`已同意`:e===`CANCELLED`?`已取消`:e===`DRAFT`?`草稿`:e===`EXPIRED`?`已逾期`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`RUNNING`?`進行中`:e}function le(e){return e===`PENDING`?`待處理`:e===`IN_PROGRESS`?`處理中`:e===`COMPLETED`?`已完成`:e===`CANCELLED`?`已取消`:e===`TRANSFERRED`?`已轉派`:e}function ue(e){return e===`APPROVED`?`同意`:e===`REJECTED`?`拒絕`:e===`RETURNED`?`退回`:e===`TRANSFERRED`?`轉派`:e}function k(e){return e===`startEvent`?`開始`:e===`endEvent`?`完成`:e===`userTask`?`簽核節點`:e===`serviceTask`?`知會節點`:e===`exclusiveGateway`?`條件分流`:`平行處理`}function A(e,t){return t?.nodes.find(t=>t.id===e)?.data.label??e}function j(e,t){if(!e)return`-`;let n=t.get(e);return n?`${n.name}(${n.email})`:e}function M(e,t=new Map){let n=ie(e.delegationChainJson);if(!e.assigneeMemberId)return e.candidateMemberIds.length?`候選 ${e.candidateMemberIds.map(e=>j(e,t)).join(`、`)}`:`未指定`;let r=j(e.assigneeMemberId,t),i=j(e.originalAssigneeMemberId,t);return n.length===0||e.originalAssigneeMemberId===e.assigneeMemberId?r:`${r}(原:${i})`}function de(e,t){return t?e.assigneeMemberId===t||e.candidateMemberIds.includes(t):!1}function fe(e,t){if(t.type!==`userTask`||!t.data.returnBehavior.allowReturn)return[];if(t.data.returnBehavior.allowedTargets===`ANY`)return e.nodes.filter(e=>e.id!==t.id).map(e=>({id:e.id,name:`${e.data.label}(${k(e.type)})`}));let n=t.data.returnBehavior.allowedTargets===`INITIATOR`?e.nodes.find(e=>e.type===`startEvent`)?.id:e.edges.find(e=>e.target===t.id)?.source,r=e.nodes.find(e=>e.id===n);return r?[{id:r.id,name:`${r.data.label}(${k(r.type)})`}]:[]}function N(e){return{email:e.email,id:e.memberId,name:`${e.name} · ${e.email}`}}function pe(e){if(!E(e))return null;let t=e.email,n=e.id,r=e.name;return typeof n==`string`&&typeof r==`string`?{email:typeof t==`string`?t:null,id:n,name:r}:null}function me(e,t){let n=e.trim().toLocaleLowerCase();if(!n)return null;let r=t.filter(e=>[e.id,e.name,e.email??``].some(e=>e.toLocaleLowerCase().includes(n)));return r.length===1?r[0]??null:null}function P(e){return T(e)?{text:e,type:`text`}:null}function he(e){return T(e)?{text:e,type:`dangerText`}:null}function F(e,t,n,r){let i=t?n.get(t):null;return{email:i?.email??null,label:i?.name??r,memberId:t,prefix:e,type:`member`}}function I(e){return!!e}function ge(e){let t=e.findIndex(e=>e.id.startsWith(`pending-task-`)||e.id.startsWith(`future-node-`));return t===-1?e.length:t}function L(e){return e.eventType===`INSTANCE_STARTED`||e.eventType===`TASK_DECIDED`||e.eventType===`SLA_TRIGGERED`}function R(e){return e===`APPROVED`?`已同意`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`TRANSFERRED`?`已轉派`:`簽核已決議`}function _e(e,t){return e===`INSTANCE_STARTED`?`案件已發起`:e===`TOKEN_CREATED`?`流程路徑已建立`:e===`ENGINE_PROCESS_REQUESTED`?`流程引擎已處理`:e===`TOKEN_ADVANCED`?`流程已前進`:e===`TASK_CREATED`?`待簽任務已建立`:e===`TASK_DECIDED`?R(C(t,`action`)):e===`SLA_TRIGGERED`?`時限提醒已觸發`:e}function z(e){try{let t=JSON.parse(e.payloadJson);return E(t)?t:{}}catch{return{}}}function B(e,t){return e.eventType===`SLA_TRIGGERED`||C(t,`action`)===`REJECTED`||C(t,`instanceState`)===`REJECTED`}function V(e){return n.t(e)}function ve(e,t,n,r){if(e.eventType===`TASK_CREATED`){let e=C(t,`assigneeMemberId`),n=C(t,`originalAssigneeMemberId`);if(!e){let e=ae(t,`candidateMemberIds`);return e.length?`候選簽核人:${e.map(e=>j(e,r)).join(`、`)}`:null}let i=j(e,r),a=j(n,r);return n&&n!==e?`待簽人:${i}(原簽核人:${a})`:`待簽人:${i}`}if(e.eventType===`TASK_DECIDED`){let e=C(t,`action`),n=C(t,`comment`),i=e?`決議:${ue(e)}`:null,a=C(t,`transferToMemberId`);return e===`REJECTED`&&n?[i,`拒絕原因:${n}`].filter(T).join(` · `):e===`TRANSFERRED`?[i,`轉派給:${j(a,r)}`].filter(T).join(` · `):i}if(e.eventType===`TOKEN_ADVANCED`){let e=C(t,`action`);if(e)return`流程結果:${ue(e)}`;let r=w(t,`arrivedCount`),i=w(t,`requiredCount`);if(r!==null&&i!==null)return`等待匯合:${r}/${i}`;let a=C(t,`fromNodeId`),o=C(t,`toNodeId`);if(a&&o)return`由 ${A(a,n)} 前進至 ${A(o,n)}`}if(e.eventType===`ENGINE_PROCESS_REQUESTED`){let e=C(t,`state`);return e?`案件狀態:${ce(e)}`:null}return null}function ye(e,t,n,r,i,a,o){if(e.eventType!==`TASK_DECIDED`)return[P(ve(e,t,n,o))].filter(I);let s=e.taskId?r.get(e.taskId):null,c=C(t,`action`)??s?.action??null,l=C(t,`comment`)??s?.comment??null,u=C(t,`transferToMemberId`)??s?.transferToMemberId??null,d=C(t,`signatureId`)??s?.signatureId??null,f=d?i.get(d):null;return[P(c?`決議:${ue(c)}`:null),c===`REJECTED`?he(`拒絕原因:${l??`-`}`):null,c===`RETURNED`?P(`退回說明:${l??`-`}`):null,c===`TRANSFERRED`?P(`轉派給:${j(u,o)}`):null,c===`TRANSFERRED`?P(`轉派說明:${l??`-`}`):null,f?P(a?.valid?`簽章:已驗證(${O(f.signedPayloadHash)})`:`簽章:待檢查(${O(f.signedPayloadHash)})`):null].filter(I)}function be(e,t,n,r,i){if(e.type===`startEvent`||i.has(e.id))return!1;if(r===`REJECTED`)return!0;let a=we(e,t,n,r);return a.tone===`neutral`||a.tone===`waiting`}function H(e,t,n,r,i){if(r!==`RUNNING`&&r!==`REJECTED`)return[];let a=e.nodes.filter(e=>be(e,t,n,r,i)),o=U(e,a,t,n,i),s=new Map(e.nodes.map((e,t)=>[e.id,t]));return a.filter(e=>o.has(e.id)).sort((e,t)=>{let n=o.get(e.id)??0,r=o.get(t.id)??0;return n===r?e.position.x===t.position.x?e.position.y===t.position.y?(s.get(e.id)??0)-(s.get(t.id)??0):e.position.y-t.position.y:e.position.x-t.position.x:n-r})}function U(e,t,n,r,i){let a=new Set(t.map(e=>e.id)),o=e.edges.reduce((e,t)=>{let n=[...e.get(t.source)??[],t.target];return new Map(e).set(t.source,n)},new Map);return W(e,n,r,i).reduce((e,t)=>xe(e,G(t,o,a)),new Map)}function W(e,t,n,r){let i=n.filter(e=>e.status===`ACTIVE`||e.status===`WAITING`).map(e=>e.currentNodeId),a=t.filter(oe).map(e=>e.nodeId),o=e.nodes.filter(e=>r.has(e.id)).map(e=>e.id),s=[...new Set([...i,...a,...o])],c=e.nodes.filter(e=>e.type===`startEvent`).map(e=>e.id);return s.length>0?s:c}function G(e,t,n){return K([{distance:0,nodeId:e}],t,n)}function K(e,t,n,r=new Set,i=new Map){let[a,...o]=e;if(!a)return i;if(r.has(a.nodeId))return K(o,t,n,r,i);let s=new Set(r).add(a.nodeId),c=n.has(a.nodeId)?new Map(i).set(a.nodeId,Math.min(i.get(a.nodeId)??a.distance,a.distance)):i;return K([...o,...(t.get(a.nodeId)??[]).map(e=>({distance:a.distance+1,nodeId:e}))],t,n,s,c)}function xe(e,t){return[...t.entries()].reduce((e,[t,n])=>new Map(e).set(t,Math.min(e.get(t)??n,n)),e)}function Se(e){return e.type===`userTask`?`未來簽核:${e.data.label}`:e.type===`serviceTask`?`未來知會:${e.data.label}`:e.type===`exclusiveGateway`?`未來分流:${e.data.label}`:e.type===`parallelGateway`?`未來匯合:${e.data.label}`:e.type===`endEvent`?`流程完成:${e.data.label}`:`未來節點:${e.data.label}`}function Ce(e,t,n,r,i,a,o,s,c){let l=e.filter(L).map(e=>{let t=z(e),n=e.nodeId?A(e.nodeId,r):null;return{descriptionParts:[P(n?`節點:${n}`:`節點:全流程`),F(`操作者`,e.actorMemberId,a,`系統`),P(`時間:${V(e.createdAt)}`),...ye(e,t,r,o,s,c,a)].filter(I),error:B(e,t),id:e.id,title:_e(e.eventType,t)}}),u=t.filter(oe).map(e=>({descriptionParts:[P(`節點:${A(e.nodeId,r)}`),F(`處理者`,e.assigneeMemberId,a,`未指定`),P(`建立時間:${V(e.createdAt)}`)].filter(I),error:!1,id:`pending-task-${e.id}`,title:e.status===`IN_PROGRESS`?`簽核處理中`:`等待簽核處理`})),d=new Set([...e.filter(L).map(e=>e.nodeId),...t.map(e=>e.nodeId)].filter(T)),f=r?H(r,t,n,i,d).map(e=>({descriptionParts:[P(`${k(e.type)} · 尚未抵達`)].filter(I),error:!1,forcePending:!0,id:`future-node-${e.id}`,title:Se(e)})):[];return[...l,...u,...f]}function we(e,t,n,r){let i=t.filter(t=>t.nodeId===e.id),a=i.find(e=>e.status===`PENDING`||e.status===`IN_PROGRESS`),o=i.find(e=>e.status===`CANCELLED`),s=i.find(e=>e.status===`COMPLETED`),c=n.filter(t=>t.currentNodeId===e.id),l=c.find(e=>e.status===`ACTIVE`),u=c.find(e=>e.status===`WAITING`);return a?{secondaryLabel:`處理者 ${M(a)}`,statusLabel:`待處理`,tone:`current`}:o?{secondaryLabel:`已取消 ${M(o)}`,statusLabel:`已取消`,tone:`cancelled`}:s?{secondaryLabel:`已完成 ${M(s)}`,statusLabel:`已完成`,tone:`completed`}:l?{secondaryLabel:`token ${l.id}`,statusLabel:`執行中`,tone:`current`}:u?{secondaryLabel:`token ${u.id}`,statusLabel:`等待前置`,tone:`waiting`}:e.type===`startEvent`?{secondaryLabel:`流程已發起`,statusLabel:`已發起`,tone:`completed`}:e.type===`endEvent`&&r!==`RUNNING`?{secondaryLabel:r,statusLabel:r===`REJECTED`?`已拒絕`:`已完成`,tone:r===`REJECTED`?`cancelled`:`completed`}:{secondaryLabel:k(e.type),statusLabel:`未抵達`,tone:`neutral`}}async function q({activityLogs:e,adhocDirectives:t=[],tasks:n}){let r=[...new Set([...e.map(e=>e.actorMemberId),...n.map(e=>e.assigneeMemberId),...n.map(e=>e.originalAssigneeMemberId),...n.flatMap(e=>e.candidateMemberIds),...n.flatMap(e=>ie(e.delegationChainJson).flatMap(e=>[e.from,e.to])),...t.flatMap(e=>[e.createdByMemberId,...J(e.targetValueJson)])].filter(T))];try{return await(0,c.resolveMemberProfiles)(r)}catch{return[]}}function J(e){try{return(JSON.parse(e).memberIds??[]).filter(e=>typeof e==`string`)}catch{return[]}}async function Te(e){return(await Promise.all(e.map(e=>(0,c.listTaskDecisions)(e.id)))).flat()}function Ee(e){return e.reduce((e,t)=>{let n=e.get(t.taskId),r=!n||new Date(t.decidedAt).getTime()>new Date(n.decidedAt).getTime()?t:n;return new Map(e).set(t.taskId,r)},new Map)}var De={display:`grid`,gap:16},Y={display:`flex`,flexWrap:`wrap`,gap:8};function Oe({canResubmitInstance:e,deciding:t,error:n,instance:r,loading:a,onResubmitFormChange:c,onResubmitInstance:l,onUploadAttachment:d,resubmitFormData:f,resubmitFormErrors:p}){return(0,s.jsxs)(`div`,{style:De,children:[n?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:n}):null,a?(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`載入中...`}):null,r?.formDefinitionSnapshot.schema&&r.formDefinitionSnapshot.uiSchema?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.t,{errors:p,onChange:e=>{c(e)},onUploadAttachment:e?d:void 0,readonly:!e,schema:r.formDefinitionSnapshot.schema,uiSchema:r.formDefinitionSnapshot.uiSchema,value:e?f:r.formData}),e?(0,s.jsx)(`div`,{style:Y,children:(0,s.jsx)(o.Button,{disabled:t,icon:u.RefreshCcwIcon,iconType:`leading`,onClick:l,variant:`base-primary`,children:`重新送出`})}):null]}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`此案件沒有可顯示的表單快照。`})]})}var ke={display:`grid`,gap:16};function Ae({attachments:e,onDownload:t,onPreview:r}){let i=(0,a.useMemo)(()=>e.map(e=>({attachment:e,createdAt:e.createdAt,filename:e.filename,id:e.id,key:e.id,mimeType:e.mimeType,sizeLabel:se(Number(e.sizeBytes))})),[e]),c=(0,a.useMemo)(()=>[{dataIndex:`filename`,key:`filename`,title:`檔名`,width:260},{dataIndex:`mimeType`,key:`mimeType`,title:`類型`,width:180},{dataIndex:`sizeLabel`,key:`sizeLabel`,title:`大小`,width:120},{key:`createdAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.createdAt)}),title:`上傳時間`,width:220}],[]),l=(0,a.useMemo)(()=>({render:e=>[...e.mimeType===`application/pdf`?[{icon:u.FileSearchIcon,iconType:`leading`,name:`預覽`,onClick:()=>{r(e.attachment)}}]:[],{icon:u.DownloadIcon,iconType:`leading`,name:`下載`,onClick:()=>{t(e.attachment)}}],variant:`base-secondary`,width:160}),[t,r]);return(0,s.jsxs)(`div`,{style:ke,children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`附件`}),i.length>0?(0,s.jsx)(o.Table,{actions:l,columns:c,dataSource:i,fullWidth:!0}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`此案件沒有附件。`})]})}var je={display:`grid`,gap:12,width:`100%`},Me={minWidth:`100%`,width:`100%`},X={display:`grid`,gap:12,width:`100%`},Ne={marginTop:12},Pe={marginTop:24};function Fe(e){e&&(e.style.width=`100%`)}var Ie={COMPLETION_NOTIFY:`結案通知`,COUNTERSIGN:`臨時會簽`,PRE_APPROVAL:`臨時加簽`,STAGE_NOTIFY:`階段完成通知`},Le={COMPLETION_NOTIFY:`本張單到達結案狀態(核准 / 拒絕 / 取消)後,通知指定對象。`,COUNTERSIGN:`指定對象會併入下一層簽核,下一層需所有人都完成才會繼續。`,PRE_APPROVAL:`指定對象需先完成加簽,本階段才會往下一層繼續。`,STAGE_NOTIFY:`本階段完成後(不論通過與否)通知指定對象。`},Re=[{id:`REJECT_INSTANCE`,name:`加簽拒絕時整單駁回`},{id:`RETURN_TO_ORIGIN`,name:`加簽拒絕時退回給我重新處理`}],Z=[{id:`MEMBER`,name:`指定成員`},{id:`WEBHOOK`,name:`Webhook`}],ze=(0,a.forwardRef)(function({adhocDirectives:e,currentMemberId:t,instance:i,memberProfilesById:l,onChanged:u,tasks:d},f){let[p,m]=(0,a.useState)(!1),[h,g]=(0,a.useState)(null),[ee,_]=(0,a.useState)(``),[te,v]=(0,a.useState)(null),[y,b]=(0,a.useState)(!1),[ne,re]=(0,a.useState)(``),[x,S]=(0,a.useState)(!1),[ie,C]=(0,a.useState)(null),[ae,w]=(0,a.useState)(``),[T,E]=(0,a.useState)(null),[oe,se]=(0,a.useState)(!1),[O,ce]=(0,a.useState)([]),[ue,k]=(0,a.useState)(!1),[P,he]=(0,a.useState)(``),[F,I]=(0,a.useState)(null),[ge,L]=(0,a.useState)(!1),[R,_e]=(0,a.useState)([]),[z,B]=(0,a.useState)(!1),[V,ve]=(0,a.useState)(`COUNTERSIGN`),[ye,be]=(0,a.useState)(`REJECT_INSTANCE`),[H,U]=(0,a.useState)(!1),[W,G]=(0,a.useState)(`MEMBER`),[K,xe]=(0,a.useState)(``),Se=ee.trim(),Ce=ne.trim(),we=ae.trim(),q=(0,a.useMemo)(()=>d.find(e=>de(e,t)&&(e.status===`PENDING`||e.status===`IN_PROGRESS`))??null,[t,d]),J=(0,a.useMemo)(()=>q&&i?i.workflowSnapshot.nodes.find(e=>e.id===q.nodeId)??null:null,[q,i]),Te=(0,a.useMemo)(()=>J&&i?fe(i.workflowSnapshot,J):[],[J,i]),Ee=J?.type===`userTask`&&J.data.returnBehavior.allowReturn,De=J?.type===`userTask`&&J.data.allowAddSigner,Y=(0,a.useMemo)(()=>e.filter(e=>e.status===`PENDING`),[e]),Oe=Te.find(e=>e.id===ie)??Te[0]??null,ke=(0,a.useMemo)(()=>d.map(e=>({...e,assigneeLabel:M(e,l),key:e.id,nodeLabel:`${A(e.nodeId,i?.workflowSnapshot??null)}${e.isAdhoc?e.adhocType===`COUNTERSIGN`?`(臨時會簽)`:`(臨時加簽)`:``}`,statusLabel:le(e.status)})),[i,l,d]),Ae=(0,a.useMemo)(()=>[{dataIndex:`nodeLabel`,key:`nodeLabel`,title:`節點`,width:180},{key:`assigneeMemberId`,title:`處理者`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:e.assigneeLabel}),width:180},{dataIndex:`statusLabel`,key:`statusLabel`,title:`狀態`,width:120},{key:`createdAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.createdAt)}),title:`建立時間`,width:220}],[]),ze=(0,a.useMemo)(()=>Y.map(e=>({...e,createdByLabel:j(e.createdByMemberId,l),key:e.id,targetLabel:Be(e,l),typeLabel:Ie[e.type]})),[l,Y]),Ve=(0,a.useMemo)(()=>[{dataIndex:`typeLabel`,key:`typeLabel`,title:`類型`,width:180},{key:`targetLabel`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:e.targetLabel}),title:`對象`,width:220},{key:`createdByLabel`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:e.createdByLabel}),title:`設定者`,width:180},{key:`createdAt`,render:e=>(0,s.jsx)(o.Typography,{component:`span`,variant:`body`,children:n.t(e.createdAt)}),title:`建立時間`,width:220},{key:`actions`,render:e=>e.createdByMemberId===t?(0,s.jsx)(o.Button,{disabled:H,onClick:()=>void rt(e.id),size:`minor`,variant:`destructive-secondary`,children:`撤回`}):(0,s.jsx)(s.Fragment,{}),title:`操作`,width:100}],[H,t]);async function He({action:e,comment:n,returnToNodeId:r=null,transferToMemberId:i=null}){if(!(!t||!q)){m(!0),g(null);try{await(0,c.decideTask)({action:e,comment:n,decidedByMemberId:t,returnToNodeId:r,taskId:q.id,transferToMemberId:i}),b(!1),S(!1),k(!1),_(``),re(``),w(``),E(null),C(null),v(null),await u()}catch(e){g(D(e))}finally{m(!1)}}}function Ue(){_(``),v(null),b(!0)}function We(){p||(b(!1),_(``),v(null))}function Ge(){re(``),C(Te[0]?.id??null),S(!0)}function Ke(){p||(S(!1),re(``),C(null))}function qe(){w(``),E(null),k(!0),Ye(``)}function Je(){p||(k(!1),w(``),E(null))}async function Ye(e){se(!0);try{ce((await(0,c.searchMembers)(e)).filter(e=>e.memberId!==t).map(N))}catch(e){g(D(e))}finally{se(!1)}}async function Xe(){if(!Se){v(`請輸入拒絕原因`);return}await He({action:`REJECTED`,comment:Se})}async function Ze(){if(!T){g(`請選擇轉派對象`);return}await He({action:`TRANSFERRED`,comment:we||null,transferToMemberId:T.id})}async function Qe(){await He({action:`RETURNED`,comment:Ce||null,returnToNodeId:Oe?.id??null})}function $e(){he(``),I(null),be(`REJECT_INSTANCE`),G(`MEMBER`),xe(``)}function Q(e){ve(e),$e(),B(!0),tt(``)}function et(){H||(B(!1),$e())}async function tt(e){L(!0);try{_e((await(0,c.searchMembers)(e)).map(N))}catch(e){g(D(e))}finally{L(!1)}}async function nt(){if(!q)return;let e=(V===`STAGE_NOTIFY`||V===`COMPLETION_NOTIFY`)&&W===`WEBHOOK`,t=K.trim(),n=F;if(e&&!t){g(`請輸入 Webhook URL`);return}if(!e&&!n){g(`請選擇對象成員`);return}let r=e||!n?{kind:`WEBHOOK`,webhookUrl:t}:{kind:`MEMBER`,memberIds:[n.id]},i=P.trim()||null;U(!0),g(null);try{V===`COUNTERSIGN`?await(0,c.requestAdhocCountersign)({comment:i,target:r,taskId:q.id}):V===`PRE_APPROVAL`?await(0,c.requestAdhocPreApproval)({comment:i,onReject:ye,target:r,taskId:q.id}):V===`STAGE_NOTIFY`?await(0,c.configureAdhocStageNotification)({target:r,taskId:q.id}):await(0,c.configureAdhocCompletionNotification)({target:r,taskId:q.id}),B(!1),$e(),await u()}catch(e){g(D(e))}finally{U(!1)}}async function rt(e){U(!0),g(null);try{await(0,c.cancelAdhocDirective)(e),await u()}catch(e){g(D(e))}finally{U(!1)}}(0,a.useImperativeHandle)(f,()=>({canAddSignerCurrentTask:De,canReturnCurrentTask:Ee,deciding:p,handleApprove:()=>{He({action:`APPROVED`,comment:null})},hasCurrentTask:q!==null,openAdhocModal:Q,openRejectModal:Ue,openReturnModal:Ge,openTransferModal:qe}),[De,Ee,q,p]);let $=V===`STAGE_NOTIFY`||V===`COMPLETION_NOTIFY`,it=$&&W===`WEBHOOK`?!K.trim():!F,at=Re.find(e=>e.id===ye)??Re[0],ot=Z.find(e=>e.id===W)??Z[0];return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`任務`}),h?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:h}):null,(0,s.jsx)(`div`,{style:Ne,children:(0,s.jsx)(o.Table,{columns:Ae,dataSource:ke,fullWidth:!0})}),Y.length>0?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.Typography,{component:`h3`,style:Pe,variant:`h3`,children:`待生效的臨時設定`}),(0,s.jsx)(`div`,{style:Ne,children:(0,s.jsx)(o.Table,{columns:Ve,dataSource:ze,fullWidth:!0})})]}):null,(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!Se,variant:`destructive-primary`},confirmText:`送出拒絕`,loading:p,modalStatusType:`error`,modalType:`standard`,onCancel:We,onClose:We,onConfirm:()=>void Xe(),open:y,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`拒絕案件時必須留下原因,供發起人與後續追蹤查看。`,title:`拒絕原因`,children:(0,s.jsxs)(`div`,{style:je,children:[(0,s.jsx)(r.t,{label:`拒絕原因`,name:`rejectReason`,required:!0,children:(0,s.jsx)(o.Textarea,{autoFocus:!0,onChange:e=>{_(e.target.value),v(null)},placeholder:`請說明拒絕原因`,ref:Fe,resize:`vertical`,rows:4,style:Me,type:te?`error`:`default`,value:ee})}),te?(0,s.jsx)(o.Typography,{color:`text-error`,variant:`body`,children:te}):null]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!T},confirmText:`送出轉派`,loading:p,modalType:`standard`,onCancel:Je,onClose:Je,onConfirm:()=>void Ze(),open:ue,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`轉派後,原任務會保留轉派紀錄,新的待簽任務會指派給指定成員。`,title:`轉派簽核`,children:(0,s.jsxs)(`div`,{style:X,children:[(0,s.jsx)(r.t,{label:`轉派對象`,name:`transferToMemberId`,required:!0,children:(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`transfer-member-search`,spellCheck:!1},loading:oe,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>E(pe(e)),onSearch:Ye,onSearchTextChange:e=>E(me(e,O)),onVisibilityChange:e=>{e&&Ye(``)},options:[...O],placeholder:`搜尋姓名或信箱`,searchDebounceTime:300,value:T})}),(0,s.jsx)(r.t,{label:`轉派說明`,name:`transferComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>w(e.target.value),placeholder:`可補充轉派原因`,ref:Fe,resize:`vertical`,rows:4,style:Me,value:ae})})]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:!Oe},confirmText:`送出退回`,loading:p,modalType:`standard`,onCancel:Ke,onClose:Ke,onConfirm:()=>void Qe(),open:x,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:`退回後,流程會回到指定節點並等待重新處理。`,title:`退回簽核`,children:(0,s.jsxs)(`div`,{style:X,children:[(0,s.jsx)(r.t,{label:`退回節點`,name:`returnTargetNodeId`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>C(e?.id??null),options:[...Te],placeholder:`選擇退回節點`,value:Oe})}),(0,s.jsx)(r.t,{label:`退回說明`,name:`returnComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>re(e.target.value),placeholder:`可補充需要修改的內容`,ref:Fe,resize:`vertical`,rows:4,style:Me,value:ne})})]})}),(0,s.jsx)(o.Modal,{cancelText:`取消`,confirmButtonProps:{disabled:it},confirmText:`送出`,loading:H,modalType:`standard`,onCancel:et,onClose:et,onConfirm:()=>void nt(),open:z,showModalFooter:!0,showModalHeader:!0,size:`regular`,supportingText:Le[V],title:Ie[V],children:(0,s.jsxs)(`div`,{style:X,children:[$?(0,s.jsx)(r.t,{label:`通知時機`,name:`adhocNotifyMode`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>ve(e?.id===`COMPLETION_NOTIFY`?`COMPLETION_NOTIFY`:`STAGE_NOTIFY`),options:[{id:`STAGE_NOTIFY`,name:Ie.STAGE_NOTIFY},{id:`COMPLETION_NOTIFY`,name:Ie.COMPLETION_NOTIFY}],value:{id:V,name:Ie[V]}})}):null,$?(0,s.jsx)(r.t,{label:`通知對象類型`,name:`adhocTargetKind`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>G(e?.id===`WEBHOOK`?`WEBHOOK`:`MEMBER`),options:[...Z],value:ot})}):null,$&&W===`WEBHOOK`?(0,s.jsx)(r.t,{label:`Webhook URL`,name:`adhocWebhookUrl`,required:!0,children:(0,s.jsx)(o.Input,{fullWidth:!0,onChange:e=>xe(e.target.value),placeholder:`https://example.com/webhook`,value:K})}):(0,s.jsx)(r.t,{label:$?`通知對象`:`簽核對象`,name:`adhocMemberId`,required:!0,children:(0,s.jsx)(o.AutoComplete,{asyncData:!0,disabledOptionsFilter:!0,emptyText:`沒有符合的成員`,inputProps:{autoCapitalize:`none`,autoCorrect:`off`,name:`adhoc-member-search`,spellCheck:!1},loading:ge,loadingText:`搜尋成員中...`,mode:`single`,onChange:e=>I(pe(e)),onSearch:tt,onSearchTextChange:e=>I(me(e,R)),onVisibilityChange:e=>{e&&tt(``)},options:[...R],placeholder:`搜尋姓名或信箱`,searchDebounceTime:300,value:F})}),V===`PRE_APPROVAL`?(0,s.jsx)(r.t,{label:`拒簽處理方式`,name:`adhocOnReject`,required:!0,children:(0,s.jsx)(o.Select,{clearable:!1,fullWidth:!0,onChange:e=>be(e?.id===`RETURN_TO_ORIGIN`?`RETURN_TO_ORIGIN`:`REJECT_INSTANCE`),options:[...Re],value:at})}):null,$?null:(0,s.jsx)(r.t,{label:`說明`,name:`adhocComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>he(e.target.value),placeholder:`可補充原因`,ref:Fe,resize:`vertical`,rows:3,style:Me,value:P})})]})})]})});function Be(e,t){try{let n=JSON.parse(e.targetValueJson);if(n.memberIds?.length)return n.memberIds.map(e=>j(e,t)).join(`、`);if(n.webhookUrl)return n.webhookUrl;if(n.positionId)return`職位 ${n.positionId}`;if(n.orgUnitId)return`部門 ${n.orgUnitId}`}catch{}return e.targetKind}var Ve={display:`grid`,gap:16};function He({signatureVerification:e,signatures:t}){let r=(0,a.useMemo)(()=>t.map(e=>({algorithm:e.algorithm,hashLabel:O(e.signedPayloadHash),key:e.id,keyVersion:e.keyVersion,signedAtLabel:n.t(e.signedAt),signerMemberId:e.signerMemberId})),[t]),i=(0,a.useMemo)(()=>[{dataIndex:`signerMemberId`,key:`signerMemberId`,title:`簽章者`,width:160},{dataIndex:`algorithm`,key:`algorithm`,title:`演算法`,width:150},{dataIndex:`keyVersion`,key:`keyVersion`,title:`Key 版本`,width:100},{dataIndex:`hashLabel`,key:`hashLabel`,title:`Payload Hash`,width:180},{dataIndex:`signedAtLabel`,key:`signedAtLabel`,title:`簽章時間`,width:220}],[]);return(0,s.jsxs)(`div`,{style:Ve,children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`簽章`}),(0,s.jsx)(o.Typography,{color:e?.valid?`text-success`:`text-error`,variant:`body`,children:e?e.valid?`簽章鏈已驗證,共 ${e.checkedCount} 筆。`:`簽章鏈驗證失敗:${e.errors.join(`、`)}`:`尚無簽章紀錄。`}),r.length>0?(0,s.jsx)(o.Table,{columns:i,dataSource:r,fullWidth:!0}):null]})}var Ue={display:`grid`,gap:16},We={cursor:`help`,textDecoration:`underline dotted`,textUnderlineOffset:3},Ge={color:`var(--mzn-color-text-error)`};function Ke(...e){return e.filter(e=>T(e??null)).join(` `)}var qe=(0,a.forwardRef)(function({className:e,descriptionParts:t,error:n,forcePending:r=!1,index:i=0,orientation:c,status:l=`pending`,title:u,type:d=`number`,...f},p){let m=r?`pending`:l;return(0,s.jsxs)(`div`,{...f,className:Ke(h.stepClasses.host,d===`dot`?h.stepClasses.dot:null,n&&m!==`processing`?h.stepClasses.error:null,c===`horizontal`?h.stepClasses.horizontal:null,d===`number`?h.stepClasses.number:null,m===`pending`?h.stepClasses.pending:null,m===`processing`?h.stepClasses.processing:null,n&&m===`processing`?h.stepClasses.processingError:null,!n&&m===`succeeded`?h.stepClasses.succeeded:null,c===`vertical`?h.stepClasses.vertical:null,e),ref:p,children:[d===`dot`?(0,s.jsx)(`span`,{className:Ke(h.stepClasses.statusIndicator,h.stepClasses.statusIndicatorDot)}):(0,s.jsx)(`span`,{className:h.stepClasses.statusIndicator,children:i+1}),(0,s.jsxs)(`div`,{className:h.stepClasses.textContainer,children:[(0,s.jsxs)(o.Typography,{className:h.stepClasses.title,variant:`label-primary-highlight`,children:[u,(0,s.jsx)(`span`,{className:h.stepClasses.titleConnectLine})]}),t.length>0?(0,s.jsx)(o.Typography,{className:h.stepClasses.description,variant:`caption`,children:t.map((e,t)=>(0,s.jsxs)(a.Fragment,{children:[t>0?` · `:null,Je(e)]},`${e.type}-${t}`))}):null]})]})});function Je(e){return e.type===`text`?e.text:e.type===`dangerText`?(0,s.jsx)(`span`,{style:Ge,children:e.text}):e.email?(0,s.jsxs)(s.Fragment,{children:[e.prefix,`:`,(0,s.jsx)(o.Tooltip,{title:e.email,children:({onMouseEnter:t,onMouseLeave:n,ref:r})=>(0,s.jsx)(`span`,{"data-testid":e.memberId?`member-tooltip-${e.memberId}`:void 0,onMouseEnter:t,onMouseLeave:n,ref:r,style:We,children:e.label})})]}):`${e.prefix}:${e.label}`}function Ye({activityLogs:e,instanceState:t,memberProfilesById:n,signatureVerification:r,signaturesById:i,taskDecisionsByTaskId:a,tasks:c,workflowSnapshot:l,workflowTokens:u}){let d=Ce(e,c,u,l,t,n,a,i,r),f=ge(d),p=d.map(e=>({...e,descriptionParts:e.descriptionParts.filter(I)}));return(0,s.jsxs)(`div`,{style:Ue,children:[(0,s.jsx)(o.Typography,{component:`h2`,variant:`h3`,children:`歷程`}),p.length>0?(0,s.jsx)(o.Stepper,{currentStep:f,orientation:`vertical`,type:`dot`,children:p.map(e=>(0,s.jsx)(qe,{descriptionParts:e.descriptionParts,error:e.error,forcePending:e.forcePending,title:e.title},e.id))}):(0,s.jsx)(o.Typography,{color:`text-neutral`,variant:`body`,children:`尚無歷程紀錄。`})]})}var Xe=184,Ze=96,Qe={display:`grid`,gap:16},$e={background:`#f8fafc`,border:`1px solid #e2e8f0`,borderRadius:8,height:`min(64vh, 620px)`,minHeight:440,overflow:`hidden`,width:`min(80vw, 1040px)`},Q={background:`#ffffff`,border:`1px solid #cbd5e1`,borderRadius:8,boxShadow:`0 8px 18px rgba(15, 23, 42, 0.08)`,display:`grid`,gap:6,minHeight:82,padding:12,width:184},et={borderRadius:999,fontSize:12,fontWeight:600,justifySelf:`start`,lineHeight:`18px`,padding:`0 8px`},tt={color:`#64748b`,fontSize:12,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},nt={opacity:0},rt={display:`flex`,flexWrap:`wrap`,gap:8},$={alignItems:`center`,background:`#ffffff`,border:`1px solid #cbd5e1`,borderRadius:8,color:`#334155`,display:`inline-flex`,fontSize:12,fontWeight:600,gap:6,lineHeight:`20px`,padding:`4px 8px`},it={display:`grid`,gap:16},at={workflowRuntime:ht};function ot({instanceId:e,showAttachments:i=!0,showForm:p=!0,showHistory:m=!0,showSignatures:h=!0,showTasks:g=!0}){let{member:ee}=t.n(),_=ee?.memberId??null,[te,v]=(0,a.useState)([]),[y,b]=(0,a.useState)(null),[ne,x]=(0,a.useState)([]),[S,ie]=(0,a.useState)([]),[C,ae]=(0,a.useState)([]),[w,T]=(0,a.useState)(null),[E,oe]=(0,a.useState)([]),[se,O]=(0,a.useState)([]),[le,ue]=(0,a.useState)([]),[k,A]=(0,a.useState)(null),[j,M]=(0,a.useState)(!0),[fe,N]=(0,a.useState)(!1),[pe,me]=(0,a.useState)(!1),[P,he]=(0,a.useState)(``),[F,I]=(0,a.useState)(!1),[ge,L]=(0,a.useState)({}),[R,_e]=(0,a.useState)({}),[z,B]=(0,a.useState)(null),[V,ve]=(0,a.useState)(null),[ye,be]=(0,a.useState)([]),H=P.trim(),U=(0,a.useRef)(null);(0,a.useEffect)(()=>{X()},[_,e]),(0,a.useEffect)(()=>{_e(y?.formData??{})},[y]);let W=(0,a.useMemo)(()=>E.find(e=>de(e,_)&&(e.status===`PENDING`||e.status===`IN_PROGRESS`))??null,[_,E]),G=(0,a.useMemo)(()=>W&&y?y.workflowSnapshot.nodes.find(e=>e.id===W.nodeId)??null:null,[W,y]),K=G?.type===`userTask`&&G.data.returnBehavior.allowReturn,xe=G?.type===`userTask`&&G.data.allowAddSigner,Se=!!(y&&y.initiatorMemberId===_&&(y.state===`RUNNING`||y.state===`RETURNED`)),Ce=!!(y&&y.initiatorMemberId===_&&y.state===`RETURNED`),we=(0,a.useMemo)(()=>new Map(le.map(e=>[e.memberId,e])),[le]),J=(0,a.useMemo)(()=>Ee(ne),[ne]),De=(0,a.useMemo)(()=>new Map(C.map(e=>[e.id,e])),[C]),Y=(0,a.useMemo)(()=>y?dt(y.workflowSnapshot):null,[y]),ke=(0,a.useMemo)(()=>y&&Y?ut(Y,E,se,y.state):[],[y,Y,E,se]),je=(0,a.useMemo)(()=>Y?ft(Y):[],[Y]),Me=(0,a.useMemo)(()=>y?ct(y.workflowSnapshot):[],[y]);async function X(){M(!0),A(null);try{let t=await(0,c.readApprovalInstance)(e);v(t.activityLogs),b(t.instance),oe(t.tasks),O(t.workflowTokens);let n=await(0,c.listAdhocDirectives)(t.instance.id),[r,i,a,o]=await Promise.all([Te(t.tasks),q({...t,adhocDirectives:n}),(0,c.listAttachments)(t.instance.id),(0,c.readInstanceSignatures)(t.instance.id)]);x(r),ue(i),ie(a),ae(o.signatures),T(o.verification),be(n)}catch(e){A(D(e))}finally{M(!1)}}async function Ne(e,t){if(!_)throw Error(`尚未登入,無法上傳附件`);return{id:(await(0,c.uploadAttachment)({file:t,formFieldPath:`form.${e.fieldKey}`})).id}}async function Pe(e){if(!_)return;let t=await(0,c.readAttachmentDownloadUrl)({id:e.id});window.open(t,`_blank`,`noopener,noreferrer`)}async function Fe(e){if(!_)return;let t=await(0,c.readAttachmentPreviewUrl)({id:e.id});B(e),ve(t)}async function Ie(){if(!(!_||!y||!Se)){if(N(!0),A(null),L({}),y.formDefinitionSnapshot.schema&&y.formDefinitionSnapshot.uiSchema){let e=(0,d.validateFormRendererValues)({schema:y.formDefinitionSnapshot.schema,uiSchema:y.formDefinitionSnapshot.uiSchema,values:R});if(!e.valid){L(e.errors),A(`請先補齊必填欄位。`),e.firstInvalidFieldKey&&(0,d.focusFormRendererField)(e.firstInvalidFieldKey),N(!1);return}}try{await(0,c.cancelApprovalInstance)({cancelledByMemberId:_,comment:H||null,instanceId:y.id}),he(``),I(!1),await X()}catch(e){A(D(e))}finally{N(!1)}}}async function Le(){if(!(!_||!y||!Ce)){N(!0),A(null);try{await(0,c.resubmitApprovalInstance)({formData:R,initiatorMemberId:_,instanceId:y.id,title:y.title}),await X()}catch(e){A(D(e))}finally{N(!1)}}}let Re=U.current?.deciding??!1,Z=fe||Re;return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.PageHeader,{children:(0,s.jsxs)(l.default,{description:y?`${ce(y.state)} · ${n.t(y.startedAt)}`:`載入案件內容。`,title:y?.title??`簽核案件`,children:[y?(0,s.jsx)(o.Button,{"aria-label":`查看流程圖`,icon:u.ShareIcon,iconType:`icon-only`,onClick:()=>me(!0),title:`查看流程圖`,variant:`base-secondary`,children:`流程圖`}):null,Se?(0,s.jsx)(o.Button,{disabled:Z,icon:u.DangerousOutlineIcon,iconType:`leading`,onClick:()=>I(!0),variant:`destructive-secondary`,children:`取消案件`}):null,W?(0,s.jsxs)(s.Fragment,{children:[xe?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.Button,{disabled:Z,icon:u.PlusIcon,iconType:`leading`,onClick:()=>U.current?.openAdhocModal(`COUNTERSIGN`),variant:`base-secondary`,children:`會簽`},`adhoc-countersign`),(0,s.jsx)(o.Button,{disabled:Z,icon:u.PlusIcon,iconType:`leading`,onClick:()=>U.current?.openAdhocModal(`PRE_APPROVAL`),variant:`base-secondary`,children:`加簽`},`adhoc-pre-approval`)]}):null,(0,s.jsx)(o.Button,{disabled:Z,icon:u.NotificationUnreadIcon,iconType:`leading`,onClick:()=>U.current?.openAdhocModal(`STAGE_NOTIFY`),variant:`base-secondary`,children:`通知設定`},`adhoc-notify`),K?(0,s.jsx)(o.Button,{disabled:Z,icon:u.RefreshCcwIcon,iconType:`leading`,onClick:()=>U.current?.openReturnModal(),variant:`base-secondary`,children:`退回`},`task-return`):null,(0,s.jsx)(o.Button,{disabled:Z,icon:u.UserIcon,iconType:`leading`,onClick:()=>U.current?.openTransferModal(),variant:`base-secondary`,children:`轉派`},`task-transfer`),(0,s.jsx)(o.Button,{disabled:Z,icon:u.DangerousOutlineIcon,iconType:`leading`,onClick:()=>U.current?.openRejectModal(),variant:`destructive-secondary`,children:`拒絕`},`task-reject`),(0,s.jsx)(o.Button,{disabled:Z,icon:u.CheckedIcon,iconType:`leading`,onClick:()=>U.current?.handleApprove(),variant:`base-primary`,children:`同意`},`task-approve`)]}):null]})}),(0,s.jsxs)(o.SectionGroup,{children:[p?(0,s.jsx)(o.Section,{children:(0,s.jsx)(Oe,{canResubmitInstance:Ce,deciding:fe,error:k,instance:y,loading:j,onResubmitFormChange:e=>{_e(e),L({})},onResubmitInstance:()=>void Le(),onUploadAttachment:Ne,resubmitFormData:R,resubmitFormErrors:ge})}):null,i?(0,s.jsx)(o.Section,{children:(0,s.jsx)(Ae,{attachments:S,onDownload:e=>{Pe(e)},onPreview:e=>{Fe(e)}})}):null,g?(0,s.jsx)(o.Section,{children:(0,s.jsx)(ze,{adhocDirectives:ye,currentMemberId:_,instance:y,memberProfilesById:we,onChanged:X,ref:U,tasks:E})}):null,h?(0,s.jsx)(o.Section,{children:(0,s.jsx)(He,{signatureVerification:w,signatures:C})}):null,m?(0,s.jsx)(o.Section,{children:(0,s.jsx)(Ye,{activityLogs:te,instanceState:y?.state??`RUNNING`,memberProfilesById:we,signatureVerification:w,signaturesById:De,taskDecisionsByTaskId:J,tasks:E,workflowSnapshot:y?.workflowSnapshot??null,workflowTokens:se})}):null]}),y?(0,s.jsx)(o.Modal,{modalType:`standard`,onClose:()=>me(!1),open:pe,showModalHeader:!0,size:`wide`,supportingText:`${ce(y.state)} · ${n.t(y.startedAt)}`,title:`流程圖`,children:(0,s.jsxs)(`div`,{style:Qe,children:[(0,s.jsx)(`div`,{style:$e,children:(0,s.jsxs)(f.ReactFlow,{edges:je,fitView:!0,fitViewOptions:{padding:.18},maxZoom:1.2,minZoom:.2,nodes:ke,nodesDraggable:!1,nodesFocusable:!1,nodeTypes:at,panOnDrag:!0,proOptions:{hideAttribution:!0},children:[(0,s.jsx)(f.Background,{}),(0,s.jsx)(f.Controls,{showInteractive:!1})]})}),Me.length>0?(0,s.jsx)(`div`,{style:rt,children:Me.map(e=>(0,s.jsx)(`span`,{style:$,children:e},e))}):null]})}):null,(0,s.jsx)(o.Modal,{modalType:`standard`,onClose:()=>{B(null),ve(null)},open:!!(z&&V),showModalHeader:!0,size:`wide`,supportingText:z?.filename??void 0,title:`PDF 預覽`,children:V?(0,s.jsx)(re,{filename:z?.filename??`PDF 預覽`,fileUrl:V,onDownload:z?()=>void Pe(z):void 0}):null}),(0,s.jsx)(o.Modal,{cancelText:`保留案件`,confirmButtonProps:{variant:`destructive-primary`},confirmText:`確認取消`,loading:fe,modalStatusType:`error`,modalType:`standard`,onCancel:()=>I(!1),onClose:()=>I(!1),onConfirm:()=>void Ie(),open:F,showModalFooter:!0,showModalHeader:!0,supportingText:`取消後會關閉目前待簽任務與候選簽核人。`,title:`取消案件`,children:(0,s.jsxs)(`div`,{style:it,children:[(0,s.jsxs)(o.Typography,{variant:`body`,children:[`確定要取消「`,y?.title??``,`」嗎?`]}),(0,s.jsx)(r.t,{label:`取消原因`,name:`cancelComment`,children:(0,s.jsx)(o.Textarea,{onChange:e=>he(e.target.value),placeholder:`可填寫取消原因`,resize:`vertical`,rows:3,value:P})})]})})]})}function st(e){return e.data.label?e.data.label:e.data.isDefault?`其他情況`:e.data.condition??``}function ct(e){return e.edges.map(st).filter(e=>e.trim().length>0)}function lt(e){return e===`startEvent`?`開始`:e===`endEvent`?`完成`:e===`userTask`?`簽核節點`:e===`serviceTask`?`知會節點`:e===`exclusiveGateway`?`條件分流`:`平行處理`}function ut(e,t,n,r){return e.nodes.map(e=>{let i=we(e,t,n,r);return{data:{kindLabel:lt(e.type),label:e.data.label,secondaryLabel:i.secondaryLabel,statusLabel:i.statusLabel,tone:i.tone},id:e.id,position:e.position,sourcePosition:f.Position.Right,targetPosition:f.Position.Left,type:`workflowRuntime`}})}function dt(e){let t=new p.graphlib.Graph;return t.setDefaultEdgeLabel(()=>({})),t.setGraph({nodesep:56,rankdir:`LR`,ranksep:120}),e.nodes.forEach(e=>{t.setNode(e.id,{height:Ze,width:Xe})}),e.edges.forEach(e=>{t.setEdge(e.source,e.target)}),p.layout(t),{...e,nodes:e.nodes.map(e=>{let n=t.node(e.id);return n?{...e,position:{x:n.x-Xe/2,y:n.y-Ze/2}}:e})}}function ft(e){return e.edges.map(e=>{let t=st(e);return{animated:!1,id:e.id,label:t,labelBgBorderRadius:6,labelBgPadding:[8,4],labelBgStyle:{fill:e.data.isDefault?`#f8fafc`:`#eff6ff`,stroke:e.data.isDefault?`#64748b`:`#2563eb`,strokeWidth:1},labelShowBg:!!t,labelStyle:{fill:e.data.isDefault?`#475569`:`#2563eb`,fontSize:12,fontWeight:600},source:e.source,style:{stroke:`#475569`,strokeWidth:1.5},target:e.target,type:e.type??`smoothstep`}})}function pt(e){return e===`current`?{...Q,border:`1px solid var(--mzn-color-primary, #0057ff)`,boxShadow:`0 0 0 3px rgba(0, 87, 255, 0.14)`}:e===`completed`?{...Q,border:`1px solid #16a34a`}:e===`cancelled`?{...Q,border:`1px solid #dc2626`,opacity:.72}:e===`waiting`?{...Q,border:`1px dashed #64748b`}:Q}function mt(e){let t=et;return e===`current`?{...t,background:`#eff6ff`,color:`#2563eb`}:e===`completed`?{...t,background:`#f0fdf4`,color:`#15803d`}:e===`cancelled`?{...t,background:`#fef2f2`,color:`#dc2626`}:e===`waiting`?{...t,background:`#f8fafc`,color:`#475569`}:{...t,background:`#f1f5f9`,color:`#64748b`}}function ht({data:e}){return(0,s.jsxs)(`div`,{style:pt(e.tone),children:[(0,s.jsx)(f.Handle,{isConnectable:!1,position:f.Position.Left,style:nt,type:`target`}),(0,s.jsx)(o.Typography,{component:`span`,ellipsis:!0,title:e.label,variant:`label-primary`,children:e.label}),(0,s.jsx)(`span`,{style:mt(e.tone),children:e.statusLabel}),(0,s.jsx)(`span`,{title:e.secondaryLabel,style:tt,children:e.secondaryLabel||e.kindLabel}),(0,s.jsx)(f.Handle,{isConnectable:!1,position:f.Position.Right,style:nt,type:`source`})]})}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return Ae}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return ze}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return Ye}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return Oe}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return He}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return ot}});
|
|
2
|
+
//# sourceMappingURL=detail-Cci9tnoC.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detail-Cci9tnoC.cjs","names":[],"sources":["../../src/components/pdf-preview.module.scss","../../src/components/pdf-preview.tsx","../../src/views/instances/detail/sections/shared.ts","../../src/views/instances/detail/sections/container-helpers.ts","../../src/views/instances/detail/sections/InstanceFormSection.tsx","../../src/views/instances/detail/sections/InstanceAttachmentsSection.tsx","../../src/views/instances/detail/sections/InstanceTasksSection.tsx","../../src/views/instances/detail/sections/InstanceSignaturesSection.tsx","../../src/views/instances/detail/sections/InstanceHistorySection.tsx","../../src/views/instances/detail/InstanceDetailView.tsx"],"sourcesContent":[".root {\n display: grid;\n gap: 12px;\n width: min(86vw, 1080px);\n}\n\n.toolbar {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: space-between;\n}\n\n.pageControls,\n.zoomControls {\n align-items: center;\n display: flex;\n gap: 8px;\n}\n\n.counter {\n min-width: 92px;\n text-align: center;\n white-space: nowrap;\n}\n\n.viewport {\n align-items: flex-start;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n display: flex;\n height: min(72vh, 760px);\n justify-content: center;\n min-height: 420px;\n overflow: auto;\n padding: 16px;\n}\n\n.page {\n background: #ffffff;\n box-shadow: 0 12px 32px rgb(15 23 42 / 14%);\n color: #111827;\n}\n\n.state {\n align-items: center;\n display: flex;\n justify-content: center;\n min-height: 320px;\n width: 100%;\n}\n\n@media (max-width: 720px) {\n .root {\n width: 92vw;\n }\n\n .toolbar {\n align-items: stretch;\n display: grid;\n }\n\n .pageControls,\n .zoomControls {\n justify-content: space-between;\n }\n\n .counter {\n min-width: 84px;\n }\n\n .viewport {\n height: 68vh;\n min-height: 360px;\n padding: 12px;\n }\n}\n","'use client';\n\nimport {\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Button, Typography } from '@mezzanine-ui/react';\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n DownloadIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@mezzanine-ui/icons';\nimport { Document, Page, pdfjs } from 'react-pdf';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport styles from './pdf-preview.module.scss';\n\n// pdfjs ships its worker as a separate chunk. Consumers should call\n// `configurePdfWorker(url)` (or set `pdfjs.GlobalWorkerOptions.workerSrc`\n// directly) before the first `<PDFPreview>` mounts. The library does not\n// hard-bundle a worker path because consumer bundlers may need to resolve\n// it through CDN, public/ asset pipeline, or pinned version.\nexport function configurePdfWorker(workerSrc: string): void {\n pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;\n}\n\nconst DEFAULT_VIEWPORT_WIDTH = 760;\nconst MAX_PAGE_WIDTH = 920;\nconst MIN_PAGE_WIDTH = 320;\nconst PAGE_HORIZONTAL_PADDING = 32;\nconst MIN_SCALE = 0.75;\nconst MAX_SCALE = 1.75;\nconst SCALE_STEP = 0.25;\n\nexport interface PDFPreviewProps {\n readonly filename: string;\n readonly fileUrl: string;\n readonly onDownload?: () => void;\n}\n\n/**\n * Mezzanine-styled PDF preview powered by `react-pdf`. Used by the instance\n * detail view to preview PDF attachments inline.\n */\nexport function PDFPreview({\n filename,\n fileUrl,\n onDownload,\n}: PDFPreviewProps): ReactElement {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const [numPages, setNumPages] = useState<number | null>(null);\n const [pageNumber, setPageNumber] = useState(1);\n const [scale, setScale] = useState(1);\n const [viewportWidth, setViewportWidth] = useState(DEFAULT_VIEWPORT_WIDTH);\n\n useEffect((): (() => void) | undefined => {\n const viewport = viewportRef.current;\n\n if (!viewport || typeof ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const observer = new ResizeObserver((entries): void => {\n const nextWidth = entries[0]?.contentRect.width;\n\n if (nextWidth) {\n setViewportWidth(nextWidth);\n }\n });\n\n observer.observe(viewport);\n\n return (): void => observer.disconnect();\n }, []);\n\n useEffect((): void => {\n setNumPages(null);\n setPageNumber(1);\n setScale(1);\n }, [fileUrl]);\n\n const pageWidth = useMemo((): number => {\n const availableWidth = Math.max(\n MIN_PAGE_WIDTH,\n viewportWidth - PAGE_HORIZONTAL_PADDING,\n );\n const baseWidth = Math.min(MAX_PAGE_WIDTH, availableWidth);\n\n return Math.round(baseWidth * scale);\n }, [scale, viewportWidth]);\n\n const loadDocument = useCallback((document: PDFDocumentProxy): void => {\n setNumPages(document.numPages);\n setPageNumber(1);\n }, []);\n\n const hasPreviousPage = pageNumber > 1;\n const hasNextPage = numPages !== null && pageNumber < numPages;\n const canZoomOut = scale > MIN_SCALE;\n const canZoomIn = scale < MAX_SCALE;\n const pageLabel =\n numPages === null\n ? `第 ${pageNumber} 頁`\n : `第 ${pageNumber} / ${numPages} 頁`;\n const zoomLabel = `${Math.round(scale * 100)}%`;\n\n return (\n <section aria-label={`${filename} PDF 預覽`} className={styles.root}>\n <div className={styles.toolbar}>\n <div className={styles.pageControls} aria-label=\"頁面切換\">\n <Button\n aria-label=\"上一頁\"\n disabled={!hasPreviousPage}\n icon={ChevronLeftIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n Math.max(1, currentPageNumber - 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {pageLabel}\n </Typography>\n <Button\n aria-label=\"下一頁\"\n disabled={!hasNextPage}\n icon={ChevronRightIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n numPages === null\n ? currentPageNumber\n : Math.min(numPages, currentPageNumber + 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n <div className={styles.zoomControls} aria-label=\"縮放\">\n <Button\n aria-label=\"縮小\"\n disabled={!canZoomOut}\n icon={ZoomOutIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.max(MIN_SCALE, currentScale - SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {zoomLabel}\n </Typography>\n <Button\n aria-label=\"放大\"\n disabled={!canZoomIn}\n icon={ZoomInIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.min(MAX_SCALE, currentScale + SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n {onDownload ? (\n <Button\n icon={DownloadIcon}\n iconType=\"leading\"\n onClick={onDownload}\n size=\"minor\"\n variant=\"base-primary\"\n >\n 下載\n </Button>\n ) : null}\n </div>\n <div className={styles.viewport} ref={viewportRef}>\n <Document\n error={<PDFPreviewState message=\"PDF 無法載入。\" />}\n file={fileUrl}\n loading={<PDFPreviewState message=\"正在載入 PDF...\" />}\n noData={<PDFPreviewState message=\"沒有可預覽的 PDF。\" />}\n onLoadSuccess={loadDocument}\n >\n <Page\n className={styles.page}\n loading={<PDFPreviewState message=\"正在載入頁面...\" />}\n pageNumber={pageNumber}\n renderAnnotationLayer\n renderTextLayer\n width={pageWidth}\n />\n </Document>\n </div>\n </section>\n );\n}\n\nfunction PDFPreviewState({\n message,\n}: {\n readonly message: string;\n}): ReactElement {\n return (\n <div className={styles.state}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {message}\n </Typography>\n </div>\n );\n}\n","/**\n * Shared types, helpers, and label functions used across\n * InstanceDetailView section components.\n */\n\nimport {\n ActivityLogRecord,\n ApprovalInstanceRecord,\n AttachmentRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowTokenRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { WorkflowDefinition, WorkflowNode } from '@rytass/bpm-core-shared/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\n\n// ---------------------------------------------------------------------------\n// Row types\n// ---------------------------------------------------------------------------\n\nexport type TaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n assigneeLabel: string;\n key: string;\n nodeLabel: string;\n statusLabel: string;\n }\n>;\n\nexport type AttachmentRow = Readonly<\n Record<string, unknown> & {\n attachment: AttachmentRecord;\n createdAt: string;\n filename: string;\n id: string;\n key: string;\n mimeType: string;\n sizeLabel: string;\n }\n>;\n\nexport type SignatureRow = Readonly<\n Record<string, unknown> & {\n algorithm: string;\n hashLabel: string;\n key: string;\n keyVersion: number;\n signedAtLabel: string;\n signerMemberId: string;\n }\n>;\n\nexport type MemberOption = Readonly<{\n email: string | null;\n id: string;\n name: string;\n}>;\n\n// ---------------------------------------------------------------------------\n// Activity step types (used by InstanceHistorySection)\n// ---------------------------------------------------------------------------\n\nexport type ActivityStepDescriptionPart =\n | Readonly<{ text: string; type: 'text' }>\n | Readonly<{ text: string; type: 'dangerText' }>\n | Readonly<{\n email: string | null;\n label: string;\n memberId: string | null;\n prefix: string;\n type: 'member';\n }>;\n\nexport interface ActivityStepRecord {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly error: boolean;\n readonly forcePending?: boolean;\n readonly id: string;\n readonly title: string;\n}\n\n// ---------------------------------------------------------------------------\n// Delegation chain\n// ---------------------------------------------------------------------------\n\ninterface DelegationChainStep {\n readonly from: string;\n readonly reason: string;\n readonly ruleId: string | null;\n readonly to: string;\n}\n\nfunction readDelegationChainStep(\n item: Readonly<Record<string, unknown>>,\n): DelegationChainStep | null {\n const from = readStringField(item, 'from');\n const to = readStringField(item, 'to');\n const reason = readStringField(item, 'reason');\n\n if (!from || !to || !reason) {\n return null;\n }\n\n return {\n from,\n reason,\n ruleId: readStringField(item, 'ruleId'),\n to,\n };\n}\n\nexport function readDelegationChain(value: string): readonly DelegationChainStep[] {\n try {\n const parsed = JSON.parse(value) as unknown;\n\n return Array.isArray(parsed)\n ? parsed\n .map((item): DelegationChainStep | null =>\n isRecord(item) ? readDelegationChainStep(item) : null,\n )\n .filter((item): item is DelegationChainStep => item !== null)\n : [];\n } catch {\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generic field readers\n// ---------------------------------------------------------------------------\n\nexport function readStringField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): string | null {\n const value = record[key];\n\n return typeof value === 'string' ? value : null;\n}\n\nexport function readStringArrayField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): readonly string[] {\n const value = record[key];\n\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nexport function readNumberField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): number | null {\n const value = record[key];\n\n return typeof value === 'number' ? value : null;\n}\n\n// ---------------------------------------------------------------------------\n// Type guards / predicates\n// ---------------------------------------------------------------------------\n\nexport function isPresentText(value: string | null): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nexport function isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function isPendingTask(task: TaskRecord): boolean {\n return task.status === 'PENDING' || task.status === 'IN_PROGRESS';\n}\n\n// ---------------------------------------------------------------------------\n// Label helpers\n// ---------------------------------------------------------------------------\n\nexport function readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nexport function formatFileSize(sizeBytes: number): string {\n if (!Number.isFinite(sizeBytes) || sizeBytes <= 0) {\n return '-';\n }\n\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n if (sizeBytes < 1024 * 1024) {\n return `${(sizeBytes / 1024).toFixed(1)} KB`;\n }\n\n return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\nexport function readShortHash(hash: string): string {\n return hash.length > 16 ? `${hash.slice(0, 12)}...` : hash;\n}\n\nexport function readInstanceStateLabel(state: string): string {\n if (state === 'APPROVED') return '已同意';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'DRAFT') return '草稿';\n if (state === 'EXPIRED') return '已逾期';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'RUNNING') return '進行中';\n\n return state;\n}\n\nexport function readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') return '待處理';\n if (status === 'IN_PROGRESS') return '處理中';\n if (status === 'COMPLETED') return '已完成';\n if (status === 'CANCELLED') return '已取消';\n if (status === 'TRANSFERRED') return '已轉派';\n\n return status;\n}\n\nexport function readTaskDecisionActionLabel(action: string): string {\n if (action === 'APPROVED') return '同意';\n if (action === 'REJECTED') return '拒絕';\n if (action === 'RETURNED') return '退回';\n if (action === 'TRANSFERRED') return '轉派';\n\n return action;\n}\n\nexport function readNodeKindLabel(type: WorkflowNode['type']): string {\n if (type === 'startEvent') return '開始';\n if (type === 'endEvent') return '完成';\n if (type === 'userTask') return '簽核節點';\n if (type === 'serviceTask') return '知會節點';\n if (type === 'exclusiveGateway') return '條件分流';\n\n return '平行處理';\n}\n\nexport function readNodeDisplayLabel(\n nodeId: string,\n workflow: WorkflowDefinition | null,\n): string {\n return (\n workflow?.nodes.find((node) => node.id === nodeId)?.data.label ?? nodeId\n );\n}\n\nexport function readMemberDisplayText(\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n if (!memberId) {\n return '-';\n }\n\n const profile = memberProfilesById.get(memberId);\n\n return profile ? `${profile.name}(${profile.email})` : memberId;\n}\n\nexport function readTaskAssigneeLabel(\n task: TaskRecord,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord> = new Map(),\n): string {\n const delegationChain = readDelegationChain(task.delegationChainJson);\n\n if (!task.assigneeMemberId) {\n return task.candidateMemberIds.length\n ? `候選 ${task.candidateMemberIds\n .map((memberId) => readMemberDisplayText(memberId, memberProfilesById))\n .join('、')}`\n : '未指定';\n }\n\n const assigneeLabel = readMemberDisplayText(\n task.assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n task.originalAssigneeMemberId,\n memberProfilesById,\n );\n\n if (\n delegationChain.length === 0 ||\n task.originalAssigneeMemberId === task.assigneeMemberId\n ) {\n return assigneeLabel;\n }\n\n return `${assigneeLabel}(原:${originalAssigneeLabel})`;\n}\n\nexport function canMemberActOnTask(\n task: TaskRecord,\n memberId: string | null,\n): boolean {\n if (!memberId) {\n return false;\n }\n\n return (\n task.assigneeMemberId === memberId ||\n task.candidateMemberIds.includes(memberId)\n );\n}\n\nexport function readReturnTargetOptions(\n workflow: WorkflowDefinition,\n node: WorkflowNode,\n): readonly { readonly id: string; readonly name: string }[] {\n if (node.type !== 'userTask' || !node.data.returnBehavior.allowReturn) {\n return [];\n }\n\n if (node.data.returnBehavior.allowedTargets === 'ANY') {\n return workflow.nodes\n .filter((candidate) => candidate.id !== node.id)\n .map((candidate) => ({\n id: candidate.id,\n name: `${candidate.data.label}(${readNodeKindLabel(candidate.type)})`,\n }));\n }\n\n const targetNodeId =\n node.data.returnBehavior.allowedTargets === 'INITIATOR'\n ? workflow.nodes.find((candidate) => candidate.type === 'startEvent')?.id\n : workflow.edges.find((edge) => edge.target === node.id)?.source;\n const targetNode = workflow.nodes.find(\n (candidate) => candidate.id === targetNodeId,\n );\n\n return targetNode\n ? [\n {\n id: targetNode.id,\n name: `${targetNode.data.label}(${readNodeKindLabel(targetNode.type)})`,\n },\n ]\n : [];\n}\n\nexport function readMemberOption(profile: MemberProfileRecord): MemberOption {\n return {\n email: profile.email,\n id: profile.memberId,\n name: `${profile.name} · ${profile.email}`,\n };\n}\n\nexport function readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const email = value.email;\n const id = value.id;\n const name = value.name;\n\n return typeof id === 'string' && typeof name === 'string'\n ? { email: typeof email === 'string' ? email : null, id, name }\n : null;\n}\n\nexport function readUniqueMemberOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalizedSearchText = searchText.trim().toLocaleLowerCase();\n\n if (!normalizedSearchText) {\n return null;\n }\n\n const matches = options.filter((option) =>\n [option.id, option.name, option.email ?? ''].some((value) =>\n value.toLocaleLowerCase().includes(normalizedSearchText),\n ),\n );\n\n return matches.length === 1 ? (matches[0] ?? null) : null;\n}\n\n// ---------------------------------------------------------------------------\n// Activity step helpers\n// ---------------------------------------------------------------------------\n\nexport function readTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'text' } : null;\n}\n\nexport function readDangerTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'dangerText' } : null;\n}\n\nexport function readMemberDescriptionPart(\n prefix: string,\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n fallbackLabel: string,\n): ActivityStepDescriptionPart {\n const profile = memberId ? memberProfilesById.get(memberId) : null;\n\n return {\n email: profile?.email ?? null,\n label: profile?.name ?? fallbackLabel,\n memberId,\n prefix,\n type: 'member',\n };\n}\n\nexport function isActivityDescriptionPart(\n part: ActivityStepDescriptionPart | null,\n): part is ActivityStepDescriptionPart {\n return Boolean(part);\n}\n\nexport function readCurrentActivityStep(\n activitySteps: readonly ActivityStepRecord[],\n): number {\n const firstPendingStepIndex = activitySteps.findIndex(\n (activityStep) =>\n activityStep.id.startsWith('pending-task-') ||\n activityStep.id.startsWith('future-node-'),\n );\n\n return firstPendingStepIndex === -1\n ? activitySteps.length\n : firstPendingStepIndex;\n}\n\nexport function isUserMeaningfulActivity(activityLog: ActivityLogRecord): boolean {\n return (\n activityLog.eventType === 'INSTANCE_STARTED' ||\n activityLog.eventType === 'TASK_DECIDED' ||\n activityLog.eventType === 'SLA_TRIGGERED'\n );\n}\n\nfunction readTaskDecisionEventLabel(action: string | null): string {\n if (action === 'APPROVED') return '已同意';\n if (action === 'REJECTED') return '已拒絕';\n if (action === 'RETURNED') return '已退回';\n if (action === 'TRANSFERRED') return '已轉派';\n\n return '簽核已決議';\n}\n\nexport function readActivityEventLabel(\n eventType: string,\n payload: Readonly<Record<string, unknown>>,\n): string {\n if (eventType === 'INSTANCE_STARTED') return '案件已發起';\n if (eventType === 'TOKEN_CREATED') return '流程路徑已建立';\n if (eventType === 'ENGINE_PROCESS_REQUESTED') return '流程引擎已處理';\n if (eventType === 'TOKEN_ADVANCED') return '流程已前進';\n if (eventType === 'TASK_CREATED') return '待簽任務已建立';\n if (eventType === 'TASK_DECIDED') {\n return readTaskDecisionEventLabel(readStringField(payload, 'action'));\n }\n if (eventType === 'SLA_TRIGGERED') return '時限提醒已觸發';\n\n return eventType;\n}\n\nexport function readActivityPayload(\n activityLog: ActivityLogRecord,\n): Readonly<Record<string, unknown>> {\n try {\n const payload = JSON.parse(activityLog.payloadJson) as unknown;\n\n return isRecord(payload) ? payload : {};\n } catch {\n return {};\n }\n}\n\nexport function isActivityError(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n): boolean {\n return (\n activityLog.eventType === 'SLA_TRIGGERED' ||\n readStringField(payload, 'action') === 'REJECTED' ||\n readStringField(payload, 'instanceState') === 'REJECTED'\n );\n}\n\nexport function formatActivityDateTime(value: string): string {\n return formatDateTime(value);\n}\n\nfunction readActivityDetail(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string | null {\n if (activityLog.eventType === 'TASK_CREATED') {\n const assigneeMemberId = readStringField(payload, 'assigneeMemberId');\n const originalAssigneeMemberId = readStringField(\n payload,\n 'originalAssigneeMemberId',\n );\n\n if (!assigneeMemberId) {\n const candidateMemberIds = readStringArrayField(\n payload,\n 'candidateMemberIds',\n );\n\n return candidateMemberIds.length\n ? `候選簽核人:${candidateMemberIds\n .map((memberId) =>\n readMemberDisplayText(memberId, memberProfilesById),\n )\n .join('、')}`\n : null;\n }\n\n const assigneeLabel = readMemberDisplayText(\n assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n originalAssigneeMemberId,\n memberProfilesById,\n );\n\n return originalAssigneeMemberId &&\n originalAssigneeMemberId !== assigneeMemberId\n ? `待簽人:${assigneeLabel}(原簽核人:${originalAssigneeLabel})`\n : `待簽人:${assigneeLabel}`;\n }\n\n if (activityLog.eventType === 'TASK_DECIDED') {\n const action = readStringField(payload, 'action');\n const comment = readStringField(payload, 'comment');\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n const transferToMemberId = readStringField(payload, 'transferToMemberId');\n\n return action === 'REJECTED' && comment\n ? [decisionLabel, `拒絕原因:${comment}`]\n .filter(isPresentText)\n .join(' · ')\n : action === 'TRANSFERRED'\n ? [\n decisionLabel,\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n ]\n .filter(isPresentText)\n .join(' · ')\n : decisionLabel;\n }\n\n if (activityLog.eventType === 'TOKEN_ADVANCED') {\n const action = readStringField(payload, 'action');\n\n if (action) {\n return `流程結果:${readTaskDecisionActionLabel(action)}`;\n }\n\n const arrivedCount = readNumberField(payload, 'arrivedCount');\n const requiredCount = readNumberField(payload, 'requiredCount');\n\n if (arrivedCount !== null && requiredCount !== null) {\n return `等待匯合:${arrivedCount}/${requiredCount}`;\n }\n\n const fromNodeId = readStringField(payload, 'fromNodeId');\n const toNodeId = readStringField(payload, 'toNodeId');\n\n if (fromNodeId && toNodeId) {\n return `由 ${readNodeDisplayLabel(fromNodeId, workflow)} 前進至 ${readNodeDisplayLabel(toNodeId, workflow)}`;\n }\n }\n\n if (activityLog.eventType === 'ENGINE_PROCESS_REQUESTED') {\n const state = readStringField(payload, 'state');\n\n return state ? `案件狀態:${readInstanceStateLabel(state)}` : null;\n }\n\n return null;\n}\n\nexport function readActivityDetailParts(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): readonly ActivityStepDescriptionPart[] {\n if (activityLog.eventType !== 'TASK_DECIDED') {\n return [\n readTextDescriptionPart(\n readActivityDetail(\n activityLog,\n payload,\n workflow,\n memberProfilesById,\n ),\n ),\n ].filter(isActivityDescriptionPart);\n }\n\n const taskDecision = activityLog.taskId\n ? taskDecisionsByTaskId.get(activityLog.taskId)\n : null;\n const action =\n readStringField(payload, 'action') ?? taskDecision?.action ?? null;\n const comment =\n readStringField(payload, 'comment') ?? taskDecision?.comment ?? null;\n const transferToMemberId =\n readStringField(payload, 'transferToMemberId') ??\n taskDecision?.transferToMemberId ??\n null;\n const signatureId =\n readStringField(payload, 'signatureId') ??\n taskDecision?.signatureId ??\n null;\n const signature = signatureId ? signaturesById.get(signatureId) : null;\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n return [\n readTextDescriptionPart(decisionLabel),\n action === 'REJECTED'\n ? readDangerTextDescriptionPart(`拒絕原因:${comment ?? '-'}`)\n : null,\n action === 'RETURNED'\n ? readTextDescriptionPart(`退回說明:${comment ?? '-'}`)\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n )\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(`轉派說明:${comment ?? '-'}`)\n : null,\n signature\n ? readTextDescriptionPart(\n signatureVerification?.valid\n ? `簽章:已驗證(${readShortHash(signature.signedPayloadHash)})`\n : `簽章:待檢查(${readShortHash(signature.signedPayloadHash)})`,\n )\n : null,\n ].filter(isActivityDescriptionPart);\n}\n\nexport function isFutureTimelineNode(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): boolean {\n if (node.type === 'startEvent' || representedNodeIds.has(node.id)) {\n return false;\n }\n\n if (instanceState === 'REJECTED') {\n return true;\n }\n\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return state.tone === 'neutral' || state.tone === 'waiting';\n}\n\nexport function readFutureTimelineNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): readonly WorkflowNode[] {\n if (instanceState !== 'RUNNING' && instanceState !== 'REJECTED') {\n return [];\n }\n\n const futureNodes = workflow.nodes.filter((node) =>\n isFutureTimelineNode(\n node,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ),\n );\n const reachableDistances = readReachableFutureNodeDistances(\n workflow,\n futureNodes,\n tasks,\n tokens,\n representedNodeIds,\n );\n const originalNodeIndexes = new Map(\n workflow.nodes.map((node, index) => [node.id, index]),\n );\n\n return futureNodes\n .filter((node) => reachableDistances.has(node.id))\n .sort((left, right) => {\n const leftDistance = reachableDistances.get(left.id) ?? 0;\n const rightDistance = reachableDistances.get(right.id) ?? 0;\n\n if (leftDistance !== rightDistance) {\n return leftDistance - rightDistance;\n }\n\n if (left.position.x !== right.position.x) {\n return left.position.x - right.position.x;\n }\n\n if (left.position.y !== right.position.y) {\n return left.position.y - right.position.y;\n }\n\n return (\n (originalNodeIndexes.get(left.id) ?? 0) -\n (originalNodeIndexes.get(right.id) ?? 0)\n );\n });\n}\n\nfunction readReachableFutureNodeDistances(\n workflow: WorkflowDefinition,\n futureNodes: readonly WorkflowNode[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const futureNodeIds = new Set(futureNodes.map((node) => node.id));\n const outgoingNodeIds = workflow.edges.reduce<\n ReadonlyMap<string, readonly string[]>\n >((groups, edge) => {\n const nextTargets = [...(groups.get(edge.source) ?? []), edge.target];\n\n return new Map(groups).set(edge.source, nextTargets);\n }, new Map());\n const frontierNodeIds = readFutureTimelineFrontierNodeIds(\n workflow,\n tasks,\n tokens,\n representedNodeIds,\n );\n\n return frontierNodeIds.reduce<ReadonlyMap<string, number>>(\n (distances, nodeId) =>\n mergeFutureNodeDistances(\n distances,\n readFutureNodeDistancesFrom(nodeId, outgoingNodeIds, futureNodeIds),\n ),\n new Map(),\n );\n}\n\nfunction readFutureTimelineFrontierNodeIds(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): readonly string[] {\n const tokenNodeIds = tokens\n .filter((token) => token.status === 'ACTIVE' || token.status === 'WAITING')\n .map((token) => token.currentNodeId);\n const pendingTaskNodeIds = tasks\n .filter(isPendingTask)\n .map((task) => task.nodeId);\n const representedFrontierNodeIds = workflow.nodes\n .filter((node) => representedNodeIds.has(node.id))\n .map((node) => node.id);\n const activeFrontierNodeIds = [\n ...new Set([\n ...tokenNodeIds,\n ...pendingTaskNodeIds,\n ...representedFrontierNodeIds,\n ]),\n ];\n const startNodeIds = workflow.nodes\n .filter((node) => node.type === 'startEvent')\n .map((node) => node.id);\n\n return activeFrontierNodeIds.length > 0\n ? activeFrontierNodeIds\n : startNodeIds;\n}\n\nfunction readFutureNodeDistancesFrom(\n startNodeId: string,\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const initialQueue: readonly {\n readonly distance: number;\n readonly nodeId: string;\n }[] = [{ distance: 0, nodeId: startNodeId }];\n\n return walkFutureNodeDistances(initialQueue, outgoingNodeIds, futureNodeIds);\n}\n\nfunction walkFutureNodeDistances(\n queue: readonly { readonly distance: number; readonly nodeId: string }[],\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n visitedNodeIds: ReadonlySet<string> = new Set(),\n distances: ReadonlyMap<string, number> = new Map(),\n): ReadonlyMap<string, number> {\n const [current, ...restQueue] = queue;\n\n if (!current) {\n return distances;\n }\n\n if (visitedNodeIds.has(current.nodeId)) {\n return walkFutureNodeDistances(\n restQueue,\n outgoingNodeIds,\n futureNodeIds,\n visitedNodeIds,\n distances,\n );\n }\n\n const nextVisitedNodeIds = new Set(visitedNodeIds).add(current.nodeId);\n const nextDistances = futureNodeIds.has(current.nodeId)\n ? new Map(distances).set(\n current.nodeId,\n Math.min(\n distances.get(current.nodeId) ?? current.distance,\n current.distance,\n ),\n )\n : distances;\n const nextQueue = [\n ...restQueue,\n ...(outgoingNodeIds.get(current.nodeId) ?? []).map((nodeId) => ({\n distance: current.distance + 1,\n nodeId,\n })),\n ];\n\n return walkFutureNodeDistances(\n nextQueue,\n outgoingNodeIds,\n futureNodeIds,\n nextVisitedNodeIds,\n nextDistances,\n );\n}\n\nfunction mergeFutureNodeDistances(\n currentDistances: ReadonlyMap<string, number>,\n nextDistances: ReadonlyMap<string, number>,\n): ReadonlyMap<string, number> {\n return [...nextDistances.entries()].reduce<ReadonlyMap<string, number>>(\n (mergedDistances, [nodeId, distance]) =>\n new Map(mergedDistances).set(\n nodeId,\n Math.min(mergedDistances.get(nodeId) ?? distance, distance),\n ),\n currentDistances,\n );\n}\n\nexport function readFutureNodeStepTitle(node: WorkflowNode): string {\n if (node.type === 'userTask') return `未來簽核:${node.data.label}`;\n if (node.type === 'serviceTask') return `未來知會:${node.data.label}`;\n if (node.type === 'exclusiveGateway') return `未來分流:${node.data.label}`;\n if (node.type === 'parallelGateway') return `未來匯合:${node.data.label}`;\n if (node.type === 'endEvent') return `流程完成:${node.data.label}`;\n\n return `未來節點:${node.data.label}`;\n}\n\nexport function readActivityStepRecords(\n activityLogs: readonly ActivityLogRecord[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n workflow: WorkflowDefinition | null,\n instanceState: ApprovalInstanceRecord['state'],\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n): ActivityStepRecord[] {\n const historySteps = activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog): ActivityStepRecord => {\n const payload = readActivityPayload(activityLog);\n const nodeLabel = activityLog.nodeId\n ? readNodeDisplayLabel(activityLog.nodeId, workflow)\n : null;\n const descriptionParts = [\n readTextDescriptionPart(\n nodeLabel ? `節點:${nodeLabel}` : '節點:全流程',\n ),\n readMemberDescriptionPart(\n '操作者',\n activityLog.actorMemberId,\n memberProfilesById,\n '系統',\n ),\n readTextDescriptionPart(\n `時間:${formatActivityDateTime(activityLog.createdAt)}`,\n ),\n ...readActivityDetailParts(\n activityLog,\n payload,\n workflow,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n memberProfilesById,\n ),\n ].filter(isActivityDescriptionPart);\n\n return {\n descriptionParts,\n error: isActivityError(activityLog, payload),\n id: activityLog.id,\n title: readActivityEventLabel(activityLog.eventType, payload),\n };\n });\n const pendingTaskSteps = tasks.filter(isPendingTask).map(\n (task): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `節點:${readNodeDisplayLabel(task.nodeId, workflow)}`,\n ),\n readMemberDescriptionPart(\n '處理者',\n task.assigneeMemberId,\n memberProfilesById,\n '未指定',\n ),\n readTextDescriptionPart(\n `建立時間:${formatActivityDateTime(task.createdAt)}`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n id: `pending-task-${task.id}`,\n title: task.status === 'IN_PROGRESS' ? '簽核處理中' : '等待簽核處理',\n }),\n );\n const representedNodeIds = new Set(\n [\n ...activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog) => activityLog.nodeId),\n ...tasks.map((task) => task.nodeId),\n ].filter(isPresentText),\n );\n const futureNodeSteps = workflow\n ? readFutureTimelineNodes(\n workflow,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ).map(\n (node): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `${readNodeKindLabel(node.type)} · 尚未抵達`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n forcePending: true,\n id: `future-node-${node.id}`,\n title: readFutureNodeStepTitle(node),\n }),\n )\n : [];\n\n return [...historySteps, ...pendingTaskSteps, ...futureNodeSteps];\n}\n\n// ---------------------------------------------------------------------------\n// Node runtime state (used by flow canvas AND history)\n// ---------------------------------------------------------------------------\n\ntype RuntimeTone = 'cancelled' | 'completed' | 'current' | 'neutral' | 'waiting';\n\nexport function readNodeRuntimeState(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): Readonly<{\n secondaryLabel: string;\n statusLabel: string;\n tone: RuntimeTone;\n}> {\n const nodeTasks = tasks.filter((task) => task.nodeId === node.id);\n const pendingTask = nodeTasks.find(\n (task) => task.status === 'PENDING' || task.status === 'IN_PROGRESS',\n );\n const cancelledTask = nodeTasks.find((task) => task.status === 'CANCELLED');\n const completedTask = nodeTasks.find((task) => task.status === 'COMPLETED');\n const nodeTokens = tokens.filter((token) => token.currentNodeId === node.id);\n const activeToken = nodeTokens.find((token) => token.status === 'ACTIVE');\n const waitingToken = nodeTokens.find((token) => token.status === 'WAITING');\n\n if (pendingTask) {\n return {\n secondaryLabel: `處理者 ${readTaskAssigneeLabel(pendingTask)}`,\n statusLabel: '待處理',\n tone: 'current',\n };\n }\n\n if (cancelledTask) {\n return {\n secondaryLabel: `已取消 ${readTaskAssigneeLabel(cancelledTask)}`,\n statusLabel: '已取消',\n tone: 'cancelled',\n };\n }\n\n if (completedTask) {\n return {\n secondaryLabel: `已完成 ${readTaskAssigneeLabel(completedTask)}`,\n statusLabel: '已完成',\n tone: 'completed',\n };\n }\n\n if (activeToken) {\n return {\n secondaryLabel: `token ${activeToken.id}`,\n statusLabel: '執行中',\n tone: 'current',\n };\n }\n\n if (waitingToken) {\n return {\n secondaryLabel: `token ${waitingToken.id}`,\n statusLabel: '等待前置',\n tone: 'waiting',\n };\n }\n\n if (node.type === 'startEvent') {\n return {\n secondaryLabel: '流程已發起',\n statusLabel: '已發起',\n tone: 'completed',\n };\n }\n\n if (node.type === 'endEvent' && instanceState !== 'RUNNING') {\n return {\n secondaryLabel: instanceState,\n statusLabel: instanceState === 'REJECTED' ? '已拒絕' : '已完成',\n tone: instanceState === 'REJECTED' ? 'cancelled' : 'completed',\n };\n }\n\n return {\n secondaryLabel: readNodeKindLabel(node.type),\n statusLabel: '未抵達',\n tone: 'neutral',\n };\n}\n","/**\n * Helper functions used by InstanceDetailView (the container) that do not\n * belong in any individual section component.\n */\n\nimport {\n ActivityLogRecord,\n AdhocDirectiveRecord,\n MemberProfileRecord,\n TaskDecisionRecord,\n TaskRecord,\n listTaskDecisions,\n resolveMemberProfiles,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n isPresentText,\n readDelegationChain as _readDelegationChain,\n} from './shared';\n\n// Re-export shared helpers needed by the container\nexport {\n canMemberActOnTask,\n readErrorMessage,\n readInstanceStateLabel,\n readNodeRuntimeState,\n} from './shared';\n\nexport async function readMemberProfilesForTimeline({\n activityLogs,\n adhocDirectives = [],\n tasks,\n}: {\n readonly activityLogs: readonly ActivityLogRecord[];\n readonly adhocDirectives?: readonly AdhocDirectiveRecord[];\n readonly tasks: readonly TaskRecord[];\n}): Promise<readonly MemberProfileRecord[]> {\n const memberIds = [\n ...new Set(\n [\n ...activityLogs.map((activityLog) => activityLog.actorMemberId),\n ...tasks.map((task) => task.assigneeMemberId),\n ...tasks.map((task) => task.originalAssigneeMemberId),\n ...tasks.flatMap((task) => task.candidateMemberIds),\n ...tasks.flatMap((task) =>\n _readDelegationChain(task.delegationChainJson).flatMap((step) => [\n step.from,\n step.to,\n ]),\n ),\n ...adhocDirectives.flatMap((directive) => [\n directive.createdByMemberId,\n ...readAdhocDirectiveTargetMemberIds(directive.targetValueJson),\n ]),\n ].filter(isPresentText),\n ),\n ];\n\n try {\n return await resolveMemberProfiles(memberIds);\n } catch {\n return [];\n }\n}\n\nfunction readAdhocDirectiveTargetMemberIds(\n targetValueJson: string,\n): readonly string[] {\n try {\n const value = JSON.parse(targetValueJson) as {\n readonly memberIds?: readonly unknown[];\n };\n\n return (value.memberIds ?? []).filter(\n (memberId): memberId is string => typeof memberId === 'string',\n );\n } catch {\n return [];\n }\n}\n\nexport async function readTaskDecisionsForTasks(\n tasks: readonly TaskRecord[],\n): Promise<readonly TaskDecisionRecord[]> {\n const decisionLists = await Promise.all(\n tasks.map((task) => listTaskDecisions(task.id)),\n );\n\n return decisionLists.flat();\n}\n\nexport function readLatestTaskDecisionsByTaskId(\n taskDecisions: readonly TaskDecisionRecord[],\n): ReadonlyMap<string, TaskDecisionRecord> {\n return taskDecisions.reduce<ReadonlyMap<string, TaskDecisionRecord>>(\n (decisionsByTaskId, decision) => {\n const currentDecision = decisionsByTaskId.get(decision.taskId);\n const nextDecision =\n !currentDecision ||\n new Date(decision.decidedAt).getTime() >\n new Date(currentDecision.decidedAt).getTime()\n ? decision\n : currentDecision;\n\n return new Map(decisionsByTaskId).set(decision.taskId, nextDecision);\n },\n new Map(),\n );\n}\n","'use client';\n\nimport { CSSProperties, ReactElement } from 'react';\nimport { Button, Typography } from '@mezzanine-ui/react';\nimport { RefreshCcwIcon } from '@mezzanine-ui/icons';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport { ApprovalInstanceRecord, WorkflowFormData } from '@rytass/bpm-core-client/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst BUTTON_ROW_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nexport interface InstanceFormSectionProps {\n /** The loaded approval instance, or null while loading. */\n readonly instance: ApprovalInstanceRecord | null;\n /** Whether the instance is in a loading state. */\n readonly loading: boolean;\n /** Error message to display, if any. */\n readonly error: string | null;\n /** Whether the current user can resubmit (edit + resubmit the returned form). */\n readonly canResubmitInstance: boolean;\n /** Current form data for the resubmit flow. */\n readonly resubmitFormData: WorkflowFormData;\n /** Validation error map for the resubmit form. */\n readonly resubmitFormErrors: Readonly<Record<string, string>>;\n /** Whether a decision/submit action is in progress. */\n readonly deciding: boolean;\n /** Called when the form data changes in the resubmit flow. */\n readonly onResubmitFormChange: (values: WorkflowFormData) => void;\n /** Called when the user clicks \"重新送出\". */\n readonly onResubmitInstance: () => void;\n /** Called when an attachment upload is requested via the form field. */\n readonly onUploadAttachment: (\n field: FormFieldDefinition,\n file: File,\n ) => Promise<{ readonly id: string }>;\n}\n\n/**\n * Renders the form snapshot section of the approval instance detail page.\n * Displays the form in read-only mode normally, or editable mode when the\n * instance has been returned and the current member can resubmit it.\n */\nexport function InstanceFormSection({\n canResubmitInstance,\n deciding,\n error,\n instance,\n loading,\n onResubmitFormChange,\n onResubmitInstance,\n onUploadAttachment,\n resubmitFormData,\n resubmitFormErrors,\n}: InstanceFormSectionProps): ReactElement {\n return (\n <div style={SECTION_BODY_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n {instance?.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema ? (\n <>\n <FormRenderer\n errors={resubmitFormErrors}\n onChange={(values): void => {\n onResubmitFormChange(values);\n }}\n onUploadAttachment={\n canResubmitInstance ? onUploadAttachment : undefined\n }\n readonly={!canResubmitInstance}\n schema={instance.formDefinitionSnapshot.schema}\n uiSchema={instance.formDefinitionSnapshot.uiSchema}\n value={\n canResubmitInstance ? resubmitFormData : instance.formData\n }\n />\n {canResubmitInstance ? (\n <div style={BUTTON_ROW_STYLE}>\n <Button\n disabled={deciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n onClick={onResubmitInstance}\n variant=\"base-primary\"\n >\n 重新送出\n </Button>\n </div>\n ) : null}\n </>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有可顯示的表單快照。\n </Typography>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { CSSProperties, ReactElement, useMemo } from 'react';\nimport { Table, Typography } from '@mezzanine-ui/react';\nimport { DownloadIcon, FileSearchIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { AttachmentRecord } from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { AttachmentRow, formatFileSize } from './shared';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nexport interface InstanceAttachmentsSectionProps {\n /** The list of attachments for this instance. */\n readonly attachments: readonly AttachmentRecord[];\n /** Called when the user clicks the download action for an attachment. */\n readonly onDownload: (attachment: AttachmentRecord) => void;\n /** Called when the user clicks the preview action for a PDF attachment. */\n readonly onPreview: (attachment: AttachmentRecord) => void;\n}\n\n/**\n * Renders the attachments section of the approval instance detail page.\n * Shows a table of attachments with download and (for PDFs) preview actions.\n */\nexport function InstanceAttachmentsSection({\n attachments,\n onDownload,\n onPreview,\n}: InstanceAttachmentsSectionProps): ReactElement {\n const attachmentRows = useMemo(\n (): AttachmentRow[] =>\n attachments.map((attachment) => ({\n attachment,\n createdAt: attachment.createdAt,\n filename: attachment.filename,\n id: attachment.id,\n key: attachment.id,\n mimeType: attachment.mimeType,\n sizeLabel: formatFileSize(Number(attachment.sizeBytes)),\n })),\n [attachments],\n );\n\n const attachmentColumns = useMemo(\n (): TableColumn<AttachmentRow>[] => [\n { dataIndex: 'filename', key: 'filename', title: '檔名', width: 260 },\n { dataIndex: 'mimeType', key: 'mimeType', title: '類型', width: 180 },\n { dataIndex: 'sizeLabel', key: 'sizeLabel', title: '大小', width: 120 },\n {\n key: 'createdAt',\n render: (record: AttachmentRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '上傳時間',\n width: 220,\n },\n ],\n [],\n );\n\n const attachmentActions = useMemo(\n (): TableActions<AttachmentRow> => ({\n render: (record): ReturnType<TableActions<AttachmentRow>['render']> => [\n ...(record.mimeType === 'application/pdf'\n ? [\n {\n icon: FileSearchIcon,\n iconType: 'leading' as const,\n name: '預覽',\n onClick: (): void => {\n onPreview(record.attachment);\n },\n },\n ]\n : []),\n {\n icon: DownloadIcon,\n iconType: 'leading',\n name: '下載',\n onClick: (): void => {\n onDownload(record.attachment);\n },\n },\n ],\n variant: 'base-secondary',\n width: 160,\n }),\n [onDownload, onPreview],\n );\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 附件\n </Typography>\n {attachmentRows.length > 0 ? (\n <Table\n actions={attachmentActions}\n columns={attachmentColumns}\n dataSource={attachmentRows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有附件。\n </Typography>\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n ChangeEvent,\n CSSProperties,\n forwardRef,\n ReactElement,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react';\nimport {\n AutoComplete,\n Button,\n Input,\n Modal,\n Select,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport {\n AdhocDirectiveRecord,\n AdhocPreApprovalRejectBehavior,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n TaskRecord,\n cancelAdhocDirective,\n configureAdhocCompletionNotification,\n configureAdhocStageNotification,\n decideTask,\n requestAdhocCountersign,\n requestAdhocPreApproval,\n searchMembers,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { BPMFormField } from '../../../../components/bpm-form-field';\nimport {\n MemberOption,\n TaskRow,\n canMemberActOnTask,\n readErrorMessage,\n readMemberDisplayText,\n readMemberOption,\n readMemberOptionFromValue,\n readNodeDisplayLabel,\n readReturnTargetOptions,\n readTaskAssigneeLabel,\n readTaskStatusLabel,\n readUniqueMemberOption,\n} from './shared';\n\nconst REJECT_REASON_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst REJECT_REASON_TEXTAREA_STYLE: CSSProperties = {\n minWidth: '100%',\n width: '100%',\n};\n\nconst MODAL_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst SECTION_TABLE_STYLE: CSSProperties = {\n marginTop: 12,\n};\n\nconst SECTION_SUBHEADING_STYLE: CSSProperties = {\n marginTop: 24,\n};\n\nfunction applyFullWidthTextareaHost(element: HTMLDivElement | null): void {\n if (!element) {\n return;\n }\n\n element.style.width = '100%';\n}\n\n/**\n * Imperative handle exposed by InstanceTasksSection via ref.\n * The container uses these to wire PageHeader action buttons to the\n * section's internal modal state without lifting state up.\n */\nexport type AdhocActionMode =\n | 'COMPLETION_NOTIFY'\n | 'COUNTERSIGN'\n | 'PRE_APPROVAL'\n | 'STAGE_NOTIFY';\n\nexport interface InstanceTasksSectionHandle {\n /** Whether a task action (decision) is currently in flight. */\n readonly deciding: boolean;\n /** Whether the current user has an actionable pending task. */\n readonly hasCurrentTask: boolean;\n /** Whether the current task's node allows a return action. */\n readonly canReturnCurrentTask: boolean;\n /** Whether the current task's node allows ad-hoc countersign/pre-approval. */\n readonly canAddSignerCurrentTask: boolean;\n /** Opens the reject-reason modal. */\n openRejectModal(): void;\n /** Opens the return modal. */\n openReturnModal(): void;\n /** Opens the transfer modal. */\n openTransferModal(): void;\n /** Opens the ad-hoc action modal in the given mode. */\n openAdhocModal(mode: AdhocActionMode): void;\n /** Submits an APPROVED decision immediately (no modal needed). */\n handleApprove(): void;\n}\n\nexport interface InstanceTasksSectionProps {\n /** All tasks for this instance. */\n readonly tasks: readonly TaskRecord[];\n /** Ad-hoc directives recorded on this instance. */\n readonly adhocDirectives: readonly AdhocDirectiveRecord[];\n /** The loaded approval instance (used to read workflowSnapshot node labels). */\n readonly instance: ApprovalInstanceRecord | null;\n /** Member profiles indexed by memberId, for displaying assignee labels. */\n readonly memberProfilesById: ReadonlyMap<string, MemberProfileRecord>;\n /** The currently authenticated member's id. */\n readonly currentMemberId: string | null;\n /**\n * Called after any task decision action (approve / reject / return /\n * transfer) completes successfully. The container should refresh data.\n */\n readonly onChanged: () => void | Promise<void>;\n}\n\nconst ADHOC_MODE_LABELS: Readonly<Record<AdhocActionMode, string>> = {\n COMPLETION_NOTIFY: '結案通知',\n COUNTERSIGN: '臨時會簽',\n PRE_APPROVAL: '臨時加簽',\n STAGE_NOTIFY: '階段完成通知',\n};\n\nconst ADHOC_MODE_SUPPORTING_TEXT: Readonly<Record<AdhocActionMode, string>> = {\n COMPLETION_NOTIFY: '本張單到達結案狀態(核准 / 拒絕 / 取消)後,通知指定對象。',\n COUNTERSIGN: '指定對象會併入下一層簽核,下一層需所有人都完成才會繼續。',\n PRE_APPROVAL: '指定對象需先完成加簽,本階段才會往下一層繼續。',\n STAGE_NOTIFY: '本階段完成後(不論通過與否)通知指定對象。',\n};\n\nconst ADHOC_ON_REJECT_OPTIONS: readonly {\n readonly id: AdhocPreApprovalRejectBehavior;\n readonly name: string;\n}[] = [\n { id: 'REJECT_INSTANCE', name: '加簽拒絕時整單駁回' },\n { id: 'RETURN_TO_ORIGIN', name: '加簽拒絕時退回給我重新處理' },\n];\n\nconst ADHOC_NOTIFY_TARGET_OPTIONS: readonly {\n readonly id: 'MEMBER' | 'WEBHOOK';\n readonly name: string;\n}[] = [\n { id: 'MEMBER', name: '指定成員' },\n { id: 'WEBHOOK', name: 'Webhook' },\n];\n\ntype AdhocDirectiveRow = Readonly<\n Record<string, unknown> &\n AdhocDirectiveRecord & {\n createdByLabel: string;\n key: string;\n targetLabel: string;\n typeLabel: string;\n }\n>;\n\n/**\n * Renders the tasks section of the approval instance detail page.\n * Contains the task table plus all decision action modals\n * (reject, return, transfer). Approve is also handled here via the\n * imperative handle exposed through the forwarded ref.\n */\nexport const InstanceTasksSection = forwardRef<\n InstanceTasksSectionHandle,\n InstanceTasksSectionProps\n>(function InstanceTasksSection(\n {\n adhocDirectives,\n currentMemberId,\n instance,\n memberProfilesById,\n onChanged,\n tasks,\n }: InstanceTasksSectionProps,\n ref,\n): ReactElement {\n const [deciding, setDeciding] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Reject modal\n const [rejectReason, setRejectReason] = useState('');\n const [rejectReasonError, setRejectReasonError] = useState<string | null>(null);\n const [rejectReasonModalOpen, setRejectReasonModalOpen] = useState(false);\n\n // Return modal\n const [returnComment, setReturnComment] = useState('');\n const [returnModalOpen, setReturnModalOpen] = useState(false);\n const [returnTargetNodeId, setReturnTargetNodeId] = useState<string | null>(null);\n\n // Transfer modal\n const [transferComment, setTransferComment] = useState('');\n const [transferMember, setTransferMember] = useState<MemberOption | null>(null);\n const [transferMemberLoading, setTransferMemberLoading] = useState(false);\n const [transferMemberOptions, setTransferMemberOptions] = useState<\n readonly MemberOption[]\n >([]);\n const [transferModalOpen, setTransferModalOpen] = useState(false);\n\n // Ad-hoc modal (countersign / pre-approval / stage & completion notify)\n const [adhocComment, setAdhocComment] = useState('');\n const [adhocMember, setAdhocMember] = useState<MemberOption | null>(null);\n const [adhocMemberLoading, setAdhocMemberLoading] = useState(false);\n const [adhocMemberOptions, setAdhocMemberOptions] = useState<\n readonly MemberOption[]\n >([]);\n const [adhocModalOpen, setAdhocModalOpen] = useState(false);\n const [adhocMode, setAdhocMode] = useState<AdhocActionMode>('COUNTERSIGN');\n const [adhocOnReject, setAdhocOnReject] =\n useState<AdhocPreApprovalRejectBehavior>('REJECT_INSTANCE');\n const [adhocSubmitting, setAdhocSubmitting] = useState(false);\n const [adhocTargetKind, setAdhocTargetKind] = useState<'MEMBER' | 'WEBHOOK'>(\n 'MEMBER',\n );\n const [adhocWebhookUrl, setAdhocWebhookUrl] = useState('');\n\n const trimmedRejectReason = rejectReason.trim();\n const trimmedReturnComment = returnComment.trim();\n const trimmedTransferComment = transferComment.trim();\n\n const currentTask = useMemo(\n (): TaskRecord | null =>\n tasks.find(\n (task) =>\n canMemberActOnTask(task, currentMemberId) &&\n (task.status === 'PENDING' || task.status === 'IN_PROGRESS'),\n ) ?? null,\n [currentMemberId, tasks],\n );\n\n const currentTaskNode = useMemo(\n () =>\n currentTask && instance\n ? (instance.workflowSnapshot.nodes.find(\n (node) => node.id === currentTask.nodeId,\n ) ?? null)\n : null,\n [currentTask, instance],\n );\n\n const returnTargetOptions = useMemo(\n (): readonly { readonly id: string; readonly name: string }[] =>\n currentTaskNode && instance\n ? readReturnTargetOptions(instance.workflowSnapshot, currentTaskNode)\n : [],\n [currentTaskNode, instance],\n );\n\n const canReturnCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.allowReturn;\n\n const canAddSignerCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowAddSigner;\n\n const pendingAdhocDirectives = useMemo(\n (): readonly AdhocDirectiveRecord[] =>\n adhocDirectives.filter((directive) => directive.status === 'PENDING'),\n [adhocDirectives],\n );\n\n const selectedReturnTargetOption =\n returnTargetOptions.find((option) => option.id === returnTargetNodeId) ??\n returnTargetOptions[0] ??\n null;\n\n const taskRows = useMemo(\n (): TaskRow[] =>\n tasks.map((task) => ({\n ...task,\n assigneeLabel: readTaskAssigneeLabel(task, memberProfilesById),\n key: task.id,\n nodeLabel: `${readNodeDisplayLabel(\n task.nodeId,\n instance?.workflowSnapshot ?? null,\n )}${\n task.isAdhoc\n ? task.adhocType === 'COUNTERSIGN'\n ? '(臨時會簽)'\n : '(臨時加簽)'\n : ''\n }`,\n statusLabel: readTaskStatusLabel(task.status),\n })),\n [instance, memberProfilesById, tasks],\n );\n\n const taskColumns = useMemo(\n (): TableColumn<TaskRow>[] => [\n { dataIndex: 'nodeLabel', key: 'nodeLabel', title: '節點', width: 180 },\n {\n key: 'assigneeMemberId',\n title: '處理者',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.assigneeLabel}\n </Typography>\n ),\n width: 180,\n },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'createdAt',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n\n const adhocDirectiveRows = useMemo(\n (): AdhocDirectiveRow[] =>\n pendingAdhocDirectives.map((directive) => ({\n ...directive,\n createdByLabel: readMemberDisplayText(\n directive.createdByMemberId,\n memberProfilesById,\n ),\n key: directive.id,\n targetLabel: readAdhocDirectiveTargetLabel(\n directive,\n memberProfilesById,\n ),\n typeLabel: ADHOC_MODE_LABELS[directive.type],\n })),\n [memberProfilesById, pendingAdhocDirectives],\n );\n\n const adhocDirectiveColumns = useMemo(\n (): TableColumn<AdhocDirectiveRow>[] => [\n {\n dataIndex: 'typeLabel',\n key: 'typeLabel',\n title: '類型',\n width: 180,\n },\n {\n key: 'targetLabel',\n render: (record: AdhocDirectiveRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.targetLabel}\n </Typography>\n ),\n title: '對象',\n width: 220,\n },\n {\n key: 'createdByLabel',\n render: (record: AdhocDirectiveRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.createdByLabel}\n </Typography>\n ),\n title: '設定者',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: AdhocDirectiveRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n {\n key: 'actions',\n render: (record: AdhocDirectiveRow): ReactElement =>\n record.createdByMemberId === currentMemberId ? (\n <Button\n disabled={adhocSubmitting}\n onClick={(): void =>\n void handleCancelAdhocDirective(record.id)\n }\n size=\"minor\"\n variant=\"destructive-secondary\"\n >\n 撤回\n </Button>\n ) : (\n <></>\n ),\n title: '操作',\n width: 100,\n },\n ],\n [adhocSubmitting, currentMemberId],\n );\n\n async function handleDecision({\n action,\n comment,\n returnToNodeId = null,\n transferToMemberId = null,\n }: Readonly<{\n action: 'APPROVED' | 'REJECTED' | 'RETURNED' | 'TRANSFERRED';\n comment: string | null;\n returnToNodeId?: string | null;\n transferToMemberId?: string | null;\n }>): Promise<void> {\n if (!currentMemberId || !currentTask) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await decideTask({\n action,\n comment,\n decidedByMemberId: currentMemberId,\n returnToNodeId,\n taskId: currentTask.id,\n transferToMemberId,\n });\n setRejectReasonModalOpen(false);\n setReturnModalOpen(false);\n setTransferModalOpen(false);\n setRejectReason('');\n setReturnComment('');\n setTransferComment('');\n setTransferMember(null);\n setReturnTargetNodeId(null);\n setRejectReasonError(null);\n await onChanged();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n function openRejectReasonModal(): void {\n setRejectReason('');\n setRejectReasonError(null);\n setRejectReasonModalOpen(true);\n }\n\n function closeRejectReasonModal(): void {\n if (deciding) {\n return;\n }\n\n setRejectReasonModalOpen(false);\n setRejectReason('');\n setRejectReasonError(null);\n }\n\n function openReturnModal(): void {\n setReturnComment('');\n setReturnTargetNodeId(returnTargetOptions[0]?.id ?? null);\n setReturnModalOpen(true);\n }\n\n function closeReturnModal(): void {\n if (deciding) {\n return;\n }\n\n setReturnModalOpen(false);\n setReturnComment('');\n setReturnTargetNodeId(null);\n }\n\n function openTransferModal(): void {\n setTransferComment('');\n setTransferMember(null);\n setTransferModalOpen(true);\n void handleSearchTransferMembers('');\n }\n\n function closeTransferModal(): void {\n if (deciding) {\n return;\n }\n\n setTransferModalOpen(false);\n setTransferComment('');\n setTransferMember(null);\n }\n\n async function handleSearchTransferMembers(\n searchText: string,\n ): Promise<void> {\n setTransferMemberLoading(true);\n\n try {\n setTransferMemberOptions(\n (await searchMembers(searchText))\n .filter(\n (searchedMember) => searchedMember.memberId !== currentMemberId,\n )\n .map(readMemberOption),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setTransferMemberLoading(false);\n }\n }\n\n async function handleRejectConfirm(): Promise<void> {\n if (!trimmedRejectReason) {\n setRejectReasonError('請輸入拒絕原因');\n\n return;\n }\n\n await handleDecision({\n action: 'REJECTED',\n comment: trimmedRejectReason,\n });\n }\n\n async function handleTransferConfirm(): Promise<void> {\n if (!transferMember) {\n setError('請選擇轉派對象');\n\n return;\n }\n\n await handleDecision({\n action: 'TRANSFERRED',\n comment: trimmedTransferComment || null,\n transferToMemberId: transferMember.id,\n });\n }\n\n async function handleReturnConfirm(): Promise<void> {\n await handleDecision({\n action: 'RETURNED',\n comment: trimmedReturnComment || null,\n returnToNodeId: selectedReturnTargetOption?.id ?? null,\n });\n }\n\n function resetAdhocModalState(): void {\n setAdhocComment('');\n setAdhocMember(null);\n setAdhocOnReject('REJECT_INSTANCE');\n setAdhocTargetKind('MEMBER');\n setAdhocWebhookUrl('');\n }\n\n function openAdhocModal(mode: AdhocActionMode): void {\n setAdhocMode(mode);\n resetAdhocModalState();\n setAdhocModalOpen(true);\n void handleSearchAdhocMembers('');\n }\n\n function closeAdhocModal(): void {\n if (adhocSubmitting) {\n return;\n }\n\n setAdhocModalOpen(false);\n resetAdhocModalState();\n }\n\n async function handleSearchAdhocMembers(searchText: string): Promise<void> {\n setAdhocMemberLoading(true);\n\n try {\n setAdhocMemberOptions(\n (await searchMembers(searchText)).map(readMemberOption),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setAdhocMemberLoading(false);\n }\n }\n\n async function handleAdhocConfirm(): Promise<void> {\n if (!currentTask) {\n return;\n }\n\n const isNotifyMode =\n adhocMode === 'STAGE_NOTIFY' || adhocMode === 'COMPLETION_NOTIFY';\n const useWebhookTarget = isNotifyMode && adhocTargetKind === 'WEBHOOK';\n const trimmedWebhookUrl = adhocWebhookUrl.trim();\n const selectedMember = adhocMember;\n\n if (useWebhookTarget && !trimmedWebhookUrl) {\n setError('請輸入 Webhook URL');\n\n return;\n }\n\n if (!useWebhookTarget && !selectedMember) {\n setError('請選擇對象成員');\n\n return;\n }\n\n const target =\n useWebhookTarget || !selectedMember\n ? { kind: 'WEBHOOK' as const, webhookUrl: trimmedWebhookUrl }\n : { kind: 'MEMBER' as const, memberIds: [selectedMember.id] };\n const trimmedAdhocComment = adhocComment.trim() || null;\n\n setAdhocSubmitting(true);\n setError(null);\n\n try {\n if (adhocMode === 'COUNTERSIGN') {\n await requestAdhocCountersign({\n comment: trimmedAdhocComment,\n target,\n taskId: currentTask.id,\n });\n } else if (adhocMode === 'PRE_APPROVAL') {\n await requestAdhocPreApproval({\n comment: trimmedAdhocComment,\n onReject: adhocOnReject,\n target,\n taskId: currentTask.id,\n });\n } else if (adhocMode === 'STAGE_NOTIFY') {\n await configureAdhocStageNotification({\n target,\n taskId: currentTask.id,\n });\n } else {\n await configureAdhocCompletionNotification({\n target,\n taskId: currentTask.id,\n });\n }\n\n setAdhocModalOpen(false);\n resetAdhocModalState();\n await onChanged();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setAdhocSubmitting(false);\n }\n }\n\n async function handleCancelAdhocDirective(directiveId: string): Promise<void> {\n setAdhocSubmitting(true);\n setError(null);\n\n try {\n await cancelAdhocDirective(directiveId);\n await onChanged();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setAdhocSubmitting(false);\n }\n }\n\n // Expose imperative handle so the container's PageHeader buttons can\n // trigger actions without lifting all modal state up.\n useImperativeHandle(\n ref,\n (): InstanceTasksSectionHandle => ({\n canAddSignerCurrentTask,\n canReturnCurrentTask,\n deciding,\n handleApprove: (): void => {\n void handleDecision({ action: 'APPROVED', comment: null });\n },\n hasCurrentTask: currentTask !== null,\n openAdhocModal,\n openRejectModal: openRejectReasonModal,\n openReturnModal,\n openTransferModal,\n }),\n [canAddSignerCurrentTask, canReturnCurrentTask, currentTask, deciding],\n );\n\n const isAdhocNotifyMode =\n adhocMode === 'STAGE_NOTIFY' || adhocMode === 'COMPLETION_NOTIFY';\n const adhocConfirmDisabled =\n isAdhocNotifyMode && adhocTargetKind === 'WEBHOOK'\n ? !adhocWebhookUrl.trim()\n : !adhocMember;\n const selectedAdhocOnRejectOption =\n ADHOC_ON_REJECT_OPTIONS.find((option) => option.id === adhocOnReject) ??\n ADHOC_ON_REJECT_OPTIONS[0];\n const selectedAdhocNotifyTargetOption =\n ADHOC_NOTIFY_TARGET_OPTIONS.find(\n (option) => option.id === adhocTargetKind,\n ) ?? ADHOC_NOTIFY_TARGET_OPTIONS[0];\n\n return (\n <>\n <Typography component=\"h2\" variant=\"h3\">\n 任務\n </Typography>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <div style={SECTION_TABLE_STYLE}>\n <Table columns={taskColumns} dataSource={taskRows} fullWidth />\n </div>\n\n {pendingAdhocDirectives.length > 0 ? (\n <>\n <Typography component=\"h3\" style={SECTION_SUBHEADING_STYLE} variant=\"h3\">\n 待生效的臨時設定\n </Typography>\n <div style={SECTION_TABLE_STYLE}>\n <Table\n columns={adhocDirectiveColumns}\n dataSource={adhocDirectiveRows}\n fullWidth\n />\n </div>\n </>\n ) : null}\n\n {/* Reject modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !trimmedRejectReason,\n variant: 'destructive-primary',\n }}\n confirmText=\"送出拒絕\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={closeRejectReasonModal}\n onClose={closeRejectReasonModal}\n onConfirm={(): void => void handleRejectConfirm()}\n open={rejectReasonModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"拒絕案件時必須留下原因,供發起人與後續追蹤查看。\"\n title=\"拒絕原因\"\n >\n <div style={REJECT_REASON_FORM_STYLE}>\n <BPMFormField label=\"拒絕原因\" name=\"rejectReason\" required>\n <Textarea\n autoFocus\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setRejectReason(event.target.value);\n setRejectReasonError(null);\n }}\n placeholder=\"請說明拒絕原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n type={rejectReasonError ? 'error' : 'default'}\n value={rejectReason}\n />\n </BPMFormField>\n {rejectReasonError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {rejectReasonError}\n </Typography>\n ) : null}\n </div>\n </Modal>\n\n {/* Transfer modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !transferMember,\n }}\n confirmText=\"送出轉派\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeTransferModal}\n onClose={closeTransferModal}\n onConfirm={(): void => void handleTransferConfirm()}\n open={transferModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"轉派後,原任務會保留轉派紀錄,新的待簽任務會指派給指定成員。\"\n title=\"轉派簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"轉派對象\" name=\"transferToMemberId\" required>\n <AutoComplete\n asyncData\n disabledOptionsFilter\n emptyText=\"沒有符合的成員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name: 'transfer-member-search',\n spellCheck: false,\n }}\n loading={transferMemberLoading}\n loadingText=\"搜尋成員中...\"\n mode=\"single\"\n onChange={(option): void =>\n setTransferMember(readMemberOptionFromValue(option))\n }\n onSearch={handleSearchTransferMembers}\n onSearchTextChange={(searchText): void =>\n setTransferMember(\n readUniqueMemberOption(searchText, transferMemberOptions),\n )\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearchTransferMembers('');\n }\n }}\n options={[...transferMemberOptions]}\n placeholder=\"搜尋姓名或信箱\"\n searchDebounceTime={300}\n value={transferMember}\n />\n </BPMFormField>\n <BPMFormField label=\"轉派說明\" name=\"transferComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setTransferComment(event.target.value)\n }\n placeholder=\"可補充轉派原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={transferComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n\n {/* Return modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !selectedReturnTargetOption,\n }}\n confirmText=\"送出退回\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeReturnModal}\n onClose={closeReturnModal}\n onConfirm={(): void => void handleReturnConfirm()}\n open={returnModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"退回後,流程會回到指定節點並等待重新處理。\"\n title=\"退回簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"退回節點\" name=\"returnTargetNodeId\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setReturnTargetNodeId(option?.id ?? null)\n }\n options={[...returnTargetOptions]}\n placeholder=\"選擇退回節點\"\n value={selectedReturnTargetOption}\n />\n </BPMFormField>\n <BPMFormField label=\"退回說明\" name=\"returnComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setReturnComment(event.target.value)\n }\n placeholder=\"可補充需要修改的內容\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={returnComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n\n {/* Ad-hoc countersign / pre-approval / notify modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: adhocConfirmDisabled,\n }}\n confirmText=\"送出\"\n loading={adhocSubmitting}\n modalType=\"standard\"\n onCancel={closeAdhocModal}\n onClose={closeAdhocModal}\n onConfirm={(): void => void handleAdhocConfirm()}\n open={adhocModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText={ADHOC_MODE_SUPPORTING_TEXT[adhocMode]}\n title={ADHOC_MODE_LABELS[adhocMode]}\n >\n <div style={MODAL_FORM_STYLE}>\n {isAdhocNotifyMode ? (\n <BPMFormField label=\"通知時機\" name=\"adhocNotifyMode\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setAdhocMode(\n option?.id === 'COMPLETION_NOTIFY'\n ? 'COMPLETION_NOTIFY'\n : 'STAGE_NOTIFY',\n )\n }\n options={[\n { id: 'STAGE_NOTIFY', name: ADHOC_MODE_LABELS.STAGE_NOTIFY },\n {\n id: 'COMPLETION_NOTIFY',\n name: ADHOC_MODE_LABELS.COMPLETION_NOTIFY,\n },\n ]}\n value={{\n id: adhocMode,\n name: ADHOC_MODE_LABELS[adhocMode],\n }}\n />\n </BPMFormField>\n ) : null}\n {isAdhocNotifyMode ? (\n <BPMFormField label=\"通知對象類型\" name=\"adhocTargetKind\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setAdhocTargetKind(\n option?.id === 'WEBHOOK' ? 'WEBHOOK' : 'MEMBER',\n )\n }\n options={[...ADHOC_NOTIFY_TARGET_OPTIONS]}\n value={selectedAdhocNotifyTargetOption}\n />\n </BPMFormField>\n ) : null}\n {isAdhocNotifyMode && adhocTargetKind === 'WEBHOOK' ? (\n <BPMFormField label=\"Webhook URL\" name=\"adhocWebhookUrl\" required>\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n setAdhocWebhookUrl(event.target.value)\n }\n placeholder=\"https://example.com/webhook\"\n value={adhocWebhookUrl}\n />\n </BPMFormField>\n ) : (\n <BPMFormField\n label={isAdhocNotifyMode ? '通知對象' : '簽核對象'}\n name=\"adhocMemberId\"\n required\n >\n <AutoComplete\n asyncData\n disabledOptionsFilter\n emptyText=\"沒有符合的成員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name: 'adhoc-member-search',\n spellCheck: false,\n }}\n loading={adhocMemberLoading}\n loadingText=\"搜尋成員中...\"\n mode=\"single\"\n onChange={(option): void =>\n setAdhocMember(readMemberOptionFromValue(option))\n }\n onSearch={handleSearchAdhocMembers}\n onSearchTextChange={(searchText): void =>\n setAdhocMember(\n readUniqueMemberOption(searchText, adhocMemberOptions),\n )\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearchAdhocMembers('');\n }\n }}\n options={[...adhocMemberOptions]}\n placeholder=\"搜尋姓名或信箱\"\n searchDebounceTime={300}\n value={adhocMember}\n />\n </BPMFormField>\n )}\n {adhocMode === 'PRE_APPROVAL' ? (\n <BPMFormField label=\"拒簽處理方式\" name=\"adhocOnReject\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setAdhocOnReject(\n option?.id === 'RETURN_TO_ORIGIN'\n ? 'RETURN_TO_ORIGIN'\n : 'REJECT_INSTANCE',\n )\n }\n options={[...ADHOC_ON_REJECT_OPTIONS]}\n value={selectedAdhocOnRejectOption}\n />\n </BPMFormField>\n ) : null}\n {!isAdhocNotifyMode ? (\n <BPMFormField label=\"說明\" name=\"adhocComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setAdhocComment(event.target.value)\n }\n placeholder=\"可補充原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={3}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={adhocComment}\n />\n </BPMFormField>\n ) : null}\n </div>\n </Modal>\n </>\n );\n});\n\nfunction readAdhocDirectiveTargetLabel(\n directive: AdhocDirectiveRecord,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n try {\n const value = JSON.parse(directive.targetValueJson) as {\n readonly memberIds?: readonly string[];\n readonly orgUnitId?: string;\n readonly positionId?: string;\n readonly webhookUrl?: string;\n };\n\n if (value.memberIds?.length) {\n return value.memberIds\n .map(\n (memberId) => readMemberDisplayText(memberId, memberProfilesById),\n )\n .join('、');\n }\n\n if (value.webhookUrl) {\n return value.webhookUrl;\n }\n\n if (value.positionId) {\n return `職位 ${value.positionId}`;\n }\n\n if (value.orgUnitId) {\n return `部門 ${value.orgUnitId}`;\n }\n } catch {\n // Fall through to the kind label below.\n }\n\n return directive.targetKind;\n}\n","'use client';\n\nimport { CSSProperties, ReactElement, useMemo } from 'react';\nimport { Table, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport {\n SignatureRecord,\n SignatureVerificationRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { SignatureRow, readShortHash } from './shared';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nexport interface InstanceSignaturesSectionProps {\n /** The list of signatures for this instance. */\n readonly signatures: readonly SignatureRecord[];\n /** The signature chain verification result, or null if not yet loaded. */\n readonly signatureVerification: SignatureVerificationRecord | null;\n}\n\n/**\n * Renders the signatures section of the approval instance detail page.\n * Shows the signature chain verification status and a table of individual\n * signature records.\n */\nexport function InstanceSignaturesSection({\n signatureVerification,\n signatures,\n}: InstanceSignaturesSectionProps): ReactElement {\n const signatureRows = useMemo(\n (): SignatureRow[] =>\n signatures.map((signature) => ({\n algorithm: signature.algorithm,\n hashLabel: readShortHash(signature.signedPayloadHash),\n key: signature.id,\n keyVersion: signature.keyVersion,\n signedAtLabel: formatDateTime(signature.signedAt),\n signerMemberId: signature.signerMemberId,\n })),\n [signatures],\n );\n\n const signatureColumns = useMemo(\n (): TableColumn<SignatureRow>[] => [\n {\n dataIndex: 'signerMemberId',\n key: 'signerMemberId',\n title: '簽章者',\n width: 160,\n },\n { dataIndex: 'algorithm', key: 'algorithm', title: '演算法', width: 150 },\n {\n dataIndex: 'keyVersion',\n key: 'keyVersion',\n title: 'Key 版本',\n width: 100,\n },\n {\n dataIndex: 'hashLabel',\n key: 'hashLabel',\n title: 'Payload Hash',\n width: 180,\n },\n {\n dataIndex: 'signedAtLabel',\n key: 'signedAtLabel',\n title: '簽章時間',\n width: 220,\n },\n ],\n [],\n );\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 簽章\n </Typography>\n <Typography\n color={\n signatureVerification?.valid ? 'text-success' : 'text-error'\n }\n variant=\"body\"\n >\n {signatureVerification\n ? signatureVerification.valid\n ? `簽章鏈已驗證,共 ${signatureVerification.checkedCount} 筆。`\n : `簽章鏈驗證失敗:${signatureVerification.errors.join('、')}`\n : '尚無簽章紀錄。'}\n </Typography>\n {signatureRows.length > 0 ? (\n <Table\n columns={signatureColumns}\n dataSource={signatureRows}\n fullWidth\n />\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport {\n CSSProperties,\n Fragment,\n ReactElement,\n RefCallback,\n forwardRef,\n} from 'react';\nimport { Stepper, Tooltip, Typography, type StepProps } from '@mezzanine-ui/react';\nimport { stepClasses } from '@mezzanine-ui/core/stepper';\nimport {\n ActivityLogRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowTokenRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport {\n ActivityStepDescriptionPart,\n ActivityStepRecord,\n isActivityDescriptionPart,\n isPresentText,\n readActivityStepRecords,\n readCurrentActivityStep,\n} from './shared';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst HISTORY_MEMBER_NAME_STYLE: CSSProperties = {\n cursor: 'help',\n textDecoration: 'underline dotted',\n textUnderlineOffset: 3,\n};\n\nconst HISTORY_DANGER_TEXT_STYLE: CSSProperties = {\n color: 'var(--mzn-color-text-error)',\n};\n\nfunction joinClassNames(\n ...classNames: readonly (string | null | undefined)[]\n): string {\n return classNames\n .filter((className): className is string =>\n isPresentText(className ?? null),\n )\n .join(' ');\n}\n\ninterface ActivityHistoryStepProps extends StepProps {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly forcePending?: boolean;\n}\n\nconst ActivityHistoryStep = forwardRef<\n HTMLDivElement,\n ActivityHistoryStepProps\n>(function ActivityHistoryStep(\n {\n className,\n descriptionParts,\n error,\n forcePending = false,\n index = 0,\n orientation,\n status = 'pending',\n title,\n type = 'number',\n ...rest\n },\n ref,\n): ReactElement {\n const displayStatus = forcePending ? 'pending' : status;\n\n return (\n <div\n {...rest}\n className={joinClassNames(\n stepClasses.host,\n type === 'dot' ? stepClasses.dot : null,\n error && displayStatus !== 'processing' ? stepClasses.error : null,\n orientation === 'horizontal' ? stepClasses.horizontal : null,\n type === 'number' ? stepClasses.number : null,\n displayStatus === 'pending' ? stepClasses.pending : null,\n displayStatus === 'processing' ? stepClasses.processing : null,\n error && displayStatus === 'processing'\n ? stepClasses.processingError\n : null,\n !error && displayStatus === 'succeeded' ? stepClasses.succeeded : null,\n orientation === 'vertical' ? stepClasses.vertical : null,\n className,\n )}\n ref={ref}\n >\n {type === 'dot' ? (\n <span\n className={joinClassNames(\n stepClasses.statusIndicator,\n stepClasses.statusIndicatorDot,\n )}\n />\n ) : (\n <span className={stepClasses.statusIndicator}>{index + 1}</span>\n )}\n <div className={stepClasses.textContainer}>\n <Typography\n className={stepClasses.title}\n variant=\"label-primary-highlight\"\n >\n {title}\n <span className={stepClasses.titleConnectLine} />\n </Typography>\n {descriptionParts.length > 0 ? (\n <Typography className={stepClasses.description} variant=\"caption\">\n {descriptionParts.map((part, partIndex) => (\n <Fragment key={`${part.type}-${partIndex}`}>\n {partIndex > 0 ? ' · ' : null}\n {renderActivityDescriptionPart(part)}\n </Fragment>\n ))}\n </Typography>\n ) : null}\n </div>\n </div>\n );\n});\n\nfunction renderActivityDescriptionPart(\n part: ActivityStepDescriptionPart,\n): ReactElement | string {\n if (part.type === 'text') {\n return part.text;\n }\n\n if (part.type === 'dangerText') {\n return <span style={HISTORY_DANGER_TEXT_STYLE}>{part.text}</span>;\n }\n\n if (!part.email) {\n return `${part.prefix}:${part.label}`;\n }\n\n return (\n <>\n {part.prefix}:\n <Tooltip title={part.email}>\n {({ onMouseEnter, onMouseLeave, ref }): ReactElement => (\n <span\n data-testid={\n part.memberId ? `member-tooltip-${part.memberId}` : undefined\n }\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n ref={ref as RefCallback<HTMLSpanElement>}\n style={HISTORY_MEMBER_NAME_STYLE}\n >\n {part.label}\n </span>\n )}\n </Tooltip>\n </>\n );\n}\n\nexport interface InstanceHistorySectionProps {\n /** Activity log records for this instance. */\n readonly activityLogs: readonly ActivityLogRecord[];\n /** All tasks for this instance (used to compute pending/future steps). */\n readonly tasks: readonly TaskRecord[];\n /** All workflow tokens for this instance. */\n readonly workflowTokens: readonly WorkflowTokenRecord[];\n /** The workflow definition snapshot, or null if not yet loaded. */\n readonly workflowSnapshot: WorkflowDefinition | null;\n /** The current state of the instance. */\n readonly instanceState: ApprovalInstanceRecord['state'];\n /** Member profiles indexed by memberId. */\n readonly memberProfilesById: ReadonlyMap<string, MemberProfileRecord>;\n /** Task decisions indexed by taskId (latest per task). */\n readonly taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>;\n /** Signatures indexed by id. */\n readonly signaturesById: ReadonlyMap<string, SignatureRecord>;\n /** Signature chain verification result, or null. */\n readonly signatureVerification: SignatureVerificationRecord | null;\n}\n\n/**\n * Renders the activity history section of the approval instance detail page.\n * Computes the step records from the provided data and renders them as a\n * vertical dot stepper.\n */\nexport function InstanceHistorySection({\n activityLogs,\n instanceState,\n memberProfilesById,\n signatureVerification,\n signaturesById,\n taskDecisionsByTaskId,\n tasks,\n workflowSnapshot,\n workflowTokens,\n}: InstanceHistorySectionProps): ReactElement {\n const activitySteps: readonly ActivityStepRecord[] = readActivityStepRecords(\n activityLogs,\n tasks,\n workflowTokens,\n workflowSnapshot,\n instanceState,\n memberProfilesById,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n );\n\n const currentActivityStep = readCurrentActivityStep(activitySteps);\n\n const filteredDescriptionParts = activitySteps.map((step) => ({\n ...step,\n descriptionParts: step.descriptionParts.filter(isActivityDescriptionPart),\n }));\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 歷程\n </Typography>\n {filteredDescriptionParts.length > 0 ? (\n <Stepper\n currentStep={currentActivityStep}\n orientation=\"vertical\"\n type=\"dot\"\n >\n {filteredDescriptionParts.map((activityStep) => (\n <ActivityHistoryStep\n descriptionParts={activityStep.descriptionParts}\n error={activityStep.error}\n forcePending={activityStep.forcePending}\n key={activityStep.id}\n title={activityStep.title}\n />\n ))}\n </Stepper>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 尚無歷程紀錄。\n </Typography>\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n Background,\n Controls,\n Handle,\n Position,\n ReactFlow,\n type Edge as FlowEdge,\n type Node as FlowNode,\n type NodeProps,\n} from '@xyflow/react';\nimport * as dagre from 'dagre';\nimport {\n Button,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n CheckedIcon,\n DangerousOutlineIcon,\n NotificationUnreadIcon,\n PlusIcon,\n RefreshCcwIcon,\n ShareIcon,\n UserIcon,\n} from '@mezzanine-ui/icons';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport {\n focusFormRendererField,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n ActivityLogRecord,\n AdhocDirectiveRecord,\n AttachmentRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n cancelApprovalInstance,\n listAdhocDirectives,\n listAttachments,\n readApprovalInstance,\n readAttachmentDownloadUrl,\n readAttachmentPreviewUrl,\n readInstanceSignatures,\n resubmitApprovalInstance,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowFormData,\n WorkflowTokenRecord,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { PDFPreview } from '../../../components/pdf-preview';\nimport {\n canMemberActOnTask,\n readErrorMessage,\n readInstanceStateLabel,\n readLatestTaskDecisionsByTaskId,\n readMemberProfilesForTimeline,\n readNodeRuntimeState,\n readTaskDecisionsForTasks,\n} from './sections/container-helpers';\nimport { InstanceFormSection } from './sections/InstanceFormSection';\nimport { InstanceAttachmentsSection } from './sections/InstanceAttachmentsSection';\nimport {\n InstanceTasksSection,\n type InstanceTasksSectionHandle,\n} from './sections/InstanceTasksSection';\nimport { InstanceSignaturesSection } from './sections/InstanceSignaturesSection';\nimport { InstanceHistorySection } from './sections/InstanceHistorySection';\n\nconst FLOW_NODE_LAYOUT_WIDTH = 184;\nconst FLOW_NODE_LAYOUT_HEIGHT = 96;\n\nconst FLOW_MODAL_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst FLOW_CANVAS_STYLE: CSSProperties = {\n background: '#f8fafc',\n border: '1px solid #e2e8f0',\n borderRadius: 8,\n height: 'min(64vh, 620px)',\n minHeight: 440,\n overflow: 'hidden',\n width: 'min(80vw, 1040px)',\n};\n\nconst NODE_STYLE: CSSProperties = {\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n boxShadow: '0 8px 18px rgba(15, 23, 42, 0.08)',\n display: 'grid',\n gap: 6,\n minHeight: 82,\n padding: 12,\n width: 184,\n};\n\nconst NODE_STATUS_STYLE: CSSProperties = {\n borderRadius: 999,\n fontSize: 12,\n fontWeight: 600,\n justifySelf: 'start',\n lineHeight: '18px',\n padding: '0 8px',\n};\n\nconst NODE_SECONDARY_STYLE: CSSProperties = {\n color: '#64748b',\n fontSize: 12,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nconst NODE_HANDLE_STYLE: CSSProperties = {\n opacity: 0,\n};\n\nconst EDGE_SUMMARY_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nconst EDGE_SUMMARY_ITEM_STYLE: CSSProperties = {\n alignItems: 'center',\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n color: '#334155',\n display: 'inline-flex',\n fontSize: 12,\n fontWeight: 600,\n gap: 6,\n lineHeight: '20px',\n padding: '4px 8px',\n};\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst READONLY_FLOW_NODE_TYPES = {\n workflowRuntime: WorkflowRuntimeNodeCard,\n};\n\ntype RuntimeTone =\n | 'cancelled'\n | 'completed'\n | 'current'\n | 'neutral'\n | 'waiting';\n\ninterface RuntimeNodeData extends Record<string, unknown> {\n readonly kindLabel: string;\n readonly label: string;\n readonly secondaryLabel: string;\n readonly statusLabel: string;\n readonly tone: RuntimeTone;\n}\n\ntype RuntimeFlowNode = FlowNode<RuntimeNodeData, 'workflowRuntime'>;\ntype RuntimeFlowEdge = FlowEdge<\n Readonly<Record<string, unknown>>,\n 'smoothstep'\n>;\n\nexport interface InstanceDetailViewProps {\n /** Approval instance id (Next.js `params.id` resolved by the page shim). */\n readonly instanceId: string;\n /** Show the form snapshot section (default: true). */\n readonly showForm?: boolean;\n /** Show the attachments section (default: true). */\n readonly showAttachments?: boolean;\n /** Show the tasks section (default: true). */\n readonly showTasks?: boolean;\n /** Show the signatures section (default: true). */\n readonly showSignatures?: boolean;\n /** Show the history section (default: true). */\n readonly showHistory?: boolean;\n}\n\n/**\n * Framework-agnostic view for the BPM approval instance detail page.\n * Mechanical port of `apps/client/src/app/instances/[id]/page.tsx`. The\n * `instanceId` is provided by the host page wrapper (typically resolved\n * from `params.id` in the Next.js Server Component shim).\n */\nexport function InstanceDetailView({\n instanceId,\n showAttachments = true,\n showForm = true,\n showHistory = true,\n showSignatures = true,\n showTasks = true,\n}: InstanceDetailViewProps): ReactElement {\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const [activityLogs, setActivityLogs] = useState<\n readonly ActivityLogRecord[]\n >([]);\n const [instance, setInstance] = useState<ApprovalInstanceRecord | null>(null);\n const [taskDecisions, setTaskDecisions] = useState<\n readonly TaskDecisionRecord[]\n >([]);\n const [attachments, setAttachments] = useState<readonly AttachmentRecord[]>(\n [],\n );\n const [signatures, setSignatures] = useState<readonly SignatureRecord[]>([]);\n const [signatureVerification, setSignatureVerification] =\n useState<SignatureVerificationRecord | null>(null);\n const [tasks, setTasks] = useState<readonly TaskRecord[]>([]);\n const [workflowTokens, setWorkflowTokens] = useState<\n readonly WorkflowTokenRecord[]\n >([]);\n const [memberProfiles, setMemberProfiles] = useState<\n readonly MemberProfileRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [deciding, setDeciding] = useState(false);\n const [workflowModalOpen, setWorkflowModalOpen] = useState(false);\n const [cancelComment, setCancelComment] = useState('');\n const [cancelModalOpen, setCancelModalOpen] = useState(false);\n const [resubmitFormErrors, setResubmitFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [resubmitFormData, setResubmitFormData] = useState<WorkflowFormData>(\n {},\n );\n const [previewAttachment, setPreviewAttachment] =\n useState<AttachmentRecord | null>(null);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [adhocDirectives, setAdhocDirectives] = useState<\n readonly AdhocDirectiveRecord[]\n >([]);\n\n const trimmedCancelComment = cancelComment.trim();\n\n // Ref to the TasksSection imperative handle, used by PageHeader buttons.\n const tasksSectionRef = useRef<InstanceTasksSectionHandle>(null);\n\n useEffect((): void => {\n void refreshInstance();\n }, [currentMemberId, instanceId]);\n\n useEffect((): void => {\n setResubmitFormData(instance?.formData ?? {});\n }, [instance]);\n\n // Derived from tasks (needed for PageHeader actions — read from ref for\n // deciding/hasCurrentTask, but we need these synchronously for rendering).\n const currentTask = useMemo(\n (): TaskRecord | null =>\n tasks.find(\n (task) =>\n canMemberActOnTask(task, currentMemberId) &&\n (task.status === 'PENDING' || task.status === 'IN_PROGRESS'),\n ) ?? null,\n [currentMemberId, tasks],\n );\n const currentTaskNode = useMemo(\n (): WorkflowNode | null =>\n currentTask && instance\n ? (instance.workflowSnapshot.nodes.find(\n (node) => node.id === currentTask.nodeId,\n ) ?? null)\n : null,\n [currentTask, instance],\n );\n const canReturnCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.allowReturn;\n const canAddSignerCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowAddSigner;\n const canCancelInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n (instance.state === 'RUNNING' || instance.state === 'RETURNED'),\n );\n const canResubmitInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n instance.state === 'RETURNED',\n );\n const memberProfilesById = useMemo(\n (): ReadonlyMap<string, MemberProfileRecord> =>\n new Map(memberProfiles.map((profile) => [profile.memberId, profile])),\n [memberProfiles],\n );\n const taskDecisionsByTaskId = useMemo(\n (): ReadonlyMap<string, TaskDecisionRecord> =>\n readLatestTaskDecisionsByTaskId(taskDecisions),\n [taskDecisions],\n );\n const signaturesById = useMemo(\n (): ReadonlyMap<string, SignatureRecord> =>\n new Map(signatures.map((signature) => [signature.id, signature])),\n [signatures],\n );\n const layoutedWorkflowSnapshot = useMemo(\n (): WorkflowDefinition | null =>\n instance\n ? layoutRuntimeWorkflowDefinition(instance.workflowSnapshot)\n : null,\n [instance],\n );\n const flowNodes = useMemo(\n (): RuntimeFlowNode[] =>\n instance && layoutedWorkflowSnapshot\n ? readRuntimeFlowNodes(\n layoutedWorkflowSnapshot,\n tasks,\n workflowTokens,\n instance.state,\n )\n : [],\n [instance, layoutedWorkflowSnapshot, tasks, workflowTokens],\n );\n const flowEdges = useMemo(\n (): RuntimeFlowEdge[] =>\n layoutedWorkflowSnapshot\n ? readRuntimeFlowEdges(layoutedWorkflowSnapshot)\n : [],\n [layoutedWorkflowSnapshot],\n );\n const edgeSummaries = useMemo(\n (): readonly string[] =>\n instance ? readEdgeSummaries(instance.workflowSnapshot) : [],\n [instance],\n );\n\n async function refreshInstance(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n const nextRecord = await readApprovalInstance(instanceId);\n setActivityLogs(nextRecord.activityLogs);\n setInstance(nextRecord.instance);\n setTasks(nextRecord.tasks);\n setWorkflowTokens(nextRecord.workflowTokens);\n const nextAdhocDirectives = await listAdhocDirectives(\n nextRecord.instance.id,\n );\n const [\n nextTaskDecisions,\n nextMemberProfiles,\n nextAttachments,\n nextSignatures,\n ] = await Promise.all([\n readTaskDecisionsForTasks(nextRecord.tasks),\n readMemberProfilesForTimeline({\n ...nextRecord,\n adhocDirectives: nextAdhocDirectives,\n }),\n listAttachments(nextRecord.instance.id),\n readInstanceSignatures(nextRecord.instance.id),\n ]);\n setTaskDecisions(nextTaskDecisions);\n setMemberProfiles(nextMemberProfiles);\n setAttachments(nextAttachments);\n setSignatures(nextSignatures.signatures);\n setSignatureVerification(nextSignatures.verification);\n setAdhocDirectives(nextAdhocDirectives);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n async function handleDownloadAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentDownloadUrl({\n id: attachment.id,\n });\n\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n\n async function handlePreviewAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentPreviewUrl({\n id: attachment.id,\n });\n\n setPreviewAttachment(attachment);\n setPreviewUrl(url);\n }\n\n async function handleCancelInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canCancelInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n setResubmitFormErrors({});\n\n if (\n instance.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema\n ) {\n const validation = validateFormRendererValues({\n schema: instance.formDefinitionSnapshot.schema,\n uiSchema: instance.formDefinitionSnapshot.uiSchema,\n values: resubmitFormData,\n });\n\n if (!validation.valid) {\n setResubmitFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setDeciding(false);\n\n return;\n }\n }\n\n try {\n await cancelApprovalInstance({\n cancelledByMemberId: currentMemberId,\n comment: trimmedCancelComment || null,\n instanceId: instance.id,\n });\n setCancelComment('');\n setCancelModalOpen(false);\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n async function handleResubmitInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canResubmitInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await resubmitApprovalInstance({\n formData: resubmitFormData,\n initiatorMemberId: currentMemberId,\n instanceId: instance.id,\n title: instance.title,\n });\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n // Derive deciding/canReturn for the PageHeader from the ref handle\n // (falls back to local state for cancel/other actions).\n const taskSectionDeciding = tasksSectionRef.current?.deciding ?? false;\n const combinedDeciding = deciding || taskSectionDeciding;\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n instance\n ? `${readInstanceStateLabel(instance.state)} · ${formatDateTime(\n instance.startedAt,\n )}`\n : '載入案件內容。'\n }\n title={instance?.title ?? '簽核案件'}\n >\n {instance ? (\n <Button\n aria-label=\"查看流程圖\"\n icon={ShareIcon}\n iconType=\"icon-only\"\n onClick={(): void => setWorkflowModalOpen(true)}\n title=\"查看流程圖\"\n variant=\"base-secondary\"\n >\n 流程圖\n </Button>\n ) : null}\n {canCancelInstance ? (\n <Button\n disabled={combinedDeciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n onClick={(): void => setCancelModalOpen(true)}\n variant=\"destructive-secondary\"\n >\n 取消案件\n </Button>\n ) : null}\n {currentTask ? (\n <>\n {/* Stable keys keep these action buttons mounted while the\n conditional ad-hoc buttons appear, so in-flight clicks are\n not lost to re-created DOM nodes. */}\n {canAddSignerCurrentTask ? (\n <>\n <Button\n disabled={combinedDeciding}\n icon={PlusIcon}\n iconType=\"leading\"\n key=\"adhoc-countersign\"\n onClick={(): void =>\n tasksSectionRef.current?.openAdhocModal('COUNTERSIGN')\n }\n variant=\"base-secondary\"\n >\n 會簽\n </Button>\n <Button\n disabled={combinedDeciding}\n icon={PlusIcon}\n iconType=\"leading\"\n key=\"adhoc-pre-approval\"\n onClick={(): void =>\n tasksSectionRef.current?.openAdhocModal('PRE_APPROVAL')\n }\n variant=\"base-secondary\"\n >\n 加簽\n </Button>\n </>\n ) : null}\n <Button\n disabled={combinedDeciding}\n icon={NotificationUnreadIcon}\n iconType=\"leading\"\n key=\"adhoc-notify\"\n onClick={(): void =>\n tasksSectionRef.current?.openAdhocModal('STAGE_NOTIFY')\n }\n variant=\"base-secondary\"\n >\n 通知設定\n </Button>\n {canReturnCurrentTask ? (\n <Button\n disabled={combinedDeciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n key=\"task-return\"\n onClick={(): void => tasksSectionRef.current?.openReturnModal()}\n variant=\"base-secondary\"\n >\n 退回\n </Button>\n ) : null}\n <Button\n disabled={combinedDeciding}\n icon={UserIcon}\n iconType=\"leading\"\n key=\"task-transfer\"\n onClick={(): void => tasksSectionRef.current?.openTransferModal()}\n variant=\"base-secondary\"\n >\n 轉派\n </Button>\n <Button\n disabled={combinedDeciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n key=\"task-reject\"\n onClick={(): void => tasksSectionRef.current?.openRejectModal()}\n variant=\"destructive-secondary\"\n >\n 拒絕\n </Button>\n <Button\n disabled={combinedDeciding}\n icon={CheckedIcon}\n iconType=\"leading\"\n key=\"task-approve\"\n onClick={(): void => tasksSectionRef.current?.handleApprove()}\n variant=\"base-primary\"\n >\n 同意\n </Button>\n </>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n {showForm ? (\n <Section>\n <InstanceFormSection\n canResubmitInstance={canResubmitInstance}\n deciding={deciding}\n error={error}\n instance={instance}\n loading={loading}\n onResubmitFormChange={(values): void => {\n setResubmitFormData(values);\n setResubmitFormErrors({});\n }}\n onResubmitInstance={(): void => void handleResubmitInstance()}\n onUploadAttachment={handleUploadAttachment}\n resubmitFormData={resubmitFormData}\n resubmitFormErrors={resubmitFormErrors}\n />\n </Section>\n ) : null}\n\n {showAttachments ? (\n <Section>\n <InstanceAttachmentsSection\n attachments={attachments}\n onDownload={(attachment): void => {\n void handleDownloadAttachment(attachment);\n }}\n onPreview={(attachment): void => {\n void handlePreviewAttachment(attachment);\n }}\n />\n </Section>\n ) : null}\n\n {showTasks ? (\n <Section>\n <InstanceTasksSection\n adhocDirectives={adhocDirectives}\n currentMemberId={currentMemberId}\n instance={instance}\n memberProfilesById={memberProfilesById}\n onChanged={refreshInstance}\n ref={tasksSectionRef}\n tasks={tasks}\n />\n </Section>\n ) : null}\n\n {showSignatures ? (\n <Section>\n <InstanceSignaturesSection\n signatureVerification={signatureVerification}\n signatures={signatures}\n />\n </Section>\n ) : null}\n\n {showHistory ? (\n <Section>\n <InstanceHistorySection\n activityLogs={activityLogs}\n instanceState={instance?.state ?? 'RUNNING'}\n memberProfilesById={memberProfilesById}\n signatureVerification={signatureVerification}\n signaturesById={signaturesById}\n taskDecisionsByTaskId={taskDecisionsByTaskId}\n tasks={tasks}\n workflowSnapshot={instance?.workflowSnapshot ?? null}\n workflowTokens={workflowTokens}\n />\n </Section>\n ) : null}\n </SectionGroup>\n\n {/* Workflow flow modal */}\n {instance ? (\n <Modal\n modalType=\"standard\"\n onClose={(): void => setWorkflowModalOpen(false)}\n open={workflowModalOpen}\n showModalHeader\n size=\"wide\"\n supportingText={`${readInstanceStateLabel(\n instance.state,\n )} · ${formatDateTime(instance.startedAt)}`}\n title=\"流程圖\"\n >\n <div style={FLOW_MODAL_BODY_STYLE}>\n <div style={FLOW_CANVAS_STYLE}>\n <ReactFlow\n edges={flowEdges}\n fitView\n fitViewOptions={{ padding: 0.18 }}\n maxZoom={1.2}\n minZoom={0.2}\n nodes={flowNodes}\n nodesDraggable={false}\n nodesFocusable={false}\n nodeTypes={READONLY_FLOW_NODE_TYPES}\n panOnDrag\n proOptions={{ hideAttribution: true }}\n >\n <Background />\n <Controls showInteractive={false} />\n </ReactFlow>\n </div>\n {edgeSummaries.length > 0 ? (\n <div style={EDGE_SUMMARY_STYLE}>\n {edgeSummaries.map((summary) => (\n <span key={summary} style={EDGE_SUMMARY_ITEM_STYLE}>\n {summary}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n </Modal>\n ) : null}\n\n {/* PDF preview modal */}\n <Modal\n modalType=\"standard\"\n onClose={(): void => {\n setPreviewAttachment(null);\n setPreviewUrl(null);\n }}\n open={Boolean(previewAttachment && previewUrl)}\n showModalHeader\n size=\"wide\"\n supportingText={previewAttachment?.filename ?? undefined}\n title=\"PDF 預覽\"\n >\n {previewUrl ? (\n <PDFPreview\n filename={previewAttachment?.filename ?? 'PDF 預覽'}\n fileUrl={previewUrl}\n onDownload={\n previewAttachment\n ? (): void => void handleDownloadAttachment(previewAttachment)\n : undefined\n }\n />\n ) : null}\n </Modal>\n\n {/* Cancel instance modal */}\n <Modal\n cancelText=\"保留案件\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"確認取消\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setCancelModalOpen(false)}\n onClose={(): void => setCancelModalOpen(false)}\n onConfirm={(): void => void handleCancelInstance()}\n open={cancelModalOpen}\n showModalFooter\n showModalHeader\n supportingText=\"取消後會關閉目前待簽任務與候選簽核人。\"\n title=\"取消案件\"\n >\n <div style={SECTION_BODY_STYLE}>\n <Typography variant=\"body\">\n 確定要取消「{instance?.title ?? ''}」嗎?\n </Typography>\n <BPMFormField label=\"取消原因\" name=\"cancelComment\">\n <Textarea\n onChange={(event): void =>\n setCancelComment(event.target.value)\n }\n placeholder=\"可填寫取消原因\"\n resize=\"vertical\"\n rows={3}\n value={cancelComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n </>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Container-local helper functions (flow canvas, labels)\n// ---------------------------------------------------------------------------\n\nfunction readEdgeLabel(edge: WorkflowDefinition['edges'][number]): string {\n if (edge.data.label) {\n return edge.data.label;\n }\n\n if (edge.data.isDefault) {\n return '其他情況';\n }\n\n return edge.data.condition ?? '';\n}\n\nfunction readEdgeSummaries(workflow: WorkflowDefinition): readonly string[] {\n return workflow.edges\n .map(readEdgeLabel)\n .filter((label) => label.trim().length > 0);\n}\n\nfunction readNodeKindLabel(type: WorkflowNode['type']): string {\n if (type === 'startEvent') return '開始';\n if (type === 'endEvent') return '完成';\n if (type === 'userTask') return '簽核節點';\n if (type === 'serviceTask') return '知會節點';\n if (type === 'exclusiveGateway') return '條件分流';\n\n return '平行處理';\n}\n\nfunction readRuntimeFlowNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): RuntimeFlowNode[] {\n return workflow.nodes.map((node): RuntimeFlowNode => {\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return {\n data: {\n kindLabel: readNodeKindLabel(node.type),\n label: node.data.label,\n secondaryLabel: state.secondaryLabel,\n statusLabel: state.statusLabel,\n tone: state.tone,\n },\n id: node.id,\n position: node.position,\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n type: 'workflowRuntime',\n };\n });\n}\n\nfunction layoutRuntimeWorkflowDefinition(\n workflow: WorkflowDefinition,\n): WorkflowDefinition {\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n nodesep: 56,\n rankdir: 'LR',\n ranksep: 120,\n });\n workflow.nodes.forEach((node): void => {\n graph.setNode(node.id, {\n height: FLOW_NODE_LAYOUT_HEIGHT,\n width: FLOW_NODE_LAYOUT_WIDTH,\n });\n });\n workflow.edges.forEach((edge): void => {\n graph.setEdge(edge.source, edge.target);\n });\n dagre.layout(graph);\n\n return {\n ...workflow,\n nodes: workflow.nodes.map((node): WorkflowNode => {\n const positionedNode = graph.node(node.id) as\n | { readonly x: number; readonly y: number }\n | undefined;\n\n return positionedNode\n ? {\n ...node,\n position: {\n x: positionedNode.x - FLOW_NODE_LAYOUT_WIDTH / 2,\n y: positionedNode.y - FLOW_NODE_LAYOUT_HEIGHT / 2,\n },\n }\n : node;\n }),\n };\n}\n\nfunction readRuntimeFlowEdges(workflow: WorkflowDefinition): RuntimeFlowEdge[] {\n return workflow.edges.map((edge): RuntimeFlowEdge => {\n const label = readEdgeLabel(edge);\n\n return {\n animated: false,\n id: edge.id,\n label,\n labelBgBorderRadius: 6,\n labelBgPadding: [8, 4],\n labelBgStyle: {\n fill: edge.data.isDefault ? '#f8fafc' : '#eff6ff',\n stroke: edge.data.isDefault ? '#64748b' : '#2563eb',\n strokeWidth: 1,\n },\n labelShowBg: Boolean(label),\n labelStyle: {\n fill: edge.data.isDefault ? '#475569' : '#2563eb',\n fontSize: 12,\n fontWeight: 600,\n },\n source: edge.source,\n style: {\n stroke: '#475569',\n strokeWidth: 1.5,\n },\n target: edge.target,\n type: edge.type ?? 'smoothstep',\n };\n });\n}\n\nfunction readNodeStyle(tone: RuntimeTone): CSSProperties {\n if (tone === 'current') {\n return {\n ...NODE_STYLE,\n border: '1px solid var(--mzn-color-primary, #0057ff)',\n boxShadow: '0 0 0 3px rgba(0, 87, 255, 0.14)',\n };\n }\n\n if (tone === 'completed') {\n return {\n ...NODE_STYLE,\n border: '1px solid #16a34a',\n };\n }\n\n if (tone === 'cancelled') {\n return {\n ...NODE_STYLE,\n border: '1px solid #dc2626',\n opacity: 0.72,\n };\n }\n\n if (tone === 'waiting') {\n return {\n ...NODE_STYLE,\n border: '1px dashed #64748b',\n };\n }\n\n return NODE_STYLE;\n}\n\nfunction readNodeStatusStyle(tone: RuntimeTone): CSSProperties {\n const baseStyle = NODE_STATUS_STYLE;\n\n if (tone === 'current') {\n return { ...baseStyle, background: '#eff6ff', color: '#2563eb' };\n }\n\n if (tone === 'completed') {\n return { ...baseStyle, background: '#f0fdf4', color: '#15803d' };\n }\n\n if (tone === 'cancelled') {\n return { ...baseStyle, background: '#fef2f2', color: '#dc2626' };\n }\n\n if (tone === 'waiting') {\n return { ...baseStyle, background: '#f8fafc', color: '#475569' };\n }\n\n return { ...baseStyle, background: '#f1f5f9', color: '#64748b' };\n}\n\nfunction WorkflowRuntimeNodeCard({\n data,\n}: NodeProps<RuntimeFlowNode>): ReactElement {\n return (\n <div style={readNodeStyle(data.tone)}>\n <Handle\n isConnectable={false}\n position={Position.Left}\n style={NODE_HANDLE_STYLE}\n type=\"target\"\n />\n <Typography\n component=\"span\"\n ellipsis\n title={data.label}\n variant=\"label-primary\"\n >\n {data.label}\n </Typography>\n <span style={readNodeStatusStyle(data.tone)}>{data.statusLabel}</span>\n <span title={data.secondaryLabel} style={NODE_SECONDARY_STYLE}>\n {data.secondaryLabel || data.kindLabel}\n </span>\n <Handle\n isConnectable={false}\n position={Position.Right}\n style={NODE_HANDLE_STYLE}\n type=\"source\"\n />\n </div>\n );\n}\n"],"mappings":"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"}
|