@rytass/bpm-core-react 0.18.0 → 0.19.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.
Files changed (283) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/chunks/{FormBuilderView-BVKY1j_0.js → FormBuilderView-Djlm3y4S.js} +485 -481
  3. package/dist/chunks/FormBuilderView-Djlm3y4S.js.map +1 -0
  4. package/dist/chunks/FormBuilderView-G6uRSywl.cjs +3 -0
  5. package/dist/chunks/FormBuilderView-G6uRSywl.cjs.map +1 -0
  6. package/dist/chunks/{FormRendererView-BsTwZkqU.js → FormRendererView-DHfVgbo6.js} +511 -274
  7. package/dist/chunks/FormRendererView-DHfVgbo6.js.map +1 -0
  8. package/dist/chunks/FormRendererView-DwfFbaip.cjs +6 -0
  9. package/dist/chunks/FormRendererView-DwfFbaip.cjs.map +1 -0
  10. package/dist/chunks/admin-pickers-BjbkBpSJ.cjs +2 -0
  11. package/dist/chunks/admin-pickers-BjbkBpSJ.cjs.map +1 -0
  12. package/dist/chunks/{admin-pickers-Djq3h-UR.js → admin-pickers-DfGxsjpp.js} +42 -42
  13. package/dist/chunks/admin-pickers-DfGxsjpp.js.map +1 -0
  14. package/dist/chunks/{approval-instance-list-page-CPXMP3PL.js → approval-instance-list-page-BnI4t5mD.js} +7 -8
  15. package/dist/chunks/{approval-instance-list-page-CPXMP3PL.js.map → approval-instance-list-page-BnI4t5mD.js.map} +1 -1
  16. package/dist/chunks/{approval-instance-list-page-ax0pm8bt.cjs → approval-instance-list-page-fqvmkBlg.cjs} +2 -2
  17. package/dist/chunks/{approval-instance-list-page-ax0pm8bt.cjs.map → approval-instance-list-page-fqvmkBlg.cjs.map} +1 -1
  18. package/dist/chunks/auth-provider-4BeCw7cI.cjs.map +1 -1
  19. package/dist/chunks/{auth-provider-B5oPmvk2.js → auth-provider-C2b-5mGt.js} +2 -3
  20. package/dist/chunks/{auth-provider-B5oPmvk2.js.map → auth-provider-C2b-5mGt.js.map} +1 -1
  21. package/dist/chunks/{bpm-form-field-Cao0rMol.js → bpm-form-field-9B-Det0u.js} +2 -3
  22. package/dist/chunks/{bpm-form-field-Cao0rMol.js.map → bpm-form-field-9B-Det0u.js.map} +1 -1
  23. package/dist/chunks/bpm-form-field-Bc6k4ZEO.cjs.map +1 -1
  24. package/dist/chunks/{categories-riC33J_j.js → categories-BAdxjNSA.js} +14 -15
  25. package/dist/chunks/{categories-riC33J_j.js.map → categories-BAdxjNSA.js.map} +1 -1
  26. package/dist/chunks/{categories-AxxhqjLZ.cjs → categories-DQUtVEiV.cjs} +2 -2
  27. package/dist/chunks/{categories-AxxhqjLZ.cjs.map → categories-DQUtVEiV.cjs.map} +1 -1
  28. package/dist/chunks/{compose-B1GlrZW9.js → compose-D6zBIc2Z.js} +131 -148
  29. package/dist/chunks/compose-D6zBIc2Z.js.map +1 -0
  30. package/dist/chunks/compose-NH6dsFXD.cjs +2 -0
  31. package/dist/chunks/compose-NH6dsFXD.cjs.map +1 -0
  32. package/dist/chunks/{dashboard-page-DdBvV6YI.js → dashboard-page-BoqNhjT_.js} +5 -6
  33. package/dist/chunks/{dashboard-page-DdBvV6YI.js.map → dashboard-page-BoqNhjT_.js.map} +1 -1
  34. package/dist/chunks/{dashboard-page-BWQBSGDq.cjs → dashboard-page-D7YJ3udk.cjs} +2 -2
  35. package/dist/chunks/{dashboard-page-BWQBSGDq.cjs.map → dashboard-page-D7YJ3udk.cjs.map} +1 -1
  36. package/dist/chunks/{delegations-MxF3uJGW.js → delegations-BfhCDz5e.js} +15 -16
  37. package/dist/chunks/{delegations-MxF3uJGW.js.map → delegations-BfhCDz5e.js.map} +1 -1
  38. package/dist/chunks/{delegations-Ckf03icM.cjs → delegations-BmFGcuhA.cjs} +2 -2
  39. package/dist/chunks/{delegations-Ckf03icM.cjs.map → delegations-BmFGcuhA.cjs.map} +1 -1
  40. package/dist/chunks/{delegations-V9HIe3_P.cjs → delegations-CcS0SHbf.cjs} +2 -2
  41. package/dist/chunks/{delegations-V9HIe3_P.cjs.map → delegations-CcS0SHbf.cjs.map} +1 -1
  42. package/dist/chunks/{delegations-xUt1tj8d.js → delegations-DBh5TT6G.js} +16 -17
  43. package/dist/chunks/{delegations-xUt1tj8d.js.map → delegations-DBh5TT6G.js.map} +1 -1
  44. package/dist/chunks/designer-Be9UI9Tg.cjs +65 -0
  45. package/dist/chunks/designer-Be9UI9Tg.cjs.map +1 -0
  46. package/dist/chunks/{designer-BCLrjb4H.js → designer-uhC_7m2i.js} +1791 -1407
  47. package/dist/chunks/designer-uhC_7m2i.js.map +1 -0
  48. package/dist/chunks/detail-6uw5dmTi.cjs +5 -0
  49. package/dist/chunks/detail-6uw5dmTi.cjs.map +1 -0
  50. package/dist/chunks/{detail-4F39ggBn.js → detail-_GeKqNC-.js} +1012 -972
  51. package/dist/chunks/detail-_GeKqNC-.js.map +1 -0
  52. package/dist/chunks/{format-date-time-CB-LxzqT.js → format-date-time-B0LdmWg4.js} +2 -3
  53. package/dist/chunks/{format-date-time-CB-LxzqT.js.map → format-date-time-B0LdmWg4.js.map} +1 -1
  54. package/dist/chunks/format-date-time-D-cx5M8z.cjs.map +1 -1
  55. package/dist/chunks/{format-member-label-DudVI55w.js → format-member-label-C73FuP-d.js} +2 -3
  56. package/dist/chunks/{format-member-label-DudVI55w.js.map → format-member-label-C73FuP-d.js.map} +1 -1
  57. package/dist/chunks/format-member-label-t7ANTF62.cjs.map +1 -1
  58. package/dist/chunks/{approver-filled-form-Dm3Iw7iw.cjs → instance-error-message-DTARGbGo.cjs} +2 -2
  59. package/dist/chunks/instance-error-message-DTARGbGo.cjs.map +1 -0
  60. package/dist/chunks/{approver-filled-form-ZEwpmsHJ.js → instance-error-message-q6gy5evy.js} +50 -38
  61. package/dist/chunks/instance-error-message-q6gy5evy.js.map +1 -0
  62. package/dist/chunks/language-provider-Bdnx3Gxl.cjs.map +1 -1
  63. package/dist/chunks/{language-provider-B3cEbLe4.js → language-provider-phkWOapf.js} +2 -3
  64. package/dist/chunks/{language-provider-B3cEbLe4.js.map → language-provider-phkWOapf.js.map} +1 -1
  65. package/dist/chunks/{login-C6qlTC6F.js → login-D6cc3bo7.js} +4 -5
  66. package/dist/chunks/{login-C6qlTC6F.js.map → login-D6cc3bo7.js.map} +1 -1
  67. package/dist/chunks/{login-AtVxZBsC.cjs → login-uvVcltrS.cjs} +2 -2
  68. package/dist/chunks/{login-AtVxZBsC.cjs.map → login-uvVcltrS.cjs.map} +1 -1
  69. package/dist/chunks/notifications-Bc4mgSds.cjs.map +1 -1
  70. package/dist/chunks/{notifications-DJ5wzCye.js → notifications-Cvme5Qbl.js} +2 -3
  71. package/dist/chunks/{notifications-DJ5wzCye.js.map → notifications-Cvme5Qbl.js.map} +1 -1
  72. package/dist/chunks/orgs-B_2J2tLX.cjs +2 -0
  73. package/dist/chunks/{orgs-BeeDDWL1.cjs.map → orgs-B_2J2tLX.cjs.map} +1 -1
  74. package/dist/chunks/{orgs-8hje_l2n.js → orgs-DqxMds26.js} +48 -49
  75. package/dist/chunks/{orgs-8hje_l2n.js.map → orgs-DqxMds26.js.map} +1 -1
  76. package/dist/chunks/{providers-B_d5tbCL.js → providers-BbCs23sk.js} +21 -25
  77. package/dist/chunks/{providers-B_d5tbCL.js.map → providers-BbCs23sk.js.map} +1 -1
  78. package/dist/chunks/{providers-chuJvMgv.cjs → providers-D_KAgOOu.cjs} +2 -2
  79. package/dist/chunks/{providers-chuJvMgv.cjs.map → providers-D_KAgOOu.cjs.map} +1 -1
  80. package/dist/chunks/router-adapter--gYs13E8.cjs.map +1 -1
  81. package/dist/chunks/{router-adapter-DftlFTOd.js → router-adapter-CkxCyzf5.js} +2 -3
  82. package/dist/chunks/{router-adapter-DftlFTOd.js.map → router-adapter-CkxCyzf5.js.map} +1 -1
  83. package/dist/chunks/{routes-config-yZbESPlw.js → routes-config-BcNaWJWJ.js} +2 -3
  84. package/dist/chunks/{routes-config-yZbESPlw.js.map → routes-config-BcNaWJWJ.js.map} +1 -1
  85. package/dist/chunks/routes-config-C1j_vFKo.cjs.map +1 -1
  86. package/dist/chunks/task-decision-3d17ZvZE.js +29 -0
  87. package/dist/chunks/task-decision-3d17ZvZE.js.map +1 -0
  88. package/dist/chunks/task-decision-CqZ4WQOC.cjs +2 -0
  89. package/dist/chunks/task-decision-CqZ4WQOC.cjs.map +1 -0
  90. package/dist/chunks/{use-bpm-member-D57LKe_u.js → use-bpm-member-BPzcNU1g.js} +3 -4
  91. package/dist/chunks/{use-bpm-member-D57LKe_u.js.map → use-bpm-member-BPzcNU1g.js.map} +1 -1
  92. package/dist/chunks/use-bpm-member-DpNAQtNC.cjs.map +1 -1
  93. package/dist/chunks/{users-Pl6hY5Y5.js → users-BBtiZ9QQ.js} +22 -25
  94. package/dist/chunks/{users-Pl6hY5Y5.js.map → users-BBtiZ9QQ.js.map} +1 -1
  95. package/dist/chunks/{users-O2L_M3BK.cjs → users-EqSzDhuj.cjs} +2 -2
  96. package/dist/chunks/{users-O2L_M3BK.cjs.map → users-EqSzDhuj.cjs.map} +1 -1
  97. package/dist/components/admin-picker-options.d.cts +11 -0
  98. package/dist/components/admin-picker-options.d.ts +11 -0
  99. package/dist/components/admin-pickers.d.cts +2 -11
  100. package/dist/components/admin-pickers.d.ts +2 -11
  101. package/dist/index.cjs +1 -1
  102. package/dist/index.cjs.map +1 -1
  103. package/dist/index.js +17 -19
  104. package/dist/index.js.map +1 -1
  105. package/dist/lib/task-decision.d.cts +16 -0
  106. package/dist/lib/task-decision.d.ts +16 -0
  107. package/dist/lib/use-org-unit-names.d.cts +10 -0
  108. package/dist/lib/use-org-unit-names.d.ts +10 -0
  109. package/dist/next/index.cjs +1 -1
  110. package/dist/next/index.cjs.map +1 -1
  111. package/dist/next/index.js +7 -8
  112. package/dist/next/index.js.map +1 -1
  113. package/dist/next/workflow-chat-route.cjs +19 -1
  114. package/dist/next/workflow-chat-route.cjs.map +1 -1
  115. package/dist/next/workflow-chat-route.js +2 -3
  116. package/dist/next/workflow-chat-route.js.map +1 -1
  117. package/dist/pages/admin/delegations/index.cjs +1 -1
  118. package/dist/pages/admin/delegations/index.cjs.map +1 -1
  119. package/dist/pages/admin/delegations/index.js +2 -3
  120. package/dist/pages/admin/orgs/index.cjs +1 -1
  121. package/dist/pages/admin/orgs/index.cjs.map +1 -1
  122. package/dist/pages/admin/orgs/index.js +2 -3
  123. package/dist/pages/admin/users/index.cjs +1 -1
  124. package/dist/pages/admin/users/index.cjs.map +1 -1
  125. package/dist/pages/admin/users/index.js +2 -3
  126. package/dist/pages/admin/webhook-endpoints/index.cjs.map +1 -1
  127. package/dist/pages/admin/webhook-endpoints/index.js +1 -2
  128. package/dist/pages/cc/index.cjs.map +1 -1
  129. package/dist/pages/cc/index.js +1 -2
  130. package/dist/pages/dashboard/index.cjs.map +1 -1
  131. package/dist/pages/dashboard/index.js +1 -2
  132. package/dist/pages/delegations/index.cjs +1 -1
  133. package/dist/pages/delegations/index.cjs.map +1 -1
  134. package/dist/pages/delegations/index.js +2 -3
  135. package/dist/pages/inbox/index.cjs.map +1 -1
  136. package/dist/pages/inbox/index.js +1 -2
  137. package/dist/pages/instances/detail/index.cjs +1 -1
  138. package/dist/pages/instances/detail/index.cjs.map +1 -1
  139. package/dist/pages/instances/detail/index.js +2 -3
  140. package/dist/pages/instances/new/index.cjs.map +1 -1
  141. package/dist/pages/instances/new/index.js +1 -2
  142. package/dist/pages/login/index.cjs +1 -1
  143. package/dist/pages/login/index.cjs.map +1 -1
  144. package/dist/pages/login/index.js +2 -3
  145. package/dist/pages/root/index.cjs.map +1 -1
  146. package/dist/pages/root/index.js +1 -2
  147. package/dist/pages/search/index.cjs.map +1 -1
  148. package/dist/pages/search/index.js +1 -2
  149. package/dist/pages/sent/index.cjs.map +1 -1
  150. package/dist/pages/sent/index.js +1 -2
  151. package/dist/pages/settings/notifications/index.cjs.map +1 -1
  152. package/dist/pages/settings/notifications/index.js +2 -3
  153. package/dist/pages/templates/categories/index.cjs +1 -1
  154. package/dist/pages/templates/categories/index.cjs.map +1 -1
  155. package/dist/pages/templates/categories/index.js +2 -3
  156. package/dist/pages/templates/compose/index.cjs +1 -1
  157. package/dist/pages/templates/compose/index.cjs.map +1 -1
  158. package/dist/pages/templates/compose/index.js +2 -3
  159. package/dist/pages/templates/designer/index.cjs +1 -1
  160. package/dist/pages/templates/designer/index.cjs.map +1 -1
  161. package/dist/pages/templates/designer/index.js +2 -3
  162. package/dist/pages/templates/index.cjs.map +1 -1
  163. package/dist/pages/templates/index.js +1 -2
  164. package/dist/pages/templates/versions/index.cjs.map +1 -1
  165. package/dist/pages/templates/versions/index.js +1 -2
  166. package/dist/views/admin/delegations/index.cjs +1 -1
  167. package/dist/views/admin/delegations/index.js +1 -1
  168. package/dist/views/admin/index.cjs +1 -1
  169. package/dist/views/admin/index.js +3 -3
  170. package/dist/views/admin/orgs/index.cjs +1 -1
  171. package/dist/views/admin/orgs/index.js +1 -1
  172. package/dist/views/admin/users/index.cjs +1 -1
  173. package/dist/views/admin/users/index.js +1 -1
  174. package/dist/views/admin/webhook-endpoints/index.cjs +1 -1
  175. package/dist/views/admin/webhook-endpoints/index.cjs.map +1 -1
  176. package/dist/views/admin/webhook-endpoints/index.js +52 -53
  177. package/dist/views/admin/webhook-endpoints/index.js.map +1 -1
  178. package/dist/views/cc/index.cjs +1 -1
  179. package/dist/views/cc/index.cjs.map +1 -1
  180. package/dist/views/cc/index.js +2 -3
  181. package/dist/views/dashboard/index.cjs +1 -1
  182. package/dist/views/dashboard/index.cjs.map +1 -1
  183. package/dist/views/dashboard/index.js +2 -3
  184. package/dist/views/delegations/index.cjs +1 -1
  185. package/dist/views/delegations/index.js +1 -1
  186. package/dist/views/forms/builder/index.cjs +1 -1
  187. package/dist/views/forms/builder/index.js +1 -1
  188. package/dist/views/forms/renderer/FormRendererView.d.cts +24 -1
  189. package/dist/views/forms/renderer/FormRendererView.d.ts +24 -1
  190. package/dist/views/forms/renderer/file-upload-field.d.cts +84 -0
  191. package/dist/views/forms/renderer/file-upload-field.d.ts +84 -0
  192. package/dist/views/forms/renderer/form-value-readers.d.cts +7 -0
  193. package/dist/views/forms/renderer/form-value-readers.d.ts +7 -0
  194. package/dist/views/forms/renderer/index.cjs +1 -1
  195. package/dist/views/forms/renderer/index.d.cts +1 -0
  196. package/dist/views/forms/renderer/index.d.ts +1 -0
  197. package/dist/views/forms/renderer/index.js +1 -1
  198. package/dist/views/forms/renderer/org-unit-field-options.d.cts +44 -0
  199. package/dist/views/forms/renderer/org-unit-field-options.d.ts +44 -0
  200. package/dist/views/forms/renderer/org-unit-field.d.cts +23 -0
  201. package/dist/views/forms/renderer/org-unit-field.d.ts +23 -0
  202. package/dist/views/inbox/index.cjs +1 -1
  203. package/dist/views/inbox/index.cjs.map +1 -1
  204. package/dist/views/inbox/index.js +133 -137
  205. package/dist/views/inbox/index.js.map +1 -1
  206. package/dist/views/instances/approver-filled-form.d.cts +9 -2
  207. package/dist/views/instances/approver-filled-form.d.ts +9 -2
  208. package/dist/views/instances/detail/index.cjs +1 -1
  209. package/dist/views/instances/detail/index.js +1 -1
  210. package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +19 -2
  211. package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +19 -2
  212. package/dist/views/instances/detail/sections/InstanceHistorySection.d.cts +8 -1
  213. package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +8 -1
  214. package/dist/views/instances/detail/sections/container-helpers.d.cts +0 -1
  215. package/dist/views/instances/detail/sections/container-helpers.d.ts +0 -1
  216. package/dist/views/instances/detail/sections/shared.d.cts +3 -4
  217. package/dist/views/instances/detail/sections/shared.d.ts +3 -4
  218. package/dist/views/instances/instance-error-message.d.cts +5 -0
  219. package/dist/views/instances/instance-error-message.d.ts +5 -0
  220. package/dist/views/instances/new/index.cjs +1 -1
  221. package/dist/views/instances/new/index.cjs.map +1 -1
  222. package/dist/views/instances/new/index.js +78 -77
  223. package/dist/views/instances/new/index.js.map +1 -1
  224. package/dist/views/login/index.cjs +1 -1
  225. package/dist/views/login/index.js +1 -1
  226. package/dist/views/search/index.cjs +1 -1
  227. package/dist/views/search/index.cjs.map +1 -1
  228. package/dist/views/search/index.js +2 -3
  229. package/dist/views/sent/index.cjs +1 -1
  230. package/dist/views/sent/index.cjs.map +1 -1
  231. package/dist/views/sent/index.js +2 -3
  232. package/dist/views/settings/index.js +1 -1
  233. package/dist/views/settings/notifications/index.js +1 -1
  234. package/dist/views/templates/categories/index.cjs +1 -1
  235. package/dist/views/templates/categories/index.js +1 -1
  236. package/dist/views/templates/compose/index.cjs +1 -1
  237. package/dist/views/templates/compose/index.js +1 -1
  238. package/dist/views/templates/designer/approver-resolver-model.d.cts +211 -0
  239. package/dist/views/templates/designer/approver-resolver-model.d.ts +211 -0
  240. package/dist/views/templates/designer/dry-run-assignee-label.d.cts +2 -0
  241. package/dist/views/templates/designer/dry-run-assignee-label.d.ts +2 -0
  242. package/dist/views/templates/designer/dry-run-sample-data.d.cts +6 -0
  243. package/dist/views/templates/designer/dry-run-sample-data.d.ts +6 -0
  244. package/dist/views/templates/designer/dynamic-form-resolver-options.d.cts +25 -0
  245. package/dist/views/templates/designer/dynamic-form-resolver-options.d.ts +25 -0
  246. package/dist/views/templates/designer/index.cjs +1 -1
  247. package/dist/views/templates/designer/index.js +1 -1
  248. package/dist/views/templates/designer/node-actor-resolver-options.d.cts +38 -0
  249. package/dist/views/templates/designer/node-actor-resolver-options.d.ts +38 -0
  250. package/dist/views/templates/index.cjs +1 -1
  251. package/dist/views/templates/index.cjs.map +1 -1
  252. package/dist/views/templates/index.js +50 -51
  253. package/dist/views/templates/index.js.map +1 -1
  254. package/dist/views/templates/versions/index.cjs +1 -1
  255. package/dist/views/templates/versions/index.cjs.map +1 -1
  256. package/dist/views/templates/versions/index.js +7 -8
  257. package/dist/views/templates/versions/index.js.map +1 -1
  258. package/package.json +3 -3
  259. package/dist/chunks/FormBuilderView-BVKY1j_0.js.map +0 -1
  260. package/dist/chunks/FormBuilderView-SrGltzFT.cjs +0 -3
  261. package/dist/chunks/FormBuilderView-SrGltzFT.cjs.map +0 -1
  262. package/dist/chunks/FormRendererView-BsTwZkqU.js.map +0 -1
  263. package/dist/chunks/FormRendererView-GpsE03np.cjs +0 -4
  264. package/dist/chunks/FormRendererView-GpsE03np.cjs.map +0 -1
  265. package/dist/chunks/admin-pickers-BRHk3qKq.cjs +0 -2
  266. package/dist/chunks/admin-pickers-BRHk3qKq.cjs.map +0 -1
  267. package/dist/chunks/admin-pickers-Djq3h-UR.js.map +0 -1
  268. package/dist/chunks/approver-filled-form-Dm3Iw7iw.cjs.map +0 -1
  269. package/dist/chunks/approver-filled-form-ZEwpmsHJ.js.map +0 -1
  270. package/dist/chunks/compose-B1GlrZW9.js.map +0 -1
  271. package/dist/chunks/compose-DZk-SfHT.cjs +0 -2
  272. package/dist/chunks/compose-DZk-SfHT.cjs.map +0 -1
  273. package/dist/chunks/designer-BCLrjb4H.js.map +0 -1
  274. package/dist/chunks/designer-BYYxEN9L.cjs +0 -65
  275. package/dist/chunks/designer-BYYxEN9L.cjs.map +0 -1
  276. package/dist/chunks/detail-4F39ggBn.js.map +0 -1
  277. package/dist/chunks/detail-BkMtA_0K.cjs +0 -2
  278. package/dist/chunks/detail-BkMtA_0K.cjs.map +0 -1
  279. package/dist/chunks/orgs-BeeDDWL1.cjs +0 -2
  280. package/dist/chunks/task-node-label-BF6UllxP.cjs +0 -2
  281. package/dist/chunks/task-node-label-BF6UllxP.cjs.map +0 -1
  282. package/dist/chunks/task-node-label-CWZgOBj0.js +0 -9
  283. package/dist/chunks/task-node-label-CWZgOBj0.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-pickers-DfGxsjpp.js","names":["styles","formatMemberLabel","readOrgUnitOption","orgUnit","readPositionOption","position","admin_pickers_module_default","PICKER_MENU_MAX_HEIGHT","MemberPicker","loading","setLoading","useState","options","setOptions","value","handleSearch","searchMembers","searchText","readMemberOption","AutoComplete","onChange","readMemberOptionFromValue","option","readUniqueOption","open","mergeMemberOptions","OrgUnitPicker","useMemo","orgUnits","Select","readOrgUnitOptionFromValue","PositionPicker","positions","readPositionOptionFromValue","member","isRecord","email","id","name","normalized","matched","selected"],"sources":["../../src/components/admin-picker-options.ts","../../src/components/admin-pickers.module.scss","../../src/components/admin-pickers.tsx"],"sourcesContent":["import type {\n OrgUnitRecord,\n PositionRecord,\n} from '@rytass/bpm-core-client/organization';\n\nexport type OrgUnitOption = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport type PositionOption = Readonly<{\n id: string;\n name: string;\n}>;\n\nexport function readOrgUnitOption(orgUnit: OrgUnitRecord): OrgUnitOption {\n return { id: orgUnit.id, name: `${orgUnit.name} · ${orgUnit.code}` };\n}\n\nexport function readPositionOption(position: PositionRecord): PositionOption {\n return { id: position.id, name: `${position.name} · ${position.code}` };\n}\n",".pickerHost {\n width: 100%;\n min-width: 0;\n\n :global(.mzn-auto-complete),\n :global(.mzn-input),\n :global(.mzn-input-container),\n :global(.mzn-select),\n :global(.mzn-select-trigger),\n :global(.mzn-text-field) {\n width: 100%;\n min-width: 0 !important;\n }\n}\n","'use client';\n\nimport { useMemo, useState, type ReactElement } from 'react';\nimport { AutoComplete, Select } from '@mezzanine-ui/react';\nimport { searchMembers } from '@rytass/bpm-core-client';\nimport type {\n OrgUnitRecord,\n PositionRecord,\n} from '@rytass/bpm-core-client/organization';\nimport { formatMemberLabel } from '../lib/format-member-label';\nimport {\n type OrgUnitOption,\n type PositionOption,\n readOrgUnitOption,\n readPositionOption,\n} from './admin-picker-options';\nimport styles from './admin-pickers.module.scss';\n\nexport {\n type OrgUnitOption,\n type PositionOption,\n readOrgUnitOption,\n readPositionOption,\n};\n\nexport type MemberOption = Readonly<{\n email: string;\n id: string;\n name: string;\n}>;\n\n// Without a cap the Mezzanine dropdown grows with its options and never\n// mounts its scrollbar, so a long org-unit or position list runs off the\n// viewport with no way to reach the items below the fold. The pickers also\n// set `flip`: near the bottom of a modal the capped menu still overflows\n// unless it may open upwards.\nconst PICKER_MENU_MAX_HEIGHT = 320;\n\ninterface MemberPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: MemberOption | null) => void;\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: MemberOption | null;\n}\n\ninterface OrgUnitPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: OrgUnitOption | null) => void;\n readonly orgUnits: readonly OrgUnitRecord[];\n readonly placeholder?: string;\n readonly size?: 'main' | 'sub';\n readonly value: OrgUnitOption | null;\n}\n\ninterface PositionPickerProps {\n readonly disabled?: boolean;\n readonly name: string;\n readonly onChange: (option: PositionOption | null) => void;\n readonly placeholder?: string;\n readonly positions: readonly PositionRecord[];\n readonly size?: 'main' | 'sub';\n readonly value: PositionOption | null;\n}\n\n/**\n * AutoComplete-backed picker that searches the BPM member directory via\n * `searchMembers()`. Emits a {@link MemberOption} `{ id, name, email }`\n * on selection (or `null` when cleared).\n */\nexport function MemberPicker({\n disabled = false,\n name,\n onChange,\n placeholder = '搜尋姓名或信箱',\n size,\n value,\n}: MemberPickerProps): ReactElement {\n const [loading, setLoading] = useState(false);\n const [options, setOptions] = useState<readonly MemberOption[]>(\n value ? [value] : [],\n );\n\n async function handleSearch(searchText: string): Promise<void> {\n setLoading(true);\n try {\n setOptions((await searchMembers(searchText)).map(readMemberOption));\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <div className={styles.pickerHost}>\n <AutoComplete\n asyncData\n disabled={disabled}\n disabledOptionsFilter\n emptyText=\"沒有符合的會員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name,\n spellCheck: false,\n }}\n loading={loading}\n loadingText=\"搜尋會員中...\"\n mode=\"single\"\n onChange={(option): void => onChange(readMemberOptionFromValue(option))}\n onSearch={handleSearch}\n onSearchTextChange={(searchText): void =>\n onChange(readUniqueOption(searchText, options))\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearch('');\n }\n }}\n options={[...mergeMemberOptions(value ? [value] : [], options)]}\n placeholder={placeholder}\n searchDebounceTime={300}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of org units. Caller is\n * responsible for fetching the org units (typically via\n * `readOrganizationDashboard` from `@rytass/bpm-core-client/organization`).\n */\nexport function OrgUnitPicker({\n disabled = false,\n onChange,\n orgUnits,\n placeholder = '選擇組織',\n size,\n value,\n}: OrgUnitPickerProps): ReactElement {\n const options = useMemo(\n (): readonly OrgUnitOption[] => orgUnits.map(readOrgUnitOption),\n [orgUnits],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readOrgUnitOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\n/**\n * Static `<Select>` over a pre-fetched list of positions.\n */\nexport function PositionPicker({\n disabled = false,\n onChange,\n placeholder = '選擇職位',\n positions,\n size,\n value,\n}: PositionPickerProps): ReactElement {\n const options = useMemo(\n (): readonly PositionOption[] => positions.map(readPositionOption),\n [positions],\n );\n return (\n <div className={styles.pickerHost}>\n <Select\n clearable\n disabled={disabled}\n flip\n fullWidth\n menuMaxHeight={PICKER_MENU_MAX_HEIGHT}\n onChange={(option): void => onChange(readPositionOptionFromValue(option))}\n options={[...options]}\n placeholder={placeholder}\n size={size}\n value={value}\n />\n </div>\n );\n}\n\nexport function readMemberOption(member: {\n readonly email: string;\n readonly memberId: string;\n readonly name: string;\n}): MemberOption {\n return {\n email: member.email,\n id: member.memberId,\n name: formatMemberLabel(member.name, member.email, 'dot'),\n };\n}\n\nfunction readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) return null;\n const email = value.email;\n const id = value.id;\n const name = value.name;\n return typeof email === 'string' &&\n typeof id === 'string' &&\n typeof name === 'string'\n ? { email, id, name }\n : null;\n}\n\nfunction readOrgUnitOptionFromValue(value: unknown): OrgUnitOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readPositionOptionFromValue(value: unknown): PositionOption | null {\n if (!isRecord(value)) return null;\n const id = value.id;\n const name = value.name;\n return typeof id === 'string' && typeof name === 'string'\n ? { id, name }\n : null;\n}\n\nfunction readUniqueOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalized = searchText.trim().toLocaleLowerCase();\n if (!normalized) return null;\n const matched = options.filter(\n (option) =>\n option.id.toLocaleLowerCase() === normalized ||\n option.email.toLocaleLowerCase() === normalized ||\n option.name.toLocaleLowerCase() === normalized,\n );\n return matched.length === 1 ? matched[0] : null;\n}\n\nfunction mergeMemberOptions(\n selected: readonly MemberOption[],\n options: readonly MemberOption[],\n): readonly MemberOption[] {\n const byId = new Map(\n [...selected, ...options].map(\n (option): readonly [string, MemberOption] => [option.id, option],\n ),\n );\n return [...byId.values()];\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { r as e } from "./router-adapter-DftlFTOd.js";
3
- import { t } from "./format-date-time-CB-LxzqT.js";
4
- import { r as n } from "./routes-config-yZbESPlw.js";
2
+ import { r as e } from "./router-adapter-CkxCyzf5.js";
3
+ import { r as t } from "./routes-config-BcNaWJWJ.js";
4
+ import { t as n } from "./format-date-time-B0LdmWg4.js";
5
5
  import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
6
6
  import { Filter as c, FilterArea as ee, FilterLine as te, FormField as l, Input as u, PageHeader as d, Section as ne, SectionGroup as f, Select as p, Table as m, Typography as h } from "@mezzanine-ui/react";
7
7
  import { resolveMembers as re } from "@rytass/bpm-core-client";
@@ -56,7 +56,7 @@ import '../approval-instance-list-page.css';var S = { instanceFilterArea: "bpm_i
56
56
  }
57
57
  ];
58
58
  function T({ defaultState: y, description: T, emptyMessage: O, searchPlaceholder: k, title: N, view: P }) {
59
- let F = e(), I = n(), [L, R] = s(null), [z, B] = s(/* @__PURE__ */ new Map()), [V, H] = s(1), [U, W] = s(10), [G, K] = s(0), [q, J] = s(!0), [Y, se] = s([]), [X, ce] = s(""), [Z, le] = s(D(y)), Q = o(0), $ = r(async () => {
59
+ let F = e(), I = t(), [L, R] = s(null), [z, B] = s(/* @__PURE__ */ new Map()), [V, H] = s(1), [U, W] = s(10), [G, K] = s(0), [q, J] = s(!0), [Y, se] = s([]), [X, ce] = s(""), [Z, le] = s(D(y)), Q = o(0), $ = r(async () => {
60
60
  let e = Q.current + 1;
61
61
  Q.current = e, J(!0), R(null);
62
62
  try {
@@ -137,7 +137,7 @@ function T({ defaultState: y, description: T, emptyMessage: O, searchPlaceholder
137
137
  render: (e) => /* @__PURE__ */ _(h, {
138
138
  component: "span",
139
139
  variant: "body",
140
- children: t(e.startedAt)
140
+ children: n(e.startedAt)
141
141
  }),
142
142
  title: "發起時間",
143
143
  width: 220
@@ -147,7 +147,7 @@ function T({ defaultState: y, description: T, emptyMessage: O, searchPlaceholder
147
147
  render: (e) => /* @__PURE__ */ _(h, {
148
148
  component: "span",
149
149
  variant: "body",
150
- children: t(e.completedAt)
150
+ children: n(e.completedAt)
151
151
  }),
152
152
  title: "完成時間",
153
153
  width: 220
@@ -274,7 +274,6 @@ function j(e, t) {
274
274
  function M(e) {
275
275
  return e instanceof Error ? e.message : "讀取簽核案件失敗。";
276
276
  }
277
- //#endregion
278
277
  export { T as t };
279
278
 
280
- //# sourceMappingURL=approval-instance-list-page-CPXMP3PL.js.map
279
+ //# sourceMappingURL=approval-instance-list-page-BnI4t5mD.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"approval-instance-list-page-CPXMP3PL.js","names":["_Fragment","styles","useRouterAdapter","useBPMRoutes","Fragment$1","ContentHeader","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","STATE_FILTER_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","useState","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","refreshRequestIdRef","useRef","refreshInstances","useCallback","requestId","result","listApprovalInstancesPage","readApprovalInstanceRow","requestError","readErrorMessage","view","useEffect","initiatorMemberIds","row","cancelled","profiles","resolveMembers","profile","columns","useMemo","Typography","readInstanceStateColor","record","readInitiatorLabel","formatDateTime","tableActions","PageHeader","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","searchPlaceholder","Select","readSelectedStateFilterOption","option","readStateFilterLabel","value","emptyMessage","Table","page","pageSize","from","to","total","instance","readApprovalInstanceCaseTitle","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":[".instanceFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const refreshRequestIdRef = useRef(0);\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n state: stateFilter.state,\n templateId: null,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [instancePage, instancePageSize, searchText, stateFilter, view]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.instanceFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取簽核案件失敗。';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"approval-instance-list-page-BnI4t5mD.js","names":["_Fragment","styles","useRouterAdapter","useBPMRoutes","formatDateTime","Fragment$1","ContentHeader","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","STATE_FILTER_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","useState","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","refreshRequestIdRef","useRef","refreshInstances","useCallback","requestId","result","listApprovalInstancesPage","readApprovalInstanceRow","requestError","readErrorMessage","view","useEffect","initiatorMemberIds","row","cancelled","profiles","resolveMembers","profile","columns","useMemo","Typography","readInstanceStateColor","record","readInitiatorLabel","tableActions","PageHeader","SectionGroup","Section","FilterArea","FilterLine","Filter","FormField","FormFieldLayout","Input","event","searchPlaceholder","Select","readSelectedStateFilterOption","option","readStateFilterLabel","value","emptyMessage","Table","page","pageSize","from","to","total","instance","readApprovalInstanceCaseTitle","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":[".instanceFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const refreshRequestIdRef = useRef(0);\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n state: stateFilter.state,\n templateId: null,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [instancePage, instancePageSize, searchText, stateFilter, view]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.instanceFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取簽核案件失敗。';\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";require('../approval-instance-list-page.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./format-date-time-D-cx5M8z.cjs"),r=require("./routes-config-C1j_vFKo.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("@rytass/bpm-core-client"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);var d={instanceFilterArea:`bpm_instanceFilterArea_qpvJq`},f=[10,20,50],p=[{id:`ALL`,name:`全部狀態`,state:null},{id:`RUNNING`,name:`進行中`,state:`RUNNING`},{id:`APPROVED`,name:`已通過`,state:`APPROVED`},{id:`REJECTED`,name:`已拒絕`,state:`REJECTED`},{id:`RETURNED`,name:`已退回`,state:`RETURNED`},{id:`CANCELLED`,name:`已取消`,state:`CANCELLED`},{id:`EXPIRED`,name:`已逾期`,state:`EXPIRED`},{id:`DRAFT`,name:`草稿`,state:`DRAFT`}];function m({defaultState:e,description:m,emptyMessage:y,searchPlaceholder:b,title:w,view:T}){let E=t.r(),D=r.r(),[O,k]=(0,i.useState)(null),[A,j]=(0,i.useState)(new Map),[M,N]=(0,i.useState)(1),[P,F]=(0,i.useState)(10),[I,L]=(0,i.useState)(0),[R,z]=(0,i.useState)(!0),[B,V]=(0,i.useState)([]),[H,U]=(0,i.useState)(``),[W,G]=(0,i.useState)(_(e)),K=(0,i.useRef)(0),q=(0,i.useCallback)(async()=>{let e=K.current+1;K.current=e,z(!0),k(null);try{let t=await(0,c.listApprovalInstancesPage)({page:M,pageSize:P,searchText:H,state:W.state,templateId:null,view:T});if(e!==K.current)return;V(t.instances.map(h)),L(t.totalCount)}catch(t){e===K.current&&k(C(t))}finally{e===K.current&&z(!1)}},[M,P,H,W,T]);(0,i.useEffect)(()=>{q()},[q]),(0,i.useEffect)(()=>{let e=Array.from(new Set(B.map(e=>e.initiatorMemberId).filter(Boolean)));if(e.length===0){j(new Map);return}let t=!1;return(async()=>{try{let n=await(0,o.resolveMembers)(e);if(t)return;j(new Map(n.map(e=>[e.memberId,e])))}catch{if(t)return;j(new Map)}})(),()=>{t=!0}},[B]);let J=(0,i.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:300},{key:`state`,render:e=>(0,s.jsx)(a.Typography,{color:x(e.state),component:`span`,variant:`body`,children:e.stateLabel}),title:`狀態`,width:120},{key:`initiatorMemberId`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:S(e.initiatorMemberId,A)}),title:`發起人`,width:180},{key:`startedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:n.t(e.startedAt)}),title:`發起時間`,width:220},{key:`completedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:n.t(e.completedAt)}),title:`完成時間`,width:220}],[A]),Y=(0,i.useMemo)(()=>({render:e=>[{name:`查看`,onClick:()=>E.push(D.caseDetail(e.id))}],variant:`base-secondary`,width:88}),[E]);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.PageHeader,{children:(0,s.jsx)(u.default,{description:m,title:w})}),(0,s.jsx)(a.SectionGroup,{children:(0,s.jsxs)(a.Section,{filterArea:(0,s.jsx)(a.FilterArea,{className:d.instanceFilterArea,size:`sub`,children:(0,s.jsxs)(a.FilterLine,{children:[(0,s.jsx)(a.Filter,{span:3,children:(0,s.jsx)(a.FormField,{fullWidth:!0,layout:l.FormFieldLayout.VERTICAL,name:`instanceSearchText`,children:(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{U(e.target.value),N(1)},placeholder:b,size:`sub`,value:H,variant:`base`})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,layout:l.FormFieldLayout.VERTICAL,name:`instanceState`,children:(0,s.jsx)(a.Select,{clearable:!1,fullWidth:!0,onChange:e=>{G(g(e)),N(1)},options:[...p],placeholder:`狀態`,renderValue:e=>`狀態:${v(e)}`,size:`sub`,value:W})})})]})}),children:[O?(0,s.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:O}):null,!O&&!R&&B.length===0?(0,s.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:y}):null,(0,s.jsx)(a.Table,{actions:Y,columns:J,dataSource:[...B],fullWidth:!0,loading:R,pagination:{current:M,onChange:e=>{N(e)},onChangePageSize:e=>{N(1),F(e)},pageSize:P,pageSizeLabel:`每頁筆數`,pageSizeOptions:f,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:I}})]})})]})}function h(e){return{...e,caseTitle:(0,c.readApprovalInstanceCaseTitle)(e),key:e.id,stateLabel:b(e.state)}}function g(e){return y(e)?_(e.state):p[0]}function _(e){return p.find(t=>t.state===e)??p[0]}function v(e){return y(e)?e.name:p[0].name}function y(e){return typeof e==`object`&&!!e&&`id`in e&&`name`in e&&`state`in e}function b(e){return e===`RUNNING`?`進行中`:e===`APPROVED`?`已通過`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`CANCELLED`?`已取消`:e===`EXPIRED`?`已逾期`:`草稿`}function x(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`CANCELLED`||e===`EXPIRED`?`text-error`:`text-neutral`}function S(e,t){let n=(e??``).trim();return n?t.get(n)?.name??n:`未知發起人`}function C(e){return e instanceof Error?e.message:`讀取簽核案件失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return m}});
2
- //# sourceMappingURL=approval-instance-list-page-ax0pm8bt.cjs.map
1
+ "use client";require('../approval-instance-list-page.css');const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./router-adapter--gYs13E8.cjs"),n=require("./routes-config-C1j_vFKo.cjs"),r=require("./format-date-time-D-cx5M8z.cjs");let i=require("react"),a=require("@mezzanine-ui/react"),o=require("@rytass/bpm-core-client"),s=require("react/jsx-runtime"),c=require("@rytass/bpm-core-client/workflow"),l=require("@mezzanine-ui/core/form"),u=require("@mezzanine-ui/react/ContentHeader");u=e.t(u,1);var d={instanceFilterArea:`bpm_instanceFilterArea_qpvJq`},f=[10,20,50],p=[{id:`ALL`,name:`全部狀態`,state:null},{id:`RUNNING`,name:`進行中`,state:`RUNNING`},{id:`APPROVED`,name:`已通過`,state:`APPROVED`},{id:`REJECTED`,name:`已拒絕`,state:`REJECTED`},{id:`RETURNED`,name:`已退回`,state:`RETURNED`},{id:`CANCELLED`,name:`已取消`,state:`CANCELLED`},{id:`EXPIRED`,name:`已逾期`,state:`EXPIRED`},{id:`DRAFT`,name:`草稿`,state:`DRAFT`}];function m({defaultState:e,description:m,emptyMessage:y,searchPlaceholder:b,title:w,view:T}){let E=t.r(),D=n.r(),[O,k]=(0,i.useState)(null),[A,j]=(0,i.useState)(new Map),[M,N]=(0,i.useState)(1),[P,F]=(0,i.useState)(10),[I,L]=(0,i.useState)(0),[R,z]=(0,i.useState)(!0),[B,V]=(0,i.useState)([]),[H,U]=(0,i.useState)(``),[W,G]=(0,i.useState)(_(e)),K=(0,i.useRef)(0),q=(0,i.useCallback)(async()=>{let e=K.current+1;K.current=e,z(!0),k(null);try{let t=await(0,c.listApprovalInstancesPage)({page:M,pageSize:P,searchText:H,state:W.state,templateId:null,view:T});if(e!==K.current)return;V(t.instances.map(h)),L(t.totalCount)}catch(t){e===K.current&&k(C(t))}finally{e===K.current&&z(!1)}},[M,P,H,W,T]);(0,i.useEffect)(()=>{q()},[q]),(0,i.useEffect)(()=>{let e=Array.from(new Set(B.map(e=>e.initiatorMemberId).filter(Boolean)));if(e.length===0){j(new Map);return}let t=!1;return(async()=>{try{let n=await(0,o.resolveMembers)(e);if(t)return;j(new Map(n.map(e=>[e.memberId,e])))}catch{if(t)return;j(new Map)}})(),()=>{t=!0}},[B]);let J=(0,i.useMemo)(()=>[{dataIndex:`caseTitle`,key:`caseTitle`,title:`案件`,width:300},{key:`state`,render:e=>(0,s.jsx)(a.Typography,{color:x(e.state),component:`span`,variant:`body`,children:e.stateLabel}),title:`狀態`,width:120},{key:`initiatorMemberId`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:S(e.initiatorMemberId,A)}),title:`發起人`,width:180},{key:`startedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:r.t(e.startedAt)}),title:`發起時間`,width:220},{key:`completedAt`,render:e=>(0,s.jsx)(a.Typography,{component:`span`,variant:`body`,children:r.t(e.completedAt)}),title:`完成時間`,width:220}],[A]),Y=(0,i.useMemo)(()=>({render:e=>[{name:`查看`,onClick:()=>E.push(D.caseDetail(e.id))}],variant:`base-secondary`,width:88}),[E]);return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.PageHeader,{children:(0,s.jsx)(u.default,{description:m,title:w})}),(0,s.jsx)(a.SectionGroup,{children:(0,s.jsxs)(a.Section,{filterArea:(0,s.jsx)(a.FilterArea,{className:d.instanceFilterArea,size:`sub`,children:(0,s.jsxs)(a.FilterLine,{children:[(0,s.jsx)(a.Filter,{span:3,children:(0,s.jsx)(a.FormField,{fullWidth:!0,layout:l.FormFieldLayout.VERTICAL,name:`instanceSearchText`,children:(0,s.jsx)(a.Input,{fullWidth:!0,onChange:e=>{U(e.target.value),N(1)},placeholder:b,size:`sub`,value:H,variant:`base`})})}),(0,s.jsx)(a.Filter,{span:2,children:(0,s.jsx)(a.FormField,{fullWidth:!0,layout:l.FormFieldLayout.VERTICAL,name:`instanceState`,children:(0,s.jsx)(a.Select,{clearable:!1,fullWidth:!0,onChange:e=>{G(g(e)),N(1)},options:[...p],placeholder:`狀態`,renderValue:e=>`狀態:${v(e)}`,size:`sub`,value:W})})})]})}),children:[O?(0,s.jsx)(a.Typography,{color:`text-error`,variant:`body`,children:O}):null,!O&&!R&&B.length===0?(0,s.jsx)(a.Typography,{color:`text-neutral`,variant:`body`,children:y}):null,(0,s.jsx)(a.Table,{actions:Y,columns:J,dataSource:[...B],fullWidth:!0,loading:R,pagination:{current:M,onChange:e=>{N(e)},onChangePageSize:e=>{N(1),F(e)},pageSize:P,pageSizeLabel:`每頁筆數`,pageSizeOptions:f,renderResultSummary:(e,t,n)=>`顯示 ${e}-${t} 筆,共 ${n} 筆`,showPageSizeOptions:!0,total:I}})]})})]})}function h(e){return{...e,caseTitle:(0,c.readApprovalInstanceCaseTitle)(e),key:e.id,stateLabel:b(e.state)}}function g(e){return y(e)?_(e.state):p[0]}function _(e){return p.find(t=>t.state===e)??p[0]}function v(e){return y(e)?e.name:p[0].name}function y(e){return typeof e==`object`&&!!e&&`id`in e&&`name`in e&&`state`in e}function b(e){return e===`RUNNING`?`進行中`:e===`APPROVED`?`已通過`:e===`REJECTED`?`已拒絕`:e===`RETURNED`?`已退回`:e===`CANCELLED`?`已取消`:e===`EXPIRED`?`已逾期`:`草稿`}function x(e){return e===`APPROVED`?`text-success`:e===`REJECTED`||e===`CANCELLED`||e===`EXPIRED`?`text-error`:`text-neutral`}function S(e,t){let n=(e??``).trim();return n?t.get(n)?.name??n:`未知發起人`}function C(e){return e instanceof Error?e.message:`讀取簽核案件失敗。`}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return m}});
2
+ //# sourceMappingURL=approval-instance-list-page-fqvmkBlg.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"approval-instance-list-page-ax0pm8bt.cjs","names":["useRouterAdapter","useBPMRoutes","useState","useRef","useCallback","listApprovalInstancesPage","resolveMembers","useMemo","Typography","formatDateTime","_Fragment","PageHeader","ContentHeader","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Select","Table","readApprovalInstanceCaseTitle","require_rolldown_runtime","require_router_adapter","require_format_date_time","require_routes_config","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","STATE_FILTER_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","refreshRequestIdRef","refreshInstances","requestId","result","readApprovalInstanceRow","requestError","readErrorMessage","view","initiatorMemberIds","row","cancelled","profiles","profile","columns","readInstanceStateColor","record","readInitiatorLabel","tableActions","event","searchPlaceholder","readSelectedStateFilterOption","option","readStateFilterLabel","value","emptyMessage","page","pageSize","from","to","total","instance","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":[".instanceFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const refreshRequestIdRef = useRef(0);\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n state: stateFilter.state,\n templateId: null,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [instancePage, instancePageSize, searchText, stateFilter, view]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.instanceFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取簽核案件失敗。';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"approval-instance-list-page-fqvmkBlg.cjs","names":["useRouterAdapter","useBPMRoutes","useState","useRef","useCallback","listApprovalInstancesPage","resolveMembers","useMemo","Typography","formatDateTime","_Fragment","PageHeader","ContentHeader","SectionGroup","Section","FilterArea","styles","FilterLine","Filter","FormField","FormFieldLayout","Input","Select","Table","readApprovalInstanceCaseTitle","require_rolldown_runtime","require_router_adapter","require_routes_config","require_format_date_time","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","_rytass_bpm_core_client_workflow","_mezzanine_ui_core_form","_mezzanine_ui_react_ContentHeader","approval_instance_list_page_module_default","INSTANCE_PAGE_SIZE_OPTIONS","STATE_FILTER_OPTIONS","ApprovalInstanceListPage","router","routes","error","setError","initiatorProfilesById","setInitiatorProfilesById","instancePage","setInstancePage","instancePageSize","setInstancePageSize","instanceTotalCount","setInstanceTotalCount","loading","setLoading","rows","setRows","searchText","setSearchText","stateFilter","setStateFilter","readStateFilterOption","defaultState","refreshRequestIdRef","refreshInstances","requestId","result","readApprovalInstanceRow","requestError","readErrorMessage","view","initiatorMemberIds","row","cancelled","profiles","profile","columns","readInstanceStateColor","record","readInitiatorLabel","tableActions","event","searchPlaceholder","readSelectedStateFilterOption","option","readStateFilterLabel","value","emptyMessage","page","pageSize","from","to","total","instance","readInstanceStateLabel","isStateFilterOption","state","trimmedMemberId","initiatorMemberId"],"sources":["../../src/components/approval-instance-list-page.module.scss","../../src/components/approval-instance-list-page.tsx"],"sourcesContent":[".instanceFilterArea {\n :global(.mzn-filter-area__actions) {\n display: none;\n }\n\n :global(.mzn-form-field__label-area) {\n display: none;\n }\n\n :global(.mzn-form-field__control-field-slot--main) {\n width: 100%;\n min-width: 0;\n }\n}\n","'use client';\n\nimport type { ChangeEvent, ReactElement } from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Filter,\n FilterArea,\n FilterLine,\n FormField,\n Input,\n PageHeader,\n Section,\n SectionGroup,\n Select,\n Table,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport { FormFieldLayout } from '@mezzanine-ui/core/form';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n resolveMembers,\n type MemberProfileRecord,\n} from '@rytass/bpm-core-client';\nimport {\n listApprovalInstancesPage,\n readApprovalInstanceCaseTitle,\n type ApprovalInstanceRecord,\n type ApprovalInstanceState,\n type ApprovalInstanceView,\n} from '@rytass/bpm-core-client/workflow';\nimport { useRouterAdapter } from '../lib/router-adapter';\nimport { useBPMRoutes } from '../lib/routes-config';\nimport { formatDateTime } from '../lib/format-date-time';\nimport styles from './approval-instance-list-page.module.scss';\n\nexport interface ApprovalInstanceListPageProps {\n readonly defaultState: ApprovalInstanceState | null;\n readonly description: string;\n readonly emptyMessage: string;\n readonly searchPlaceholder: string;\n readonly title: string;\n readonly view: ApprovalInstanceView;\n}\n\ntype StateFilterOption = Readonly<{\n id: 'ALL' | ApprovalInstanceState;\n name: string;\n state: ApprovalInstanceState | null;\n}>;\n\ntype ApprovalInstanceRow = Readonly<\n Record<string, unknown> &\n ApprovalInstanceRecord & {\n caseTitle: string;\n key: string;\n stateLabel: string;\n }\n>;\n\nconst INSTANCE_PAGE_SIZE_OPTIONS = [10, 20, 50];\nconst STATE_FILTER_OPTIONS: readonly StateFilterOption[] = [\n { id: 'ALL', name: '全部狀態', state: null },\n { id: 'RUNNING', name: '進行中', state: 'RUNNING' },\n { id: 'APPROVED', name: '已通過', state: 'APPROVED' },\n { id: 'REJECTED', name: '已拒絕', state: 'REJECTED' },\n { id: 'RETURNED', name: '已退回', state: 'RETURNED' },\n { id: 'CANCELLED', name: '已取消', state: 'CANCELLED' },\n { id: 'EXPIRED', name: '已逾期', state: 'EXPIRED' },\n { id: 'DRAFT', name: '草稿', state: 'DRAFT' },\n];\n\n/**\n * Shared list page for any approval-instance \"view\" (inbox / sent / cc /\n * delegated). Caller picks the view + default state filter; the page renders\n * the standard BPM filter bar + paginated table and navigates to\n * `/instances/:id` on row action.\n */\nexport function ApprovalInstanceListPage({\n defaultState,\n description,\n emptyMessage,\n searchPlaceholder,\n title,\n view,\n}: ApprovalInstanceListPageProps): ReactElement {\n const router = useRouterAdapter();\n const routes = useBPMRoutes();\n const [error, setError] = useState<string | null>(null);\n const [initiatorProfilesById, setInitiatorProfilesById] = useState<\n ReadonlyMap<string, MemberProfileRecord>\n >(new Map());\n const [instancePage, setInstancePage] = useState(1);\n const [instancePageSize, setInstancePageSize] = useState(10);\n const [instanceTotalCount, setInstanceTotalCount] = useState(0);\n const [loading, setLoading] = useState(true);\n const [rows, setRows] = useState<readonly ApprovalInstanceRow[]>([]);\n const [searchText, setSearchText] = useState('');\n const [stateFilter, setStateFilter] = useState<StateFilterOption>(\n readStateFilterOption(defaultState),\n );\n const refreshRequestIdRef = useRef(0);\n\n const refreshInstances = useCallback(async (): Promise<void> => {\n const requestId = refreshRequestIdRef.current + 1;\n refreshRequestIdRef.current = requestId;\n setLoading(true);\n setError(null);\n\n try {\n const result = await listApprovalInstancesPage({\n page: instancePage,\n pageSize: instancePageSize,\n searchText,\n state: stateFilter.state,\n templateId: null,\n view,\n });\n\n if (requestId !== refreshRequestIdRef.current) {\n return;\n }\n\n setRows(result.instances.map(readApprovalInstanceRow));\n setInstanceTotalCount(result.totalCount);\n } catch (requestError: unknown) {\n if (requestId === refreshRequestIdRef.current) {\n setError(readErrorMessage(requestError));\n }\n } finally {\n if (requestId === refreshRequestIdRef.current) {\n setLoading(false);\n }\n }\n }, [instancePage, instancePageSize, searchText, stateFilter, view]);\n\n useEffect((): void => {\n void refreshInstances();\n }, [refreshInstances]);\n\n useEffect((): (() => void) | void => {\n const initiatorMemberIds = Array.from(\n new Set(rows.map((row) => row.initiatorMemberId).filter(Boolean)),\n );\n\n if (initiatorMemberIds.length === 0) {\n setInitiatorProfilesById(new Map());\n\n return;\n }\n\n let cancelled = false;\n\n void (async (): Promise<void> => {\n try {\n const profiles = await resolveMembers(initiatorMemberIds);\n\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(\n new Map(profiles.map((profile) => [profile.memberId, profile])),\n );\n } catch {\n if (cancelled) {\n return;\n }\n\n setInitiatorProfilesById(new Map());\n }\n })();\n\n return (): void => {\n cancelled = true;\n };\n }, [rows]);\n\n const columns = useMemo(\n (): TableColumn<ApprovalInstanceRow>[] => [\n { dataIndex: 'caseTitle', key: 'caseTitle', title: '案件', width: 300 },\n {\n key: 'state',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography\n color={readInstanceStateColor(record.state)}\n component=\"span\"\n variant=\"body\"\n >\n {record.stateLabel}\n </Typography>\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'initiatorMemberId',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readInitiatorLabel(\n record.initiatorMemberId,\n initiatorProfilesById,\n )}\n </Typography>\n ),\n title: '發起人',\n width: 180,\n },\n {\n key: 'startedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.startedAt)}\n </Typography>\n ),\n title: '發起時間',\n width: 220,\n },\n {\n key: 'completedAt',\n render: (record: ApprovalInstanceRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.completedAt)}\n </Typography>\n ),\n title: '完成時間',\n width: 220,\n },\n ],\n [initiatorProfilesById],\n );\n const tableActions = useMemo(\n (): TableActions<ApprovalInstanceRow> => ({\n render: (\n record,\n ): ReturnType<TableActions<ApprovalInstanceRow>['render']> => [\n {\n name: '查看',\n onClick: (): void => router.push(routes.caseDetail(record.id)),\n },\n ],\n variant: 'base-secondary',\n width: 88,\n }),\n [router],\n );\n\n return (\n <>\n <PageHeader>\n <ContentHeader description={description} title={title} />\n </PageHeader>\n\n <SectionGroup>\n <Section\n filterArea={\n <FilterArea className={styles.instanceFilterArea} size=\"sub\">\n <FilterLine>\n <Filter span={3}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceSearchText\"\n >\n <Input\n fullWidth\n onChange={(\n event: ChangeEvent<HTMLInputElement>,\n ): void => {\n setSearchText(event.target.value);\n setInstancePage(1);\n }}\n placeholder={searchPlaceholder}\n size=\"sub\"\n value={searchText}\n variant=\"base\"\n />\n </FormField>\n </Filter>\n <Filter span={2}>\n <FormField\n fullWidth\n layout={FormFieldLayout.VERTICAL}\n name=\"instanceState\"\n >\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void => {\n setStateFilter(readSelectedStateFilterOption(option));\n setInstancePage(1);\n }}\n options={[...STATE_FILTER_OPTIONS]}\n placeholder=\"狀態\"\n renderValue={(value): string =>\n `狀態:${readStateFilterLabel(value)}`\n }\n size=\"sub\"\n value={stateFilter}\n />\n </FormField>\n </Filter>\n </FilterLine>\n </FilterArea>\n }\n >\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {!error && !loading && rows.length === 0 ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n {emptyMessage}\n </Typography>\n ) : null}\n <Table\n actions={tableActions}\n columns={columns}\n dataSource={[...rows]}\n fullWidth\n loading={loading}\n pagination={{\n current: instancePage,\n onChange: (page): void => {\n setInstancePage(page);\n },\n onChangePageSize: (pageSize): void => {\n setInstancePage(1);\n setInstancePageSize(pageSize);\n },\n pageSize: instancePageSize,\n pageSizeLabel: '每頁筆數',\n pageSizeOptions: INSTANCE_PAGE_SIZE_OPTIONS,\n renderResultSummary: (from, to, total): string =>\n `顯示 ${from}-${to} 筆,共 ${total} 筆`,\n showPageSizeOptions: true,\n total: instanceTotalCount,\n }}\n />\n </Section>\n </SectionGroup>\n </>\n );\n}\n\nfunction readApprovalInstanceRow(\n instance: ApprovalInstanceRecord,\n): ApprovalInstanceRow {\n return {\n ...instance,\n caseTitle: readApprovalInstanceCaseTitle(instance),\n key: instance.id,\n stateLabel: readInstanceStateLabel(instance.state),\n };\n}\n\nfunction readSelectedStateFilterOption(option: unknown): StateFilterOption {\n if (!isStateFilterOption(option)) {\n return STATE_FILTER_OPTIONS[0];\n }\n return readStateFilterOption(option.state);\n}\n\nfunction readStateFilterOption(\n state: ApprovalInstanceState | null,\n): StateFilterOption {\n return (\n STATE_FILTER_OPTIONS.find((option) => option.state === state) ??\n STATE_FILTER_OPTIONS[0]\n );\n}\n\nfunction readStateFilterLabel(value: unknown): string {\n return isStateFilterOption(value) ? value.name : STATE_FILTER_OPTIONS[0].name;\n}\n\nfunction isStateFilterOption(value: unknown): value is StateFilterOption {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'id' in value &&\n 'name' in value &&\n 'state' in value\n );\n}\n\nfunction readInstanceStateLabel(state: ApprovalInstanceState): string {\n if (state === 'RUNNING') return '進行中';\n if (state === 'APPROVED') return '已通過';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'EXPIRED') return '已逾期';\n return '草稿';\n}\n\nfunction readInstanceStateColor(\n state: ApprovalInstanceState,\n): 'text-error' | 'text-neutral' | 'text-success' {\n if (state === 'APPROVED') return 'text-success';\n if (state === 'REJECTED' || state === 'CANCELLED' || state === 'EXPIRED') {\n return 'text-error';\n }\n return 'text-neutral';\n}\n\nfunction readInitiatorLabel(\n initiatorMemberId: string | null | undefined,\n initiatorProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n const trimmedMemberId = (initiatorMemberId ?? '').trim();\n if (!trimmedMemberId) return '未知發起人';\n return initiatorProfilesById.get(trimmedMemberId)?.name ?? trimmedMemberId;\n}\n\nfunction readErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : '讀取簽核案件失敗。';\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth-provider-4BeCw7cI.cjs","names":["createContext","useRouterAdapter","useState","useCallback","readApiCurrentMember","loginApi","logoutApi","useMemo","useContext","styles","Typography","require_router_adapter","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","auth_provider_module_default","AuthContext","AuthProvider","router","loading","setLoading","member","setMember","refresh","current","login","next","input","logout","loginPath","active","isPublicPath","publicPaths","readCurrentPath","value","AuthLoadingState","useAuth","ctx","label","p","pathname"],"sources":["../../src/lib/auth-provider.module.scss","../../src/lib/auth-provider.tsx"],"sourcesContent":[".authLoading {\n align-items: center;\n background: var(--mzn-color-bg-body);\n display: flex;\n min-height: 100vh;\n justify-content: center;\n padding: 32px;\n}\n","'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport {\n loginApi,\n logoutApi,\n readApiCurrentMember,\n type ApiMember,\n} from '@rytass/bpm-core-client';\nimport { useRouterAdapter } from './router-adapter';\nimport styles from './auth-provider.module.scss';\n\ninterface AuthContextValue {\n readonly loading: boolean;\n readonly member: ApiMember | null;\n readonly login: (input: {\n readonly identifier: string;\n readonly password: string;\n }) => Promise<ApiMember>;\n readonly logout: () => Promise<void>;\n readonly refresh: () => Promise<ApiMember | null>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport interface AuthProviderProps {\n readonly children: ReactNode;\n /**\n * Paths that should not redirect to `/login` when there is no session.\n * Defaults to `['/login']`. Override when your host runs the login UI\n * under a different path.\n */\n readonly publicPaths?: readonly string[];\n /**\n * Where to send unauthenticated users. Defaults to `'/login'`.\n */\n readonly loginPath?: string;\n}\n\n/**\n * BPM auth context provider. Reads / writes the host BPM API session via\n * `@rytass/bpm-core-client` (`loginApi` / `logoutApi` / `readApiCurrentMember`)\n * and uses the host-supplied {@link useRouterAdapter} to redirect\n * unauthenticated users.\n */\nexport function AuthProvider({\n children,\n publicPaths = ['/login'],\n loginPath = '/login',\n}: AuthProviderProps): ReactElement {\n const router = useRouterAdapter();\n const [loading, setLoading] = useState(true);\n const [member, setMember] = useState<ApiMember | null>(null);\n\n const refresh = useCallback(async (): Promise<ApiMember | null> => {\n const current = await readApiCurrentMember();\n setMember(current);\n return current;\n }, []);\n\n const login = useCallback(\n async (input: {\n readonly identifier: string;\n readonly password: string;\n }): Promise<ApiMember> => {\n const next = await loginApi(input);\n setMember(next);\n return next;\n },\n [],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n await logoutApi();\n setMember(null);\n router.replace(loginPath);\n }, [loginPath, router]);\n\n useEffect((): (() => void) => {\n let active = true;\n setLoading(true);\n void (async () => {\n try {\n const current = await readApiCurrentMember();\n if (active) setMember(current);\n } catch {\n if (active) setMember(null);\n } finally {\n if (active) setLoading(false);\n }\n })();\n return (): void => {\n active = false;\n };\n }, []);\n\n useEffect((): void => {\n if (loading || isPublicPath(router.pathname, publicPaths) || member) return;\n router.replace(\n `${loginPath}?next=${encodeURIComponent(readCurrentPath(router.pathname))}`,\n );\n }, [loading, loginPath, member, publicPaths, router]);\n\n const value = useMemo<AuthContextValue>(\n () => ({ loading, login, logout, member, refresh }),\n [loading, login, logout, member, refresh],\n );\n\n if (loading && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"確認登入狀態\" />;\n }\n if (!loading && !member && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"前往登入頁\" />;\n }\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n/**\n * Access the BPM auth context. Throws when used outside `<AuthProvider>`.\n */\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) throw new Error('useAuth must be used inside <AuthProvider>');\n return ctx;\n}\n\nfunction AuthLoadingState({\n label,\n}: {\n readonly label: string;\n}): ReactElement {\n return (\n <main className={styles.authLoading}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {label}\n </Typography>\n </main>\n );\n}\n\nfunction isPublicPath(\n pathname: string | null,\n publicPaths: readonly string[],\n): boolean {\n return publicPaths.some((p) => p === pathname);\n}\n\nfunction readCurrentPath(pathname: string | null): string {\n if (typeof window === 'undefined') return pathname ?? '/';\n return `${window.location.pathname}${window.location.search}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth-provider-4BeCw7cI.cjs","names":["createContext","useRouterAdapter","useState","useCallback","readApiCurrentMember","loginApi","logoutApi","useMemo","useContext","styles","Typography","require_router_adapter","react","_mezzanine_ui_react","_rytass_bpm_core_client","react_jsx_runtime","auth_provider_module_default","AuthContext","AuthProvider","router","loading","setLoading","member","setMember","refresh","current","login","next","input","logout","loginPath","active","isPublicPath","publicPaths","readCurrentPath","value","AuthLoadingState","useAuth","ctx","label","p","pathname"],"sources":["../../src/lib/auth-provider.module.scss","../../src/lib/auth-provider.tsx"],"sourcesContent":[".authLoading {\n align-items: center;\n background: var(--mzn-color-bg-body);\n display: flex;\n min-height: 100vh;\n justify-content: center;\n padding: 32px;\n}\n","'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport {\n loginApi,\n logoutApi,\n readApiCurrentMember,\n type ApiMember,\n} from '@rytass/bpm-core-client';\nimport { useRouterAdapter } from './router-adapter';\nimport styles from './auth-provider.module.scss';\n\ninterface AuthContextValue {\n readonly loading: boolean;\n readonly member: ApiMember | null;\n readonly login: (input: {\n readonly identifier: string;\n readonly password: string;\n }) => Promise<ApiMember>;\n readonly logout: () => Promise<void>;\n readonly refresh: () => Promise<ApiMember | null>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport interface AuthProviderProps {\n readonly children: ReactNode;\n /**\n * Paths that should not redirect to `/login` when there is no session.\n * Defaults to `['/login']`. Override when your host runs the login UI\n * under a different path.\n */\n readonly publicPaths?: readonly string[];\n /**\n * Where to send unauthenticated users. Defaults to `'/login'`.\n */\n readonly loginPath?: string;\n}\n\n/**\n * BPM auth context provider. Reads / writes the host BPM API session via\n * `@rytass/bpm-core-client` (`loginApi` / `logoutApi` / `readApiCurrentMember`)\n * and uses the host-supplied {@link useRouterAdapter} to redirect\n * unauthenticated users.\n */\nexport function AuthProvider({\n children,\n publicPaths = ['/login'],\n loginPath = '/login',\n}: AuthProviderProps): ReactElement {\n const router = useRouterAdapter();\n const [loading, setLoading] = useState(true);\n const [member, setMember] = useState<ApiMember | null>(null);\n\n const refresh = useCallback(async (): Promise<ApiMember | null> => {\n const current = await readApiCurrentMember();\n setMember(current);\n return current;\n }, []);\n\n const login = useCallback(\n async (input: {\n readonly identifier: string;\n readonly password: string;\n }): Promise<ApiMember> => {\n const next = await loginApi(input);\n setMember(next);\n return next;\n },\n [],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n await logoutApi();\n setMember(null);\n router.replace(loginPath);\n }, [loginPath, router]);\n\n useEffect((): (() => void) => {\n let active = true;\n setLoading(true);\n void (async () => {\n try {\n const current = await readApiCurrentMember();\n if (active) setMember(current);\n } catch {\n if (active) setMember(null);\n } finally {\n if (active) setLoading(false);\n }\n })();\n return (): void => {\n active = false;\n };\n }, []);\n\n useEffect((): void => {\n if (loading || isPublicPath(router.pathname, publicPaths) || member) return;\n router.replace(\n `${loginPath}?next=${encodeURIComponent(readCurrentPath(router.pathname))}`,\n );\n }, [loading, loginPath, member, publicPaths, router]);\n\n const value = useMemo<AuthContextValue>(\n () => ({ loading, login, logout, member, refresh }),\n [loading, login, logout, member, refresh],\n );\n\n if (loading && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"確認登入狀態\" />;\n }\n if (!loading && !member && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"前往登入頁\" />;\n }\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n/**\n * Access the BPM auth context. Throws when used outside `<AuthProvider>`.\n */\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) throw new Error('useAuth must be used inside <AuthProvider>');\n return ctx;\n}\n\nfunction AuthLoadingState({\n label,\n}: {\n readonly label: string;\n}): ReactElement {\n return (\n <main className={styles.authLoading}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {label}\n </Typography>\n </main>\n );\n}\n\nfunction isPublicPath(\n pathname: string | null,\n publicPaths: readonly string[],\n): boolean {\n return publicPaths.some((p) => p === pathname);\n}\n\nfunction readCurrentPath(pathname: string | null): string {\n if (typeof window === 'undefined') return pathname ?? '/';\n return `${window.location.pathname}${window.location.search}`;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { r as e } from "./router-adapter-DftlFTOd.js";
2
+ import { r as e } from "./router-adapter-CkxCyzf5.js";
3
3
  import { createContext as t, useCallback as n, useContext as r, useEffect as i, useMemo as a, useState as o } from "react";
4
4
  import { Typography as s } from "@mezzanine-ui/react";
5
5
  import { loginApi as c, logoutApi as l, readApiCurrentMember as u } from "@rytass/bpm-core-client";
@@ -77,7 +77,6 @@ function _(e, t) {
77
77
  function v(e) {
78
78
  return typeof window > "u" ? e ?? "/" : `${window.location.pathname}${window.location.search}`;
79
79
  }
80
- //#endregion
81
80
  export { h as n, m as t };
82
81
 
83
- //# sourceMappingURL=auth-provider-B5oPmvk2.js.map
82
+ //# sourceMappingURL=auth-provider-C2b-5mGt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth-provider-B5oPmvk2.js","names":["styles","useRouterAdapter","auth_provider_module_default","AuthContext","createContext","AuthProvider","router","loading","setLoading","useState","member","setMember","refresh","useCallback","current","readApiCurrentMember","login","next","loginApi","input","logout","logoutApi","loginPath","useEffect","active","isPublicPath","publicPaths","readCurrentPath","value","useMemo","AuthLoadingState","useAuth","ctx","useContext","Typography","label","p","pathname"],"sources":["../../src/lib/auth-provider.module.scss","../../src/lib/auth-provider.tsx"],"sourcesContent":[".authLoading {\n align-items: center;\n background: var(--mzn-color-bg-body);\n display: flex;\n min-height: 100vh;\n justify-content: center;\n padding: 32px;\n}\n","'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport {\n loginApi,\n logoutApi,\n readApiCurrentMember,\n type ApiMember,\n} from '@rytass/bpm-core-client';\nimport { useRouterAdapter } from './router-adapter';\nimport styles from './auth-provider.module.scss';\n\ninterface AuthContextValue {\n readonly loading: boolean;\n readonly member: ApiMember | null;\n readonly login: (input: {\n readonly identifier: string;\n readonly password: string;\n }) => Promise<ApiMember>;\n readonly logout: () => Promise<void>;\n readonly refresh: () => Promise<ApiMember | null>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport interface AuthProviderProps {\n readonly children: ReactNode;\n /**\n * Paths that should not redirect to `/login` when there is no session.\n * Defaults to `['/login']`. Override when your host runs the login UI\n * under a different path.\n */\n readonly publicPaths?: readonly string[];\n /**\n * Where to send unauthenticated users. Defaults to `'/login'`.\n */\n readonly loginPath?: string;\n}\n\n/**\n * BPM auth context provider. Reads / writes the host BPM API session via\n * `@rytass/bpm-core-client` (`loginApi` / `logoutApi` / `readApiCurrentMember`)\n * and uses the host-supplied {@link useRouterAdapter} to redirect\n * unauthenticated users.\n */\nexport function AuthProvider({\n children,\n publicPaths = ['/login'],\n loginPath = '/login',\n}: AuthProviderProps): ReactElement {\n const router = useRouterAdapter();\n const [loading, setLoading] = useState(true);\n const [member, setMember] = useState<ApiMember | null>(null);\n\n const refresh = useCallback(async (): Promise<ApiMember | null> => {\n const current = await readApiCurrentMember();\n setMember(current);\n return current;\n }, []);\n\n const login = useCallback(\n async (input: {\n readonly identifier: string;\n readonly password: string;\n }): Promise<ApiMember> => {\n const next = await loginApi(input);\n setMember(next);\n return next;\n },\n [],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n await logoutApi();\n setMember(null);\n router.replace(loginPath);\n }, [loginPath, router]);\n\n useEffect((): (() => void) => {\n let active = true;\n setLoading(true);\n void (async () => {\n try {\n const current = await readApiCurrentMember();\n if (active) setMember(current);\n } catch {\n if (active) setMember(null);\n } finally {\n if (active) setLoading(false);\n }\n })();\n return (): void => {\n active = false;\n };\n }, []);\n\n useEffect((): void => {\n if (loading || isPublicPath(router.pathname, publicPaths) || member) return;\n router.replace(\n `${loginPath}?next=${encodeURIComponent(readCurrentPath(router.pathname))}`,\n );\n }, [loading, loginPath, member, publicPaths, router]);\n\n const value = useMemo<AuthContextValue>(\n () => ({ loading, login, logout, member, refresh }),\n [loading, login, logout, member, refresh],\n );\n\n if (loading && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"確認登入狀態\" />;\n }\n if (!loading && !member && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"前往登入頁\" />;\n }\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n/**\n * Access the BPM auth context. Throws when used outside `<AuthProvider>`.\n */\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) throw new Error('useAuth must be used inside <AuthProvider>');\n return ctx;\n}\n\nfunction AuthLoadingState({\n label,\n}: {\n readonly label: string;\n}): ReactElement {\n return (\n <main className={styles.authLoading}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {label}\n </Typography>\n </main>\n );\n}\n\nfunction isPublicPath(\n pathname: string | null,\n publicPaths: readonly string[],\n): boolean {\n return publicPaths.some((p) => p === pathname);\n}\n\nfunction readCurrentPath(pathname: string | null): string {\n if (typeof window === 'undefined') return pathname ?? '/';\n return `${window.location.pathname}${window.location.search}`;\n}\n"],"mappings":";;;;;;kDCiCMG,IAAcC,EAAuC,IAAI;AAsB/D,SAAgBC,EAAa,EAC3B,aACA,iBAAc,CAAC,QAAQ,GACvB,eAAY,YACsB;CAClC,IAAMC,IAASL,EAAiB,GAC1B,CAACM,GAASC,KAAcC,EAAS,EAAI,GACrC,CAACC,GAAQC,KAAaF,EAA2B,IAAI,GAErDG,IAAUC,EAAY,YAAuC;EACjE,IAAMC,IAAU,MAAMC,EAAqB;EAE3C,OADAJ,EAAUG,CAAO,GACVA;CACT,GAAG,CAAC,CAAC,GAECE,IAAQH,EACZ,OAAO,MAGmB;EACxB,IAAMI,IAAO,MAAMC,EAASC,CAAK;EAEjC,OADAR,EAAUM,CAAI,GACPA;CACT,GACA,CAAC,CACH,GAEMG,IAASP,EAAY,YAA2B;EAGpD,AAFA,MAAMQ,EAAU,GAChBV,EAAU,IAAI,GACdL,EAAO,QAAQgB,CAAS;CAC1B,GAAG,CAACA,GAAWhB,CAAM,CAAC;CAoBtB,AAlBAiB,QAA8B;EAC5B,IAAIC,IAAS;EAYb,OAXAhB,EAAW,EAAI,IACT,YAAY;GAChB,IAAI;IACF,IAAMM,IAAU,MAAMC,EAAqB;IAC3C,AAAIS,KAAQb,EAAUG,CAAO;GAC/B,QAAQ;IACN,AAAIU,KAAQb,EAAU,IAAI;GAC5B,UAAU;IACR,AAAIa,KAAQhB,EAAW,EAAK;GAC9B;EACF,EAAA,CAAG,SACgB;GACjB,IAAS;EACX;CACF,GAAG,CAAC,CAAC,GAELe,QAAsB;EACpB,AAAIhB,KAAWkB,EAAanB,EAAO,UAAUoB,CAAW,KAAKhB,KAC7DJ,EAAO,QACL,GAAGgB,EAAU,QAAQ,mBAAmBK,EAAgBrB,EAAO,QAAQ,CAAC,GAC1E;CACF,GAAG;EAACC;EAASe;EAAWZ;EAAQgB;EAAapB;CAAM,CAAC;CAEpD,IAAMsB,IAAQC,SACL;EAAE;EAAS;EAAO;EAAQ;EAAQ;CAAQ,IACjD;EAACtB;EAASS;EAAOI;EAAQV;EAAQE;CAAO,CAC1C;CAQA,OANIL,KAAW,CAACkB,EAAanB,EAAO,UAAUoB,CAAW,IAChD,kBAACI,GAAD,EAAkB,OAAM,SAAU,CAAA,IAEvC,CAACvB,KAAW,CAACG,KAAU,CAACe,EAAanB,EAAO,UAAUoB,CAAW,IAC5D,kBAACI,GAAD,EAAkB,OAAM,QAAS,CAAA,IAEnC,kBAAC3B,EAAY,UAAb;EAA6B;EAAQ;CAA+B,CAAA;AAC7E;AAKA,SAAgB4B,IAA4B;CAC1C,IAAMC,IAAMC,EAAW9B,CAAW;CAClC,IAAI,CAAC6B,GAAK,MAAU,MAAM,4CAA4C;CACtE,OAAOA;AACT;AAEA,SAASF,EAAiB,EACxB,YAGe;CACf,OACE,kBAAC,QAAD;EAAM,WAAW9B,EAAO;EACtB,UAAA,kBAACkC,GAAD;GAAY,OAAM;GAAe,SAAQ;GACtC,UAAAC;EACS,CAAA;CACR,CAAA;AAEV;AAEA,SAASV,EACP,GACA,GACS;CACT,OAAOC,EAAY,MAAM,MAAMU,MAAMC,CAAQ;AAC/C;AAEA,SAASV,EAAgB,GAAiC;CAExD,OADI,OAAO,SAAW,MAAoBU,KAAY,MAC/C,GAAG,OAAO,SAAS,WAAW,OAAO,SAAS;AACvD"}
1
+ {"version":3,"file":"auth-provider-C2b-5mGt.js","names":["styles","useRouterAdapter","auth_provider_module_default","AuthContext","createContext","AuthProvider","router","loading","setLoading","useState","member","setMember","refresh","useCallback","current","readApiCurrentMember","login","next","loginApi","input","logout","logoutApi","loginPath","useEffect","active","isPublicPath","publicPaths","readCurrentPath","value","useMemo","AuthLoadingState","useAuth","ctx","useContext","Typography","label","p","pathname"],"sources":["../../src/lib/auth-provider.module.scss","../../src/lib/auth-provider.tsx"],"sourcesContent":[".authLoading {\n align-items: center;\n background: var(--mzn-color-bg-body);\n display: flex;\n min-height: 100vh;\n justify-content: center;\n padding: 32px;\n}\n","'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { Typography } from '@mezzanine-ui/react';\nimport {\n loginApi,\n logoutApi,\n readApiCurrentMember,\n type ApiMember,\n} from '@rytass/bpm-core-client';\nimport { useRouterAdapter } from './router-adapter';\nimport styles from './auth-provider.module.scss';\n\ninterface AuthContextValue {\n readonly loading: boolean;\n readonly member: ApiMember | null;\n readonly login: (input: {\n readonly identifier: string;\n readonly password: string;\n }) => Promise<ApiMember>;\n readonly logout: () => Promise<void>;\n readonly refresh: () => Promise<ApiMember | null>;\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport interface AuthProviderProps {\n readonly children: ReactNode;\n /**\n * Paths that should not redirect to `/login` when there is no session.\n * Defaults to `['/login']`. Override when your host runs the login UI\n * under a different path.\n */\n readonly publicPaths?: readonly string[];\n /**\n * Where to send unauthenticated users. Defaults to `'/login'`.\n */\n readonly loginPath?: string;\n}\n\n/**\n * BPM auth context provider. Reads / writes the host BPM API session via\n * `@rytass/bpm-core-client` (`loginApi` / `logoutApi` / `readApiCurrentMember`)\n * and uses the host-supplied {@link useRouterAdapter} to redirect\n * unauthenticated users.\n */\nexport function AuthProvider({\n children,\n publicPaths = ['/login'],\n loginPath = '/login',\n}: AuthProviderProps): ReactElement {\n const router = useRouterAdapter();\n const [loading, setLoading] = useState(true);\n const [member, setMember] = useState<ApiMember | null>(null);\n\n const refresh = useCallback(async (): Promise<ApiMember | null> => {\n const current = await readApiCurrentMember();\n setMember(current);\n return current;\n }, []);\n\n const login = useCallback(\n async (input: {\n readonly identifier: string;\n readonly password: string;\n }): Promise<ApiMember> => {\n const next = await loginApi(input);\n setMember(next);\n return next;\n },\n [],\n );\n\n const logout = useCallback(async (): Promise<void> => {\n await logoutApi();\n setMember(null);\n router.replace(loginPath);\n }, [loginPath, router]);\n\n useEffect((): (() => void) => {\n let active = true;\n setLoading(true);\n void (async () => {\n try {\n const current = await readApiCurrentMember();\n if (active) setMember(current);\n } catch {\n if (active) setMember(null);\n } finally {\n if (active) setLoading(false);\n }\n })();\n return (): void => {\n active = false;\n };\n }, []);\n\n useEffect((): void => {\n if (loading || isPublicPath(router.pathname, publicPaths) || member) return;\n router.replace(\n `${loginPath}?next=${encodeURIComponent(readCurrentPath(router.pathname))}`,\n );\n }, [loading, loginPath, member, publicPaths, router]);\n\n const value = useMemo<AuthContextValue>(\n () => ({ loading, login, logout, member, refresh }),\n [loading, login, logout, member, refresh],\n );\n\n if (loading && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"確認登入狀態\" />;\n }\n if (!loading && !member && !isPublicPath(router.pathname, publicPaths)) {\n return <AuthLoadingState label=\"前往登入頁\" />;\n }\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n/**\n * Access the BPM auth context. Throws when used outside `<AuthProvider>`.\n */\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) throw new Error('useAuth must be used inside <AuthProvider>');\n return ctx;\n}\n\nfunction AuthLoadingState({\n label,\n}: {\n readonly label: string;\n}): ReactElement {\n return (\n <main className={styles.authLoading}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {label}\n </Typography>\n </main>\n );\n}\n\nfunction isPublicPath(\n pathname: string | null,\n publicPaths: readonly string[],\n): boolean {\n return publicPaths.some((p) => p === pathname);\n}\n\nfunction readCurrentPath(pathname: string | null): string {\n if (typeof window === 'undefined') return pathname ?? '/';\n return `${window.location.pathname}${window.location.search}`;\n}\n"],"mappings":";;;;;;A,kDCiCMG,IAAcC,EAAuC,IAAI;AAsB/D,SAAgBC,EAAa,EAC3B,aACA,iBAAc,CAAC,QAAQ,GACvB,eAAY,YACsB;CAClC,IAAMC,IAASL,EAAiB,GAC1B,CAACM,GAASC,KAAcC,EAAS,EAAI,GACrC,CAACC,GAAQC,KAAaF,EAA2B,IAAI,GAErDG,IAAUC,EAAY,YAAuC;EACjE,IAAMC,IAAU,MAAMC,EAAqB;EAE3C,OADAJ,EAAUG,CAAO,GACVA;CACT,GAAG,CAAC,CAAC,GAECE,IAAQH,EACZ,OAAO,MAGmB;EACxB,IAAMI,IAAO,MAAMC,EAASC,CAAK;EAEjC,OADAR,EAAUM,CAAI,GACPA;CACT,GACA,CAAC,CACH,GAEMG,IAASP,EAAY,YAA2B;EAGpD,AAFA,MAAMQ,EAAU,GAChBV,EAAU,IAAI,GACdL,EAAO,QAAQgB,CAAS;CAC1B,GAAG,CAACA,GAAWhB,CAAM,CAAC;CAoBtB,AAlBAiB,QAA8B;EAC5B,IAAIC,IAAS;EAYb,OAXAhB,EAAW,EAAI,IACT,YAAY;GAChB,IAAI;IACF,IAAMM,IAAU,MAAMC,EAAqB;IAC3C,AAAIS,KAAQb,EAAUG,CAAO;GAC/B,QAAQ;IACN,AAAIU,KAAQb,EAAU,IAAI;GAC5B,UAAU;IACR,AAAIa,KAAQhB,EAAW,EAAK;GAC9B;EACF,EAAA,CAAG,SACgB;GACjB,IAAS;EACX;CACF,GAAG,CAAC,CAAC,GAELe,QAAsB;EACpB,AAAIhB,KAAWkB,EAAanB,EAAO,UAAUoB,CAAW,KAAKhB,KAC7DJ,EAAO,QACL,GAAGgB,EAAU,QAAQ,mBAAmBK,EAAgBrB,EAAO,QAAQ,CAAC,GAC1E;CACF,GAAG;EAACC;EAASe;EAAWZ;EAAQgB;EAAapB;CAAM,CAAC;CAEpD,IAAMsB,IAAQC,SACL;EAAE;EAAS;EAAO;EAAQ;EAAQ;CAAQ,IACjD;EAACtB;EAASS;EAAOI;EAAQV;EAAQE;CAAO,CAC1C;CAQA,OANIL,KAAW,CAACkB,EAAanB,EAAO,UAAUoB,CAAW,IAChD,kBAACI,GAAD,EAAkB,OAAM,SAAU,CAAA,IAEvC,CAACvB,KAAW,CAACG,KAAU,CAACe,EAAanB,EAAO,UAAUoB,CAAW,IAC5D,kBAACI,GAAD,EAAkB,OAAM,QAAS,CAAA,IAEnC,kBAAC3B,EAAY,UAAb;EAA6B;EAAQ;CAA+B,CAAA;AAC7E;AAKA,SAAgB4B,IAA4B;CAC1C,IAAMC,IAAMC,EAAW9B,CAAW;CAClC,IAAI,CAAC6B,GAAK,MAAU,MAAM,4CAA4C;CACtE,OAAOA;AACT;AAEA,SAASF,EAAiB,EACxB,YAGe;CACf,OACE,kBAAC,QAAD;EAAM,WAAW9B,EAAO;EACtB,UAAA,kBAACkC,GAAD;GAAY,OAAM;GAAe,SAAQ;GACtC,UAAAC;EACS,CAAA;CACR,CAAA;AAEV;AAEA,SAASV,EACP,GACA,GACS;CACT,OAAOC,EAAY,MAAM,MAAMU,MAAMC,CAAQ;AAC/C;AAEA,SAASV,EAAgB,GAAiC;CAExD,OADI,OAAO,SAAW,MAAoBU,KAAY,MAC/C,GAAG,OAAO,SAAS,WAAW,OAAO,SAAS;AACvD"}
@@ -2,7 +2,7 @@
2
2
  import { FormField as e } from "@mezzanine-ui/react";
3
3
  import { jsx as t } from "react/jsx-runtime";
4
4
  import { FormFieldDensity as n, FormFieldLayout as r } from "@mezzanine-ui/core/form";
5
- //#region src/components/bpm-form-field.tsx
5
+ // src/components/bpm-form-field.tsx
6
6
  function i({ density: i = n.TIGHT, fullWidth: a = !0, layout: o = r.HORIZONTAL, ...s }) {
7
7
  return /* @__PURE__ */ t(e, {
8
8
  density: i,
@@ -11,7 +11,6 @@ function i({ density: i = n.TIGHT, fullWidth: a = !0, layout: o = r.HORIZONTAL,
11
11
  ...s
12
12
  });
13
13
  }
14
- //#endregion
15
14
  export { i as t };
16
15
 
17
- //# sourceMappingURL=bpm-form-field-Cao0rMol.js.map
16
+ //# sourceMappingURL=bpm-form-field-9B-Det0u.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bpm-form-field-Cao0rMol.js","names":["BPMFormField","FormFieldDensity","FormFieldLayout","props","FormField"],"sources":["../../src/components/bpm-form-field.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement } from 'react';\nimport { FormField, type FormFieldProps } from '@mezzanine-ui/react';\nimport { FormFieldDensity, FormFieldLayout } from '@mezzanine-ui/core/form';\n\ntype BPMFormFieldProps = Omit<\n FormFieldProps,\n 'density' | 'fullWidth' | 'layout'\n> &\n Partial<Pick<FormFieldProps, 'density' | 'fullWidth' | 'layout'>>;\n\n/**\n * Mezzanine `<FormField>` pre-configured with the BPM admin defaults\n * (`TIGHT` density, `HORIZONTAL` layout, full width). Use everywhere a\n * label-aligned field is needed.\n */\nexport function BPMFormField({\n density = FormFieldDensity.TIGHT,\n fullWidth = true,\n layout = FormFieldLayout.HORIZONTAL,\n ...props\n}: BPMFormFieldProps): ReactElement {\n return (\n <FormField\n density={density}\n fullWidth={fullWidth}\n layout={layout}\n {...props}\n />\n );\n}\n"],"mappings":";;;;;AAiBA,SAAgBA,EAAa,EAC3B,aAAUC,EAAiB,OAC3B,eAAY,IACZ,YAASC,EAAgB,YACzB,GAAGC,KAC+B;CAClC,OACE,kBAACC,GAAD;EACW;EACE;EACH;EACR,GAAID;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"bpm-form-field-9B-Det0u.js","names":["BPMFormField","FormFieldDensity","FormFieldLayout","props","FormField"],"sources":["../../src/components/bpm-form-field.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement } from 'react';\nimport { FormField, type FormFieldProps } from '@mezzanine-ui/react';\nimport { FormFieldDensity, FormFieldLayout } from '@mezzanine-ui/core/form';\n\ntype BPMFormFieldProps = Omit<\n FormFieldProps,\n 'density' | 'fullWidth' | 'layout'\n> &\n Partial<Pick<FormFieldProps, 'density' | 'fullWidth' | 'layout'>>;\n\n/**\n * Mezzanine `<FormField>` pre-configured with the BPM admin defaults\n * (`TIGHT` density, `HORIZONTAL` layout, full width). Use everywhere a\n * label-aligned field is needed.\n */\nexport function BPMFormField({\n density = FormFieldDensity.TIGHT,\n fullWidth = true,\n layout = FormFieldLayout.HORIZONTAL,\n ...props\n}: BPMFormFieldProps): ReactElement {\n return (\n <FormField\n density={density}\n fullWidth={fullWidth}\n layout={layout}\n {...props}\n />\n );\n}\n"],"mappings":";;;;;AAiBA,SAAgBA,EAAa,EAC3B,aAAUC,EAAiB,OAC3B,eAAY,IACZ,YAASC,EAAgB,YACzB,GAAGC,KAC+B;CAClC,OACE,kBAACC,GAAD;EACW;EACE;EACH;EACR,GAAID;CACL,CAAA;AAEL"}
@@ -1 +1 @@
1
- {"version":3,"file":"bpm-form-field-Bc6k4ZEO.cjs","names":["FormFieldDensity","FormFieldLayout","FormField","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","BPMFormField","props"],"sources":["../../src/components/bpm-form-field.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement } from 'react';\nimport { FormField, type FormFieldProps } from '@mezzanine-ui/react';\nimport { FormFieldDensity, FormFieldLayout } from '@mezzanine-ui/core/form';\n\ntype BPMFormFieldProps = Omit<\n FormFieldProps,\n 'density' | 'fullWidth' | 'layout'\n> &\n Partial<Pick<FormFieldProps, 'density' | 'fullWidth' | 'layout'>>;\n\n/**\n * Mezzanine `<FormField>` pre-configured with the BPM admin defaults\n * (`TIGHT` density, `HORIZONTAL` layout, full width). Use everywhere a\n * label-aligned field is needed.\n */\nexport function BPMFormField({\n density = FormFieldDensity.TIGHT,\n fullWidth = true,\n layout = FormFieldLayout.HORIZONTAL,\n ...props\n}: BPMFormFieldProps): ReactElement {\n return (\n <FormField\n density={density}\n fullWidth={fullWidth}\n layout={layout}\n {...props}\n />\n );\n}\n"],"mappings":"sHAiBA,SAAgBM,EAAa,CAC3B,UAAUN,EAAAA,iBAAiB,MAC3B,YAAY,GACZ,SAASC,EAAAA,gBAAgB,WACzB,GAAGM,GAC+B,CAClC,OACE,EAAAH,EAAA,IAAA,CAACF,EAAAA,UAAD,CACW,UACE,YACH,SACR,GAAIK,CACL,CAAA,CAEL"}
1
+ {"version":3,"file":"bpm-form-field-Bc6k4ZEO.cjs","names":["FormFieldDensity","FormFieldLayout","FormField","_mezzanine_ui_react","react_jsx_runtime","_mezzanine_ui_core_form","BPMFormField","props"],"sources":["../../src/components/bpm-form-field.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement } from 'react';\nimport { FormField, type FormFieldProps } from '@mezzanine-ui/react';\nimport { FormFieldDensity, FormFieldLayout } from '@mezzanine-ui/core/form';\n\ntype BPMFormFieldProps = Omit<\n FormFieldProps,\n 'density' | 'fullWidth' | 'layout'\n> &\n Partial<Pick<FormFieldProps, 'density' | 'fullWidth' | 'layout'>>;\n\n/**\n * Mezzanine `<FormField>` pre-configured with the BPM admin defaults\n * (`TIGHT` density, `HORIZONTAL` layout, full width). Use everywhere a\n * label-aligned field is needed.\n */\nexport function BPMFormField({\n density = FormFieldDensity.TIGHT,\n fullWidth = true,\n layout = FormFieldLayout.HORIZONTAL,\n ...props\n}: BPMFormFieldProps): ReactElement {\n return (\n <FormField\n density={density}\n fullWidth={fullWidth}\n layout={layout}\n {...props}\n />\n );\n}\n"],"mappings":"A,sHAiBA,SAAgBM,EAAa,CAC3B,UAAUN,EAAAA,iBAAiB,MAC3B,YAAY,GACZ,SAASC,EAAAA,gBAAgB,WACzB,GAAGM,GAC+B,CAClC,OACE,EAAAH,EAAA,IAAA,CAACF,EAAAA,UAAD,CACW,UACE,YACH,SACR,GAAIK,CACL,CAAA,CAEL,C"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import { t as e } from "./format-date-time-CB-LxzqT.js";
3
- import { t } from "./bpm-form-field-Cao0rMol.js";
2
+ import { t as e } from "./bpm-form-field-9B-Det0u.js";
3
+ import { t } from "./format-date-time-B0LdmWg4.js";
4
4
  import { useCallback as n, useEffect as r, useMemo as i, useState as a } from "react";
5
5
  import { Badge as o, Button as s, Filter as c, FilterArea as l, FilterLine as u, FormField as d, Input as f, Modal as p, PageHeader as m, Section as h, SectionGroup as g, Tab as _, TabItem as v, Table as y, Textarea as b, Typography as x } from "@mezzanine-ui/react";
6
6
  import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
@@ -30,7 +30,7 @@ import '../categories.css';var A = {
30
30
  }
31
31
  ];
32
32
  function N() {
33
- let [t, o] = a([]), [b, N] = a(1), [F, I] = a(10), [L, R] = a("ALL"), [z, B] = a(0), [V, H] = a(null), [U, W] = a(null), [G, K] = a(!0), [q, J] = a(null), [Y, X] = a(!1), [Z, oe] = a(""), Q = n(async () => {
33
+ let [e, o] = a([]), [b, N] = a(1), [F, I] = a(10), [L, R] = a("ALL"), [z, B] = a(0), [V, H] = a(null), [U, W] = a(null), [G, K] = a(!0), [q, J] = a(null), [Y, X] = a(!1), [Z, oe] = a(""), Q = n(async () => {
34
34
  K(!0), W(null);
35
35
  try {
36
36
  let e = await O({
@@ -54,11 +54,11 @@ function N() {
54
54
  r(() => {
55
55
  Q();
56
56
  }, [Q]);
57
- let se = i(() => t.map((t) => ({
58
- ...t,
59
- key: t.id,
60
- updatedAtLabel: e(t.updatedAt)
61
- })), [t]), ce = i(() => [
57
+ let se = i(() => e.map((e) => ({
58
+ ...e,
59
+ key: e.id,
60
+ updatedAtLabel: t(e.updatedAt)
61
+ })), [e]), ce = i(() => [
62
62
  {
63
63
  dataIndex: "name",
64
64
  key: "name",
@@ -266,7 +266,7 @@ function N() {
266
266
  })
267
267
  ] });
268
268
  }
269
- function ne({ loading: e, modal: n, onClose: i, onSubmit: o }) {
269
+ function ne({ loading: t, modal: n, onClose: i, onSubmit: o }) {
270
270
  let [s, c] = a(""), [l, u] = a(null), [d, m] = a(""), [h, g] = a("0");
271
271
  r(() => {
272
272
  n && (c(n.record?.description ?? ""), u(null), m(n.record?.name ?? ""), g(String(n.record?.sortOrder ?? 0)));
@@ -290,7 +290,7 @@ function ne({ loading: e, modal: n, onClose: i, onSubmit: o }) {
290
290
  cancelText: "取消",
291
291
  confirmButtonProps: { disabled: !d.trim() },
292
292
  confirmText: n?.type === "EDIT" ? "儲存" : "建立",
293
- loading: e,
293
+ loading: t,
294
294
  modalType: "standard",
295
295
  onCancel: i,
296
296
  onClose: i,
@@ -303,7 +303,7 @@ function ne({ loading: e, modal: n, onClose: i, onSubmit: o }) {
303
303
  children: [/* @__PURE__ */ w("div", {
304
304
  className: A.templateModalFields,
305
305
  children: [
306
- /* @__PURE__ */ C(t, {
306
+ /* @__PURE__ */ C(e, {
307
307
  label: "分類名稱",
308
308
  name: "categoryName",
309
309
  required: !0,
@@ -318,7 +318,7 @@ function ne({ loading: e, modal: n, onClose: i, onSubmit: o }) {
318
318
  variant: "base"
319
319
  })
320
320
  }),
321
- /* @__PURE__ */ C(t, {
321
+ /* @__PURE__ */ C(e, {
322
322
  label: "排序",
323
323
  name: "categorySortOrder",
324
324
  children: /* @__PURE__ */ C(f, {
@@ -331,7 +331,7 @@ function ne({ loading: e, modal: n, onClose: i, onSubmit: o }) {
331
331
  variant: "base"
332
332
  })
333
333
  }),
334
- /* @__PURE__ */ C(t, {
334
+ /* @__PURE__ */ C(e, {
335
335
  label: "說明",
336
336
  name: "categoryDescription",
337
337
  children: /* @__PURE__ */ C(b, {
@@ -370,7 +370,6 @@ function ae(e) {
370
370
  function P(e) {
371
371
  return e instanceof Error ? e.message : "發生未知錯誤";
372
372
  }
373
- //#endregion
374
373
  export { A as n, N as t };
375
374
 
376
- //# sourceMappingURL=categories-riC33J_j.js.map
375
+ //# sourceMappingURL=categories-BAdxjNSA.js.map