@open-mercato/core 0.7.1-develop.7178.1.ab93fbaf4e → 0.7.1-develop.7180.1.9717fbbb43

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 (808) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/staff_time_entry/index.js +14 -0
  3. package/dist/generated/entities/staff_time_entry/index.js.map +2 -2
  4. package/dist/generated/entities/staff_time_entry_tag/index.js +15 -0
  5. package/dist/generated/entities/staff_time_entry_tag/index.js.map +7 -0
  6. package/dist/generated/entities/staff_time_project/index.js +16 -0
  7. package/dist/generated/entities/staff_time_project/index.js.map +2 -2
  8. package/dist/generated/entities/staff_time_report/index.js +57 -0
  9. package/dist/generated/entities/staff_time_report/index.js.map +7 -0
  10. package/dist/generated/entities/staff_time_report_entry/index.js +27 -0
  11. package/dist/generated/entities/staff_time_report_entry/index.js.map +7 -0
  12. package/dist/generated/entities/staff_time_report_event/index.js +21 -0
  13. package/dist/generated/entities/staff_time_report_event/index.js.map +7 -0
  14. package/dist/generated/entities/staff_time_report_project/index.js +15 -0
  15. package/dist/generated/entities/staff_time_report_project/index.js.map +7 -0
  16. package/dist/generated/entities/staff_time_tag/index.js +21 -0
  17. package/dist/generated/entities/staff_time_tag/index.js.map +7 -0
  18. package/dist/generated/entities/staff_time_task/index.js +37 -0
  19. package/dist/generated/entities/staff_time_task/index.js.map +7 -0
  20. package/dist/generated/entities/staff_time_task_comment/index.js +21 -0
  21. package/dist/generated/entities/staff_time_task_comment/index.js.map +7 -0
  22. package/dist/generated/entities/staff_time_task_status/index.js +29 -0
  23. package/dist/generated/entities/staff_time_task_status/index.js.map +7 -0
  24. package/dist/generated/entities/staff_time_task_tag/index.js +15 -0
  25. package/dist/generated/entities/staff_time_task_tag/index.js.map +7 -0
  26. package/dist/generated/entities.ids.generated.js +11 -1
  27. package/dist/generated/entities.ids.generated.js.map +2 -2
  28. package/dist/generated/entity-fields-registry.js +149 -0
  29. package/dist/generated/entity-fields-registry.js.map +2 -2
  30. package/dist/helpers/integration/timesheetFixtures.js +7 -0
  31. package/dist/helpers/integration/timesheetFixtures.js.map +2 -2
  32. package/dist/modules/auth/cli.js +16 -0
  33. package/dist/modules/auth/cli.js.map +2 -2
  34. package/dist/modules/auth/lib/backendChrome.js +1 -0
  35. package/dist/modules/auth/lib/backendChrome.js.map +2 -2
  36. package/dist/modules/customer_accounts/lib/customerRoleAcls.js +44 -0
  37. package/dist/modules/customer_accounts/lib/customerRoleAcls.js.map +7 -0
  38. package/dist/modules/customer_accounts/setup.js +1 -28
  39. package/dist/modules/customer_accounts/setup.js.map +2 -2
  40. package/dist/modules/data_sync/api/options.js +2 -0
  41. package/dist/modules/data_sync/api/options.js.map +2 -2
  42. package/dist/modules/data_sync/backend/data-sync/page.js +39 -17
  43. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  44. package/dist/modules/data_sync/lib/start-controls.js +42 -0
  45. package/dist/modules/data_sync/lib/start-controls.js.map +7 -0
  46. package/dist/modules/staff/acl.js +9 -1
  47. package/dist/modules/staff/acl.js.map +2 -2
  48. package/dist/modules/staff/ai-agents.js +142 -0
  49. package/dist/modules/staff/ai-agents.js.map +7 -0
  50. package/dist/modules/staff/ai-tools/time-tracking-pack.js +348 -0
  51. package/dist/modules/staff/ai-tools/time-tracking-pack.js.map +7 -0
  52. package/dist/modules/staff/ai-tools/types.js +54 -0
  53. package/dist/modules/staff/ai-tools/types.js.map +7 -0
  54. package/dist/modules/staff/ai-tools.js +8 -0
  55. package/dist/modules/staff/ai-tools.js.map +7 -0
  56. package/dist/modules/staff/analytics.js +84 -1
  57. package/dist/modules/staff/analytics.js.map +2 -2
  58. package/dist/modules/staff/api/guards.js +37 -3
  59. package/dist/modules/staff/api/guards.js.map +2 -2
  60. package/dist/modules/staff/api/leave-requests/accept/route.js +1 -3
  61. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  62. package/dist/modules/staff/api/leave-requests/reject/route.js +1 -3
  63. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  64. package/dist/modules/staff/api/portal/time-reports/[id]/route.js +131 -0
  65. package/dist/modules/staff/api/portal/time-reports/[id]/route.js.map +7 -0
  66. package/dist/modules/staff/api/portal/time-reports/route.js +179 -0
  67. package/dist/modules/staff/api/portal/time-reports/route.js.map +7 -0
  68. package/dist/modules/staff/api/team-members/self/route.js +1 -3
  69. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  70. package/dist/modules/staff/api/team-members/tags/assign/route.js +1 -3
  71. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  72. package/dist/modules/staff/api/team-members/tags/unassign/route.js +1 -3
  73. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  74. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js +174 -0
  75. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js.map +7 -0
  76. package/dist/modules/staff/api/timesheets/access-requests/route.js +226 -0
  77. package/dist/modules/staff/api/timesheets/access-requests/route.js.map +7 -0
  78. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +15 -8
  79. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
  80. package/dist/modules/staff/api/timesheets/my-projects/route.js +13 -1
  81. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
  82. package/dist/modules/staff/api/timesheets/my-work/myWorkAggregate.js +42 -0
  83. package/dist/modules/staff/api/timesheets/my-work/myWorkAggregate.js.map +7 -0
  84. package/dist/modules/staff/api/timesheets/my-work/route.js +383 -0
  85. package/dist/modules/staff/api/timesheets/my-work/route.js.map +7 -0
  86. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +14 -2
  87. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
  88. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js +168 -0
  89. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js.map +7 -0
  90. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js +246 -0
  91. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js.map +7 -0
  92. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js +183 -0
  93. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js.map +7 -0
  94. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js +164 -0
  95. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js.map +7 -0
  96. package/dist/modules/staff/api/timesheets/reports/preview/route.js +360 -0
  97. package/dist/modules/staff/api/timesheets/reports/preview/route.js.map +7 -0
  98. package/dist/modules/staff/api/timesheets/reports/route.js +316 -0
  99. package/dist/modules/staff/api/timesheets/reports/route.js.map +7 -0
  100. package/dist/modules/staff/api/timesheets/reports/shared.js +63 -0
  101. package/dist/modules/staff/api/timesheets/reports/shared.js.map +7 -0
  102. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js +164 -0
  103. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js.map +7 -0
  104. package/dist/modules/staff/api/timesheets/settings/rounding-impact/route.js +168 -0
  105. package/dist/modules/staff/api/timesheets/settings/rounding-impact/route.js.map +7 -0
  106. package/dist/modules/staff/api/timesheets/settings/route.js +199 -0
  107. package/dist/modules/staff/api/timesheets/settings/route.js.map +7 -0
  108. package/dist/modules/staff/api/timesheets/tags/access.js +76 -0
  109. package/dist/modules/staff/api/timesheets/tags/access.js.map +7 -0
  110. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js +235 -0
  111. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js.map +7 -0
  112. package/dist/modules/staff/api/timesheets/tags/route.js +160 -0
  113. package/dist/modules/staff/api/timesheets/tags/route.js.map +7 -0
  114. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js +233 -0
  115. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js.map +7 -0
  116. package/dist/modules/staff/api/timesheets/task-statuses/route.js +188 -0
  117. package/dist/modules/staff/api/timesheets/task-statuses/route.js.map +7 -0
  118. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +399 -0
  119. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +7 -0
  120. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js +210 -0
  121. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js.map +7 -0
  122. package/dist/modules/staff/api/timesheets/tasks/route.js +333 -0
  123. package/dist/modules/staff/api/timesheets/tasks/route.js.map +7 -0
  124. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js +228 -0
  125. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js.map +7 -0
  126. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +29 -10
  127. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +2 -2
  128. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +31 -18
  129. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
  130. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +21 -7
  131. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  132. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +27 -7
  133. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
  134. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +215 -32
  135. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
  136. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js +378 -0
  137. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js.map +7 -0
  138. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js +340 -0
  139. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js.map +7 -0
  140. package/dist/modules/staff/api/timesheets/time-entries/route.js +238 -26
  141. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  142. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +23 -8
  143. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
  144. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js +209 -0
  145. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js.map +7 -0
  146. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +59 -2
  147. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +2 -2
  148. package/dist/modules/staff/api/timesheets/time-projects/route.js +264 -22
  149. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  150. package/dist/modules/staff/backend/staff/time-tracking/board/page.js +110 -0
  151. package/dist/modules/staff/backend/staff/time-tracking/board/page.js.map +7 -0
  152. package/dist/modules/staff/backend/staff/time-tracking/board/page.meta.js +18 -0
  153. package/dist/modules/staff/backend/staff/time-tracking/board/page.meta.js.map +7 -0
  154. package/dist/modules/staff/backend/staff/time-tracking/entries/page.js +981 -0
  155. package/dist/modules/staff/backend/staff/time-tracking/entries/page.js.map +7 -0
  156. package/dist/modules/staff/backend/staff/time-tracking/entries/page.meta.js +18 -0
  157. package/dist/modules/staff/backend/staff/time-tracking/entries/page.meta.js.map +7 -0
  158. package/dist/modules/staff/backend/staff/time-tracking/page.js +583 -0
  159. package/dist/modules/staff/backend/staff/time-tracking/page.js.map +7 -0
  160. package/dist/modules/staff/backend/staff/time-tracking/page.meta.js +15 -0
  161. package/dist/modules/staff/backend/staff/time-tracking/page.meta.js.map +7 -0
  162. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.js +65 -0
  163. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.js.map +7 -0
  164. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.js +16 -0
  165. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.js.map +7 -0
  166. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +229 -0
  167. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +7 -0
  168. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.js +16 -0
  169. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.js.map +7 -0
  170. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +1014 -0
  171. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +7 -0
  172. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.js +16 -0
  173. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.js.map +7 -0
  174. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.js +97 -0
  175. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.js.map +7 -0
  176. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.meta.js +16 -0
  177. package/dist/modules/staff/backend/staff/time-tracking/projects/create/page.meta.js.map +7 -0
  178. package/dist/modules/staff/backend/staff/time-tracking/projects/page.js +1040 -0
  179. package/dist/modules/staff/backend/staff/time-tracking/projects/page.js.map +7 -0
  180. package/dist/modules/staff/backend/staff/time-tracking/projects/page.meta.js +19 -0
  181. package/dist/modules/staff/backend/staff/time-tracking/projects/page.meta.js.map +7 -0
  182. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +353 -0
  183. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +7 -0
  184. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js +457 -0
  185. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.js.map +7 -0
  186. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.js +16 -0
  187. package/dist/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.js.map +7 -0
  188. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.js +697 -0
  189. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.js.map +7 -0
  190. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.meta.js +16 -0
  191. package/dist/modules/staff/backend/staff/time-tracking/reports/create/page.meta.js.map +7 -0
  192. package/dist/modules/staff/backend/staff/time-tracking/reports/page.js +174 -0
  193. package/dist/modules/staff/backend/staff/time-tracking/reports/page.js.map +7 -0
  194. package/dist/modules/staff/backend/staff/time-tracking/reports/page.meta.js +18 -0
  195. package/dist/modules/staff/backend/staff/time-tracking/reports/page.meta.js.map +7 -0
  196. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +546 -0
  197. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +7 -0
  198. package/dist/modules/staff/backend/staff/time-tracking/settings/page.meta.js +18 -0
  199. package/dist/modules/staff/backend/staff/time-tracking/settings/page.meta.js.map +7 -0
  200. package/dist/modules/staff/backend/staff/time-tracking/timesheet/GridView.js +710 -0
  201. package/dist/modules/staff/backend/staff/time-tracking/timesheet/GridView.js.map +7 -0
  202. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.js +646 -0
  203. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.js.map +7 -0
  204. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.meta.js +18 -0
  205. package/dist/modules/staff/backend/staff/time-tracking/timesheet/page.meta.js.map +7 -0
  206. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -793
  207. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  208. package/dist/modules/staff/backend/staff/timesheets/page.meta.js +2 -7
  209. package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +2 -2
  210. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +5 -136
  211. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +2 -2
  212. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +1 -7
  213. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +2 -2
  214. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +5 -445
  215. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +3 -3
  216. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +1 -7
  217. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +2 -2
  218. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +4 -76
  219. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +2 -2
  220. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +1 -7
  221. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +2 -2
  222. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +4 -613
  223. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  224. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +2 -17
  225. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +2 -2
  226. package/dist/modules/staff/ce.js +40 -0
  227. package/dist/modules/staff/ce.js.map +2 -2
  228. package/dist/modules/staff/cli.js +166 -1
  229. package/dist/modules/staff/cli.js.map +2 -2
  230. package/dist/modules/staff/commands/index.js +5 -0
  231. package/dist/modules/staff/commands/index.js.map +2 -2
  232. package/dist/modules/staff/commands/timesheets-entries.js +569 -21
  233. package/dist/modules/staff/commands/timesheets-entries.js.map +3 -3
  234. package/dist/modules/staff/commands/timesheets-projects.js +450 -7
  235. package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
  236. package/dist/modules/staff/commands/timesheets-reports.js +1036 -0
  237. package/dist/modules/staff/commands/timesheets-reports.js.map +7 -0
  238. package/dist/modules/staff/commands/timesheets-tags.js +1015 -0
  239. package/dist/modules/staff/commands/timesheets-tags.js.map +7 -0
  240. package/dist/modules/staff/commands/timesheets-task-comments.js +438 -0
  241. package/dist/modules/staff/commands/timesheets-task-comments.js.map +7 -0
  242. package/dist/modules/staff/commands/timesheets-task-statuses.js +723 -0
  243. package/dist/modules/staff/commands/timesheets-task-statuses.js.map +7 -0
  244. package/dist/modules/staff/commands/timesheets-tasks.js +834 -0
  245. package/dist/modules/staff/commands/timesheets-tasks.js.map +7 -0
  246. package/dist/modules/staff/data/enrichers.js +426 -12
  247. package/dist/modules/staff/data/enrichers.js.map +2 -2
  248. package/dist/modules/staff/data/entities.js +552 -3
  249. package/dist/modules/staff/data/entities.js.map +2 -2
  250. package/dist/modules/staff/data/extensions.js +41 -0
  251. package/dist/modules/staff/data/extensions.js.map +7 -0
  252. package/dist/modules/staff/data/validators.js +254 -9
  253. package/dist/modules/staff/data/validators.js.map +2 -2
  254. package/dist/modules/staff/di.js +42 -1
  255. package/dist/modules/staff/di.js.map +2 -2
  256. package/dist/modules/staff/events.js +84 -6
  257. package/dist/modules/staff/events.js.map +2 -2
  258. package/dist/modules/staff/events.payloads.js +158 -0
  259. package/dist/modules/staff/events.payloads.js.map +7 -0
  260. package/dist/modules/staff/extension-points.js +261 -0
  261. package/dist/modules/staff/extension-points.js.map +7 -0
  262. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js +138 -0
  263. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.js.map +7 -0
  264. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.js +12 -0
  265. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.js.map +7 -0
  266. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js +133 -0
  267. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.js.map +7 -0
  268. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.js +19 -0
  269. package/dist/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.js.map +7 -0
  270. package/dist/modules/staff/lib/crud.js +11 -1
  271. package/dist/modules/staff/lib/crud.js.map +2 -2
  272. package/dist/modules/staff/lib/time-tracking/access.js +92 -0
  273. package/dist/modules/staff/lib/time-tracking/access.js.map +7 -0
  274. package/dist/modules/staff/lib/time-tracking/billability.js +39 -0
  275. package/dist/modules/staff/lib/time-tracking/billability.js.map +7 -0
  276. package/dist/modules/staff/lib/time-tracking/capacity.js +68 -0
  277. package/dist/modules/staff/lib/time-tracking/capacity.js.map +7 -0
  278. package/dist/modules/staff/lib/time-tracking/componentContracts.js +15 -0
  279. package/dist/modules/staff/lib/time-tracking/componentContracts.js.map +7 -0
  280. package/dist/modules/staff/lib/time-tracking/cost.js +82 -0
  281. package/dist/modules/staff/lib/time-tracking/cost.js.map +7 -0
  282. package/dist/modules/staff/lib/time-tracking/duration.js +55 -0
  283. package/dist/modules/staff/lib/time-tracking/duration.js.map +7 -0
  284. package/dist/modules/staff/lib/time-tracking/featureAccess.js +41 -0
  285. package/dist/modules/staff/lib/time-tracking/featureAccess.js.map +7 -0
  286. package/dist/modules/staff/lib/time-tracking/interval.js +72 -0
  287. package/dist/modules/staff/lib/time-tracking/interval.js.map +7 -0
  288. package/dist/modules/staff/lib/time-tracking/migrateProjectCodes.js +88 -0
  289. package/dist/modules/staff/lib/time-tracking/migrateProjectCodes.js.map +7 -0
  290. package/dist/modules/staff/lib/time-tracking/moneyVisibility.js +10 -0
  291. package/dist/modules/staff/lib/time-tracking/moneyVisibility.js.map +7 -0
  292. package/dist/modules/staff/lib/time-tracking/overlap.js +87 -0
  293. package/dist/modules/staff/lib/time-tracking/overlap.js.map +7 -0
  294. package/dist/modules/staff/lib/time-tracking/portalRecipients.js +27 -0
  295. package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +7 -0
  296. package/dist/modules/staff/lib/time-tracking/portalReports.js +16 -0
  297. package/dist/modules/staff/lib/time-tracking/portalReports.js.map +7 -0
  298. package/dist/modules/staff/lib/time-tracking/projectCode.js +135 -0
  299. package/dist/modules/staff/lib/time-tracking/projectCode.js.map +7 -0
  300. package/dist/modules/staff/lib/time-tracking/reapplyRounding.js +187 -0
  301. package/dist/modules/staff/lib/time-tracking/reapplyRounding.js.map +7 -0
  302. package/dist/modules/staff/lib/time-tracking/recalculationRunner.js +80 -0
  303. package/dist/modules/staff/lib/time-tracking/recalculationRunner.js.map +7 -0
  304. package/dist/modules/staff/lib/time-tracking/recalculations.js +56 -0
  305. package/dist/modules/staff/lib/time-tracking/recalculations.js.map +7 -0
  306. package/dist/modules/staff/lib/time-tracking/registries/invoke.js +63 -0
  307. package/dist/modules/staff/lib/time-tracking/registries/invoke.js.map +7 -0
  308. package/dist/modules/staff/lib/time-tracking/registries/registry.js +62 -0
  309. package/dist/modules/staff/lib/time-tracking/registries/registry.js.map +7 -0
  310. package/dist/modules/staff/lib/time-tracking/registries/scope.js +21 -0
  311. package/dist/modules/staff/lib/time-tracking/registries/scope.js.map +7 -0
  312. package/dist/modules/staff/lib/time-tracking/rollup.js +34 -0
  313. package/dist/modules/staff/lib/time-tracking/rollup.js.map +7 -0
  314. package/dist/modules/staff/lib/time-tracking/rounding.js +66 -0
  315. package/dist/modules/staff/lib/time-tracking/rounding.js.map +7 -0
  316. package/dist/modules/staff/lib/time-tracking/roundingImpact.js +39 -0
  317. package/dist/modules/staff/lib/time-tracking/roundingImpact.js.map +7 -0
  318. package/dist/modules/staff/lib/time-tracking/settingKeys.js +214 -0
  319. package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +7 -0
  320. package/dist/modules/staff/lib/time-tracking/settings.js +87 -0
  321. package/dist/modules/staff/lib/time-tracking/settings.js.map +7 -0
  322. package/dist/modules/staff/lib/time-tracking/sqlInClause.js +9 -0
  323. package/dist/modules/staff/lib/time-tracking/sqlInClause.js.map +7 -0
  324. package/dist/modules/staff/lib/time-tracking/timeEntrySources.js +48 -0
  325. package/dist/modules/staff/lib/time-tracking/timeEntrySources.js.map +7 -0
  326. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +283 -0
  327. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +7 -0
  328. package/dist/modules/staff/lib/time-tracking-ui/CustomerPicker.js +324 -0
  329. package/dist/modules/staff/lib/time-tracking-ui/CustomerPicker.js.map +7 -0
  330. package/dist/modules/staff/lib/time-tracking-ui/DurationInput.js +121 -0
  331. package/dist/modules/staff/lib/time-tracking-ui/DurationInput.js.map +7 -0
  332. package/dist/modules/staff/lib/time-tracking-ui/EntryDetailsFields.js +188 -0
  333. package/dist/modules/staff/lib/time-tracking-ui/EntryDetailsFields.js.map +7 -0
  334. package/dist/modules/staff/lib/time-tracking-ui/EntryFilterBar.js +89 -0
  335. package/dist/modules/staff/lib/time-tracking-ui/EntryFilterBar.js.map +7 -0
  336. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +855 -0
  337. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +7 -0
  338. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +360 -0
  339. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +7 -0
  340. package/dist/modules/staff/lib/time-tracking-ui/KanbanColumn.js +259 -0
  341. package/dist/modules/staff/lib/time-tracking-ui/KanbanColumn.js.map +7 -0
  342. package/dist/modules/staff/lib/time-tracking-ui/NewTaskDialog.js +238 -0
  343. package/dist/modules/staff/lib/time-tracking-ui/NewTaskDialog.js.map +7 -0
  344. package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js +130 -0
  345. package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js.map +7 -0
  346. package/dist/modules/staff/lib/time-tracking-ui/PeriodSelector.js +98 -0
  347. package/dist/modules/staff/lib/time-tracking-ui/PeriodSelector.js.map +7 -0
  348. package/dist/modules/staff/lib/time-tracking-ui/PhasePlaceholder.js +27 -0
  349. package/dist/modules/staff/lib/time-tracking-ui/PhasePlaceholder.js.map +7 -0
  350. package/dist/modules/staff/lib/time-tracking-ui/ProjectCodeField.js +166 -0
  351. package/dist/modules/staff/lib/time-tracking-ui/ProjectCodeField.js.map +7 -0
  352. package/dist/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.js +295 -0
  353. package/dist/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.js.map +7 -0
  354. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +212 -0
  355. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +7 -0
  356. package/dist/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.js +729 -0
  357. package/dist/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.js.map +7 -0
  358. package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js +217 -0
  359. package/dist/modules/staff/lib/time-tracking-ui/ReportSheet.js.map +7 -0
  360. package/dist/modules/staff/lib/time-tracking-ui/TagPicker.js +158 -0
  361. package/dist/modules/staff/lib/time-tracking-ui/TagPicker.js.map +7 -0
  362. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +224 -0
  363. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +7 -0
  364. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +93 -0
  365. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +7 -0
  366. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +1196 -0
  367. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +7 -0
  368. package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js +176 -0
  369. package/dist/modules/staff/lib/time-tracking-ui/TaskListView.js.map +7 -0
  370. package/dist/modules/staff/lib/time-tracking-ui/TaskPicker.js +307 -0
  371. package/dist/modules/staff/lib/time-tracking-ui/TaskPicker.js.map +7 -0
  372. package/dist/modules/staff/lib/time-tracking-ui/TaskQuickLog.js +284 -0
  373. package/dist/modules/staff/lib/time-tracking-ui/TaskQuickLog.js.map +7 -0
  374. package/dist/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.js +73 -0
  375. package/dist/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.js.map +7 -0
  376. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDialog.js +1499 -0
  377. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDialog.js.map +7 -0
  378. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.js +95 -0
  379. package/dist/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.js.map +7 -0
  380. package/dist/modules/staff/lib/time-tracking-ui/TimesheetCalendar.js +188 -0
  381. package/dist/modules/staff/lib/time-tracking-ui/TimesheetCalendar.js.map +7 -0
  382. package/dist/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.js +61 -0
  383. package/dist/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.js.map +7 -0
  384. package/dist/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.js +45 -0
  385. package/dist/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.js.map +7 -0
  386. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +176 -0
  387. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +7 -0
  388. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +82 -0
  389. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +7 -0
  390. package/dist/modules/staff/lib/time-tracking-ui/boardSummary.js +5 -0
  391. package/dist/modules/staff/lib/time-tracking-ui/boardSummary.js.map +7 -0
  392. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +152 -0
  393. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +7 -0
  394. package/dist/modules/staff/lib/time-tracking-ui/projectTeamAssignment.js +92 -0
  395. package/dist/modules/staff/lib/time-tracking-ui/projectTeamAssignment.js.map +7 -0
  396. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +111 -0
  397. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +7 -0
  398. package/dist/modules/staff/lib/time-tracking-ui/timeEntryDialogState.js +243 -0
  399. package/dist/modules/staff/lib/time-tracking-ui/timeEntryDialogState.js.map +7 -0
  400. package/dist/modules/staff/lib/time-tracking-ui/timeEntryListData.js +151 -0
  401. package/dist/modules/staff/lib/time-tracking-ui/timeEntryListData.js.map +7 -0
  402. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +105 -0
  403. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +7 -0
  404. package/dist/modules/staff/lib/time-tracking-ui/timesheetData.js +132 -0
  405. package/dist/modules/staff/lib/time-tracking-ui/timesheetData.js.map +7 -0
  406. package/dist/modules/staff/lib/time-tracking-ui/timesheetPeriod.js +205 -0
  407. package/dist/modules/staff/lib/time-tracking-ui/timesheetPeriod.js.map +7 -0
  408. package/dist/modules/staff/lib/time-tracking-ui/timesheetTargets.js +53 -0
  409. package/dist/modules/staff/lib/time-tracking-ui/timesheetTargets.js.map +7 -0
  410. package/dist/modules/staff/lib/time-tracking-ui/useBoardFilters.js +77 -0
  411. package/dist/modules/staff/lib/time-tracking-ui/useBoardFilters.js.map +7 -0
  412. package/dist/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.js +151 -0
  413. package/dist/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.js.map +7 -0
  414. package/dist/modules/staff/lib/timeTrackingSeeds.js +809 -0
  415. package/dist/modules/staff/lib/timeTrackingSeeds.js.map +7 -0
  416. package/dist/modules/staff/lib/timesheets/timeEntryCacheInvalidation.js +2 -3
  417. package/dist/modules/staff/lib/timesheets/timeEntryCacheInvalidation.js.map +2 -2
  418. package/dist/modules/staff/lib/timesheets/timeEntryDecoration.js +152 -0
  419. package/dist/modules/staff/lib/timesheets/timeEntryDecoration.js.map +7 -0
  420. package/dist/modules/staff/lib/timesheets-projects/budgetBurn.js +36 -0
  421. package/dist/modules/staff/lib/timesheets-projects/budgetBurn.js.map +7 -0
  422. package/dist/modules/staff/lib/timesheets-projects/budgetThreshold.js +66 -0
  423. package/dist/modules/staff/lib/timesheets-projects/budgetThreshold.js.map +7 -0
  424. package/dist/modules/staff/lib/timesheets-projects/budgetThresholdState.js +78 -0
  425. package/dist/modules/staff/lib/timesheets-projects/budgetThresholdState.js.map +7 -0
  426. package/dist/modules/staff/lib/timesheets-projects/computeProjectFinancials.js +81 -0
  427. package/dist/modules/staff/lib/timesheets-projects/computeProjectFinancials.js.map +7 -0
  428. package/dist/modules/staff/lib/timesheets-projects/reportSelection.js +44 -0
  429. package/dist/modules/staff/lib/timesheets-projects/reportSelection.js.map +7 -0
  430. package/dist/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.js +169 -0
  431. package/dist/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.js.map +7 -0
  432. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.js +22 -0
  433. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.js.map +7 -0
  434. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +51 -1
  435. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +2 -2
  436. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.js +70 -0
  437. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.js.map +7 -0
  438. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js +63 -0
  439. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js.map +7 -0
  440. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js +170 -0
  441. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js.map +7 -0
  442. package/dist/modules/staff/lib/timesheets-reports/pdf.js +205 -0
  443. package/dist/modules/staff/lib/timesheets-reports/pdf.js.map +7 -0
  444. package/dist/modules/staff/lib/timesheets-reports/reportApprovalPolicies.js +68 -0
  445. package/dist/modules/staff/lib/timesheets-reports/reportApprovalPolicies.js.map +7 -0
  446. package/dist/modules/staff/lib/timesheets-reports/reportConfigData.js +135 -0
  447. package/dist/modules/staff/lib/timesheets-reports/reportConfigData.js.map +7 -0
  448. package/dist/modules/staff/lib/timesheets-reports/reportConfigState.js +48 -0
  449. package/dist/modules/staff/lib/timesheets-reports/reportConfigState.js.map +7 -0
  450. package/dist/modules/staff/lib/timesheets-reports/reportExport.js +262 -0
  451. package/dist/modules/staff/lib/timesheets-reports/reportExport.js.map +7 -0
  452. package/dist/modules/staff/lib/timesheets-reports/reportExportFormats.js +34 -0
  453. package/dist/modules/staff/lib/timesheets-reports/reportExportFormats.js.map +7 -0
  454. package/dist/modules/staff/lib/timesheets-reports/reportGroupings.js +79 -0
  455. package/dist/modules/staff/lib/timesheets-reports/reportGroupings.js.map +7 -0
  456. package/dist/modules/staff/lib/timesheets-reports/reportLabels.js +11 -0
  457. package/dist/modules/staff/lib/timesheets-reports/reportLabels.js.map +7 -0
  458. package/dist/modules/staff/lib/timesheets-reports/reportReference.js +83 -0
  459. package/dist/modules/staff/lib/timesheets-reports/reportReference.js.map +7 -0
  460. package/dist/modules/staff/lib/timesheets-reports/reportRows.js +42 -0
  461. package/dist/modules/staff/lib/timesheets-reports/reportRows.js.map +7 -0
  462. package/dist/modules/staff/lib/timesheets-reports/reportSheetData.js +107 -0
  463. package/dist/modules/staff/lib/timesheets-reports/reportSheetData.js.map +7 -0
  464. package/dist/modules/staff/lib/timesheets-reports/reportTotals.js +289 -0
  465. package/dist/modules/staff/lib/timesheets-reports/reportTotals.js.map +7 -0
  466. package/dist/modules/staff/lib/timesheets-reports/xlsx.js +145 -0
  467. package/dist/modules/staff/lib/timesheets-reports/xlsx.js.map +7 -0
  468. package/dist/modules/staff/lib/timesheets-tasks/computeTaskRollups.js +116 -0
  469. package/dist/modules/staff/lib/timesheets-tasks/computeTaskRollups.js.map +7 -0
  470. package/dist/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.js +50 -0
  471. package/dist/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.js.map +7 -0
  472. package/dist/modules/staff/lib/timesheets-tasks/seedProjectStatuses.js +27 -0
  473. package/dist/modules/staff/lib/timesheets-tasks/seedProjectStatuses.js.map +7 -0
  474. package/dist/modules/staff/lib/timesheets-tasks/statusPositions.js +65 -0
  475. package/dist/modules/staff/lib/timesheets-tasks/statusPositions.js.map +7 -0
  476. package/dist/modules/staff/lib/timesheets-tasks/statusSlug.js +31 -0
  477. package/dist/modules/staff/lib/timesheets-tasks/statusSlug.js.map +7 -0
  478. package/dist/modules/staff/lib/timesheets-tasks/taskHierarchy.js +31 -0
  479. package/dist/modules/staff/lib/timesheets-tasks/taskHierarchy.js.map +7 -0
  480. package/dist/modules/staff/lib/timesheets-tasks/taskHoursTotals.js +17 -0
  481. package/dist/modules/staff/lib/timesheets-tasks/taskHoursTotals.js.map +7 -0
  482. package/dist/modules/staff/lib/timesheets-tasks/taskReference.js +51 -0
  483. package/dist/modules/staff/lib/timesheets-tasks/taskReference.js.map +7 -0
  484. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +11 -4
  485. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +2 -2
  486. package/dist/modules/staff/lib/timesheets-ui/ListView.js +369 -111
  487. package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +2 -2
  488. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +47 -2
  489. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +2 -2
  490. package/dist/modules/staff/migrations/Migration20260813073131_staff.js +79 -0
  491. package/dist/modules/staff/migrations/Migration20260813073131_staff.js.map +7 -0
  492. package/dist/modules/staff/migrations/Migration20260824143357_staff.js +15 -0
  493. package/dist/modules/staff/migrations/Migration20260824143357_staff.js.map +7 -0
  494. package/dist/modules/staff/notifications.client.js +16 -0
  495. package/dist/modules/staff/notifications.client.js.map +7 -0
  496. package/dist/modules/staff/notifications.handlers.js +80 -0
  497. package/dist/modules/staff/notifications.handlers.js.map +7 -0
  498. package/dist/modules/staff/notifications.js +168 -0
  499. package/dist/modules/staff/notifications.js.map +2 -2
  500. package/dist/modules/staff/search.js +159 -1
  501. package/dist/modules/staff/search.js.map +2 -2
  502. package/dist/modules/staff/setup.js +20 -1
  503. package/dist/modules/staff/setup.js.map +2 -2
  504. package/dist/modules/staff/subscribers/time-project-access-requested-notification.js +68 -0
  505. package/dist/modules/staff/subscribers/time-project-access-requested-notification.js.map +7 -0
  506. package/dist/modules/staff/subscribers/time-project-budget-threshold-notification.js +149 -0
  507. package/dist/modules/staff/subscribers/time-project-budget-threshold-notification.js.map +7 -0
  508. package/dist/modules/staff/subscribers/time-report-approved-notification.js +78 -0
  509. package/dist/modules/staff/subscribers/time-report-approved-notification.js.map +7 -0
  510. package/dist/modules/staff/subscribers/time-report-portal-broadcast.js +78 -0
  511. package/dist/modules/staff/subscribers/time-report-portal-broadcast.js.map +7 -0
  512. package/dist/modules/staff/translations.js +4 -1
  513. package/dist/modules/staff/translations.js.map +2 -2
  514. package/dist/modules/staff/widgets/components.js +7 -0
  515. package/dist/modules/staff/widgets/components.js.map +7 -0
  516. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +5 -4
  517. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +2 -2
  518. package/dist/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.js +135 -0
  519. package/dist/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.js.map +7 -0
  520. package/dist/modules/staff/widgets/notifications/index.js +5 -0
  521. package/dist/modules/staff/widgets/notifications/index.js.map +7 -0
  522. package/dist/modules/staff/workers/timesheets-reapply-rounding.js +43 -0
  523. package/dist/modules/staff/workers/timesheets-reapply-rounding.js.map +7 -0
  524. package/generated/entities/staff_time_entry/index.ts +7 -0
  525. package/generated/entities/staff_time_entry_tag/index.ts +6 -0
  526. package/generated/entities/staff_time_project/index.ts +8 -0
  527. package/generated/entities/staff_time_report/index.ts +27 -0
  528. package/generated/entities/staff_time_report_entry/index.ts +12 -0
  529. package/generated/entities/staff_time_report_event/index.ts +9 -0
  530. package/generated/entities/staff_time_report_project/index.ts +6 -0
  531. package/generated/entities/staff_time_tag/index.ts +9 -0
  532. package/generated/entities/staff_time_task/index.ts +17 -0
  533. package/generated/entities/staff_time_task_comment/index.ts +9 -0
  534. package/generated/entities/staff_time_task_status/index.ts +13 -0
  535. package/generated/entities/staff_time_task_tag/index.ts +6 -0
  536. package/generated/entities.ids.generated.ts +11 -1
  537. package/generated/entity-fields-registry.ts +149 -0
  538. package/package.json +7 -7
  539. package/src/helpers/integration/timesheetFixtures.ts +31 -1
  540. package/src/modules/auth/README.md +1 -1
  541. package/src/modules/auth/cli.ts +35 -1
  542. package/src/modules/auth/i18n/de.json +7 -0
  543. package/src/modules/auth/i18n/en.json +7 -0
  544. package/src/modules/auth/i18n/es.json +7 -0
  545. package/src/modules/auth/i18n/ko.json +7 -0
  546. package/src/modules/auth/i18n/pl.json +7 -0
  547. package/src/modules/auth/lib/backendChrome.tsx +1 -0
  548. package/src/modules/customer_accounts/lib/customerRoleAcls.ts +79 -0
  549. package/src/modules/customer_accounts/setup.ts +1 -45
  550. package/src/modules/data_sync/AGENTS.md +34 -0
  551. package/src/modules/data_sync/api/options.ts +2 -0
  552. package/src/modules/data_sync/backend/data-sync/page.tsx +82 -33
  553. package/src/modules/data_sync/i18n/de.json +1 -0
  554. package/src/modules/data_sync/i18n/en.json +1 -0
  555. package/src/modules/data_sync/i18n/es.json +1 -0
  556. package/src/modules/data_sync/i18n/ko.json +1 -0
  557. package/src/modules/data_sync/i18n/pl.json +1 -0
  558. package/src/modules/data_sync/lib/adapter.ts +45 -0
  559. package/src/modules/data_sync/lib/start-controls.ts +89 -0
  560. package/src/modules/staff/AGENTS.md +769 -1
  561. package/src/modules/staff/acl.ts +9 -0
  562. package/src/modules/staff/ai-agents.ts +189 -0
  563. package/src/modules/staff/ai-tools/time-tracking-pack.ts +494 -0
  564. package/src/modules/staff/ai-tools/types.ts +82 -0
  565. package/src/modules/staff/ai-tools.ts +13 -0
  566. package/src/modules/staff/analytics.ts +113 -0
  567. package/src/modules/staff/api/guards.ts +85 -3
  568. package/src/modules/staff/api/leave-requests/accept/route.ts +0 -2
  569. package/src/modules/staff/api/leave-requests/reject/route.ts +0 -2
  570. package/src/modules/staff/api/portal/time-reports/[id]/route.ts +182 -0
  571. package/src/modules/staff/api/portal/time-reports/route.ts +270 -0
  572. package/src/modules/staff/api/team-members/self/route.ts +0 -2
  573. package/src/modules/staff/api/team-members/tags/assign/route.ts +0 -2
  574. package/src/modules/staff/api/team-members/tags/unassign/route.ts +0 -2
  575. package/src/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.ts +292 -0
  576. package/src/modules/staff/api/timesheets/access-requests/route.ts +299 -0
  577. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +15 -7
  578. package/src/modules/staff/api/timesheets/my-projects/route.ts +14 -1
  579. package/src/modules/staff/api/timesheets/my-work/myWorkAggregate.ts +90 -0
  580. package/src/modules/staff/api/timesheets/my-work/route.ts +475 -0
  581. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +15 -2
  582. package/src/modules/staff/api/timesheets/reports/[id]/close/route.ts +203 -0
  583. package/src/modules/staff/api/timesheets/reports/[id]/export/route.ts +315 -0
  584. package/src/modules/staff/api/timesheets/reports/[id]/sheet/route.ts +220 -0
  585. package/src/modules/staff/api/timesheets/reports/[id]/unlock/route.ts +208 -0
  586. package/src/modules/staff/api/timesheets/reports/preview/route.ts +449 -0
  587. package/src/modules/staff/api/timesheets/reports/route.ts +386 -0
  588. package/src/modules/staff/api/timesheets/reports/shared.ts +121 -0
  589. package/src/modules/staff/api/timesheets/settings/reapply-rounding/route.ts +205 -0
  590. package/src/modules/staff/api/timesheets/settings/rounding-impact/route.ts +226 -0
  591. package/src/modules/staff/api/timesheets/settings/route.ts +242 -0
  592. package/src/modules/staff/api/timesheets/tags/access.ts +134 -0
  593. package/src/modules/staff/api/timesheets/tags/entry-assignments/route.ts +290 -0
  594. package/src/modules/staff/api/timesheets/tags/route.ts +177 -0
  595. package/src/modules/staff/api/timesheets/tags/task-assignments/route.ts +294 -0
  596. package/src/modules/staff/api/timesheets/task-statuses/route.ts +232 -0
  597. package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +532 -0
  598. package/src/modules/staff/api/timesheets/tasks/[id]/status/route.ts +271 -0
  599. package/src/modules/staff/api/timesheets/tasks/route.ts +443 -0
  600. package/src/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.ts +306 -0
  601. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +32 -10
  602. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +32 -17
  603. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +27 -6
  604. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +36 -6
  605. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +331 -34
  606. package/src/modules/staff/api/timesheets/time-entries/copy-day/route.ts +533 -0
  607. package/src/modules/staff/api/timesheets/time-entries/overlaps/route.ts +457 -0
  608. package/src/modules/staff/api/timesheets/time-entries/route.ts +378 -24
  609. package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +31 -9
  610. package/src/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.ts +246 -0
  611. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +62 -2
  612. package/src/modules/staff/api/timesheets/time-projects/route.ts +397 -22
  613. package/src/modules/staff/backend/staff/time-tracking/board/page.meta.ts +14 -0
  614. package/src/modules/staff/backend/staff/time-tracking/board/page.tsx +151 -0
  615. package/src/modules/staff/backend/staff/time-tracking/entries/page.meta.ts +14 -0
  616. package/src/modules/staff/backend/staff/time-tracking/entries/page.tsx +1229 -0
  617. package/src/modules/staff/backend/staff/time-tracking/page.meta.ts +11 -0
  618. package/src/modules/staff/backend/staff/time-tracking/page.tsx +823 -0
  619. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.meta.ts +12 -0
  620. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/board/page.tsx +81 -0
  621. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.meta.ts +12 -0
  622. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +275 -0
  623. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.meta.ts +12 -0
  624. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +1420 -0
  625. package/src/modules/staff/backend/staff/time-tracking/projects/create/page.meta.ts +12 -0
  626. package/src/modules/staff/backend/staff/time-tracking/projects/create/page.tsx +109 -0
  627. package/src/modules/staff/backend/staff/time-tracking/projects/page.meta.ts +15 -0
  628. package/src/modules/staff/backend/staff/time-tracking/projects/page.tsx +1254 -0
  629. package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +466 -0
  630. package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.meta.ts +12 -0
  631. package/src/modules/staff/backend/staff/time-tracking/reports/[id]/page.tsx +632 -0
  632. package/src/modules/staff/backend/staff/time-tracking/reports/create/page.meta.ts +12 -0
  633. package/src/modules/staff/backend/staff/time-tracking/reports/create/page.tsx +867 -0
  634. package/src/modules/staff/backend/staff/time-tracking/reports/page.meta.ts +14 -0
  635. package/src/modules/staff/backend/staff/time-tracking/reports/page.tsx +246 -0
  636. package/src/modules/staff/backend/staff/time-tracking/settings/page.meta.ts +14 -0
  637. package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +701 -0
  638. package/src/modules/staff/backend/staff/time-tracking/timesheet/GridView.tsx +953 -0
  639. package/src/modules/staff/backend/staff/time-tracking/timesheet/page.meta.ts +14 -0
  640. package/src/modules/staff/backend/staff/time-tracking/timesheet/page.tsx +800 -0
  641. package/src/modules/staff/backend/staff/timesheets/page.meta.ts +6 -6
  642. package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1010
  643. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +0 -6
  644. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +4 -158
  645. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +0 -6
  646. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -609
  647. package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +0 -6
  648. package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +3 -89
  649. package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +2 -19
  650. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +3 -778
  651. package/src/modules/staff/ce.ts +63 -0
  652. package/src/modules/staff/cli.ts +207 -1
  653. package/src/modules/staff/commands/index.ts +5 -0
  654. package/src/modules/staff/commands/timesheets-entries.ts +1006 -28
  655. package/src/modules/staff/commands/timesheets-projects.ts +593 -7
  656. package/src/modules/staff/commands/timesheets-reports.ts +1329 -0
  657. package/src/modules/staff/commands/timesheets-tags.ts +1315 -0
  658. package/src/modules/staff/commands/timesheets-task-comments.ts +583 -0
  659. package/src/modules/staff/commands/timesheets-task-statuses.ts +889 -0
  660. package/src/modules/staff/commands/timesheets-tasks.ts +1121 -0
  661. package/src/modules/staff/data/enrichers.ts +675 -10
  662. package/src/modules/staff/data/entities.ts +494 -2
  663. package/src/modules/staff/data/extensions.ts +68 -0
  664. package/src/modules/staff/data/validators.ts +348 -3
  665. package/src/modules/staff/di.ts +96 -0
  666. package/src/modules/staff/events.payloads.ts +268 -0
  667. package/src/modules/staff/events.ts +87 -5
  668. package/src/modules/staff/extension-points.ts +308 -0
  669. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.meta.ts +10 -0
  670. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/[id]/page.tsx +225 -0
  671. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.meta.ts +17 -0
  672. package/src/modules/staff/frontend/[orgSlug]/portal/time-reports/page.tsx +182 -0
  673. package/src/modules/staff/i18n/de.json +899 -0
  674. package/src/modules/staff/i18n/en.json +899 -0
  675. package/src/modules/staff/i18n/es.json +899 -0
  676. package/src/modules/staff/i18n/ko.json +899 -0
  677. package/src/modules/staff/i18n/pl.json +899 -0
  678. package/src/modules/staff/lib/crud.ts +14 -3
  679. package/src/modules/staff/lib/time-tracking/access.ts +155 -0
  680. package/src/modules/staff/lib/time-tracking/billability.ts +68 -0
  681. package/src/modules/staff/lib/time-tracking/capacity.ts +124 -0
  682. package/src/modules/staff/lib/time-tracking/componentContracts.ts +26 -0
  683. package/src/modules/staff/lib/time-tracking/cost.ts +144 -0
  684. package/src/modules/staff/lib/time-tracking/duration.ts +68 -0
  685. package/src/modules/staff/lib/time-tracking/featureAccess.ts +115 -0
  686. package/src/modules/staff/lib/time-tracking/interval.ts +90 -0
  687. package/src/modules/staff/lib/time-tracking/migrateProjectCodes.ts +161 -0
  688. package/src/modules/staff/lib/time-tracking/moneyVisibility.ts +37 -0
  689. package/src/modules/staff/lib/time-tracking/overlap.ts +159 -0
  690. package/src/modules/staff/lib/time-tracking/portalRecipients.ts +76 -0
  691. package/src/modules/staff/lib/time-tracking/portalReports.ts +31 -0
  692. package/src/modules/staff/lib/time-tracking/projectCode.ts +221 -0
  693. package/src/modules/staff/lib/time-tracking/reapplyRounding.ts +313 -0
  694. package/src/modules/staff/lib/time-tracking/recalculationRunner.ts +118 -0
  695. package/src/modules/staff/lib/time-tracking/recalculations.ts +135 -0
  696. package/src/modules/staff/lib/time-tracking/registries/invoke.ts +122 -0
  697. package/src/modules/staff/lib/time-tracking/registries/registry.ts +124 -0
  698. package/src/modules/staff/lib/time-tracking/registries/scope.ts +56 -0
  699. package/src/modules/staff/lib/time-tracking/rollup.ts +59 -0
  700. package/src/modules/staff/lib/time-tracking/rounding.ts +126 -0
  701. package/src/modules/staff/lib/time-tracking/roundingImpact.ts +75 -0
  702. package/src/modules/staff/lib/time-tracking/settingKeys.ts +274 -0
  703. package/src/modules/staff/lib/time-tracking/settings.ts +168 -0
  704. package/src/modules/staff/lib/time-tracking/sqlInClause.ts +22 -0
  705. package/src/modules/staff/lib/time-tracking/timeEntrySources.ts +85 -0
  706. package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +360 -0
  707. package/src/modules/staff/lib/time-tracking-ui/CustomerPicker.tsx +427 -0
  708. package/src/modules/staff/lib/time-tracking-ui/DurationInput.tsx +192 -0
  709. package/src/modules/staff/lib/time-tracking-ui/EntryDetailsFields.tsx +224 -0
  710. package/src/modules/staff/lib/time-tracking-ui/EntryFilterBar.tsx +144 -0
  711. package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +1065 -0
  712. package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +435 -0
  713. package/src/modules/staff/lib/time-tracking-ui/KanbanColumn.tsx +316 -0
  714. package/src/modules/staff/lib/time-tracking-ui/NewTaskDialog.tsx +291 -0
  715. package/src/modules/staff/lib/time-tracking-ui/NoProjectAccess.tsx +162 -0
  716. package/src/modules/staff/lib/time-tracking-ui/PeriodSelector.tsx +149 -0
  717. package/src/modules/staff/lib/time-tracking-ui/PhasePlaceholder.tsx +31 -0
  718. package/src/modules/staff/lib/time-tracking-ui/ProjectCodeField.tsx +230 -0
  719. package/src/modules/staff/lib/time-tracking-ui/ProjectCurrencyField.tsx +432 -0
  720. package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +323 -0
  721. package/src/modules/staff/lib/time-tracking-ui/ProjectTeamDrawer.tsx +930 -0
  722. package/src/modules/staff/lib/time-tracking-ui/ReportSheet.tsx +357 -0
  723. package/src/modules/staff/lib/time-tracking-ui/TagPicker.tsx +195 -0
  724. package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +243 -0
  725. package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +137 -0
  726. package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +1405 -0
  727. package/src/modules/staff/lib/time-tracking-ui/TaskListView.tsx +260 -0
  728. package/src/modules/staff/lib/time-tracking-ui/TaskPicker.tsx +435 -0
  729. package/src/modules/staff/lib/time-tracking-ui/TaskQuickLog.tsx +296 -0
  730. package/src/modules/staff/lib/time-tracking-ui/TimeEntriesSummaryFooter.tsx +97 -0
  731. package/src/modules/staff/lib/time-tracking-ui/TimeEntryDialog.tsx +1929 -0
  732. package/src/modules/staff/lib/time-tracking-ui/TimeEntryDurationCell.tsx +126 -0
  733. package/src/modules/staff/lib/time-tracking-ui/TimesheetCalendar.tsx +265 -0
  734. package/src/modules/staff/lib/time-tracking-ui/TimesheetPeriodFooter.tsx +78 -0
  735. package/src/modules/staff/lib/time-tracking-ui/TimesheetViewSwitch.tsx +70 -0
  736. package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +231 -0
  737. package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +128 -0
  738. package/src/modules/staff/lib/time-tracking-ui/boardSummary.ts +20 -0
  739. package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +228 -0
  740. package/src/modules/staff/lib/time-tracking-ui/projectTeamAssignment.ts +143 -0
  741. package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +194 -0
  742. package/src/modules/staff/lib/time-tracking-ui/timeEntryDialogState.ts +400 -0
  743. package/src/modules/staff/lib/time-tracking-ui/timeEntryListData.ts +271 -0
  744. package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +168 -0
  745. package/src/modules/staff/lib/time-tracking-ui/timesheetData.ts +225 -0
  746. package/src/modules/staff/lib/time-tracking-ui/timesheetPeriod.ts +278 -0
  747. package/src/modules/staff/lib/time-tracking-ui/timesheetTargets.ts +93 -0
  748. package/src/modules/staff/lib/time-tracking-ui/useBoardFilters.ts +107 -0
  749. package/src/modules/staff/lib/time-tracking-ui/useTimesheetPreferences.ts +245 -0
  750. package/src/modules/staff/lib/timeTrackingSeeds.ts +1037 -0
  751. package/src/modules/staff/lib/timesheets/timeEntryCacheInvalidation.ts +11 -10
  752. package/src/modules/staff/lib/timesheets/timeEntryDecoration.ts +256 -0
  753. package/src/modules/staff/lib/timesheets-projects/budgetBurn.ts +60 -0
  754. package/src/modules/staff/lib/timesheets-projects/budgetThreshold.ts +135 -0
  755. package/src/modules/staff/lib/timesheets-projects/budgetThresholdState.ts +137 -0
  756. package/src/modules/staff/lib/timesheets-projects/computeProjectFinancials.ts +142 -0
  757. package/src/modules/staff/lib/timesheets-projects/reportSelection.ts +82 -0
  758. package/src/modules/staff/lib/timesheets-projects-ui/AssignMembersDialog.tsx +237 -0
  759. package/src/modules/staff/lib/timesheets-projects-ui/ProjectBudgetCell.tsx +33 -0
  760. package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +56 -1
  761. package/src/modules/staff/lib/timesheets-projects-ui/ProjectsBulkActionsBar.tsx +90 -0
  762. package/src/modules/staff/lib/timesheets-reports/buildReportSheet.ts +125 -0
  763. package/src/modules/staff/lib/timesheets-reports/loadReportData.ts +251 -0
  764. package/src/modules/staff/lib/timesheets-reports/pdf.ts +263 -0
  765. package/src/modules/staff/lib/timesheets-reports/reportApprovalPolicies.ts +137 -0
  766. package/src/modules/staff/lib/timesheets-reports/reportConfigData.ts +247 -0
  767. package/src/modules/staff/lib/timesheets-reports/reportConfigState.ts +89 -0
  768. package/src/modules/staff/lib/timesheets-reports/reportExport.ts +373 -0
  769. package/src/modules/staff/lib/timesheets-reports/reportExportFormats.ts +71 -0
  770. package/src/modules/staff/lib/timesheets-reports/reportGroupings.ts +153 -0
  771. package/src/modules/staff/lib/timesheets-reports/reportLabels.ts +23 -0
  772. package/src/modules/staff/lib/timesheets-reports/reportReference.ts +146 -0
  773. package/src/modules/staff/lib/timesheets-reports/reportRows.ts +89 -0
  774. package/src/modules/staff/lib/timesheets-reports/reportSheetData.ts +196 -0
  775. package/src/modules/staff/lib/timesheets-reports/reportTotals.ts +544 -0
  776. package/src/modules/staff/lib/timesheets-reports/xlsx.ts +207 -0
  777. package/src/modules/staff/lib/timesheets-tasks/computeTaskRollups.ts +238 -0
  778. package/src/modules/staff/lib/timesheets-tasks/defaultStatusTemplate.ts +90 -0
  779. package/src/modules/staff/lib/timesheets-tasks/seedProjectStatuses.ts +43 -0
  780. package/src/modules/staff/lib/timesheets-tasks/statusPositions.ts +132 -0
  781. package/src/modules/staff/lib/timesheets-tasks/statusSlug.ts +43 -0
  782. package/src/modules/staff/lib/timesheets-tasks/taskHierarchy.ts +99 -0
  783. package/src/modules/staff/lib/timesheets-tasks/taskHoursTotals.ts +42 -0
  784. package/src/modules/staff/lib/timesheets-tasks/taskReference.ts +108 -0
  785. package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +18 -4
  786. package/src/modules/staff/lib/timesheets-ui/ListView.tsx +504 -149
  787. package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +50 -2
  788. package/src/modules/staff/migrations/.snapshot-open-mercato.json +3244 -228
  789. package/src/modules/staff/migrations/Migration20260813073131_staff.ts +94 -0
  790. package/src/modules/staff/migrations/Migration20260824143357_staff.ts +17 -0
  791. package/src/modules/staff/notifications.client.ts +16 -0
  792. package/src/modules/staff/notifications.handlers.ts +88 -0
  793. package/src/modules/staff/notifications.ts +163 -0
  794. package/src/modules/staff/search.ts +191 -1
  795. package/src/modules/staff/setup.ts +22 -0
  796. package/src/modules/staff/subscribers/time-project-access-requested-notification.ts +95 -0
  797. package/src/modules/staff/subscribers/time-project-budget-threshold-notification.ts +226 -0
  798. package/src/modules/staff/subscribers/time-report-approved-notification.ts +116 -0
  799. package/src/modules/staff/subscribers/time-report-portal-broadcast.ts +120 -0
  800. package/src/modules/staff/translations.ts +17 -0
  801. package/src/modules/staff/widgets/components.ts +34 -0
  802. package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +6 -5
  803. package/src/modules/staff/widgets/notifications/TimeProjectAccessRequestedRenderer.tsx +138 -0
  804. package/src/modules/staff/widgets/notifications/index.ts +1 -0
  805. package/src/modules/staff/workers/timesheets-reapply-rounding.ts +59 -0
  806. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +0 -123
  807. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +0 -7
  808. package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +0 -138
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { useQueries, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n DndContext,\n DragOverlay,\n MeasuringStrategy,\n PointerSensor,\n pointerWithin,\n useSensor,\n useSensors,\n type Announcements,\n type CollisionDetection,\n type DragEndEvent,\n type DragStartEvent,\n type ScreenReaderInstructions,\n type UniqueIdentifier,\n} from '@dnd-kit/core'\nimport { Plus, RotateCcw } from 'lucide-react'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useBackendChrome } from '@open-mercato/ui/backend/BackendChromeProvider'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { hasFeature } from '@open-mercato/shared/security/features'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { sumTaskLoggedMinutes } from '../timesheets-tasks/taskHoursTotals'\nimport { KanbanColumn, KANBAN_COLUMN_DROPPABLE_PREFIX } from './KanbanColumn'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport { TaskDrawer } from './TaskDrawer'\nimport type { KanbanMoveTarget, KanbanTagOption } from './KanbanCard'\nimport {\n BOARD_DIRECTORY_PAGE_SIZE,\n BOARD_PAGE_SIZE,\n BOARD_QUERY_ROOT,\n boardColumnQueryKey,\n fetchTaskPages,\n useAssigneeNames,\n useBoardSelf,\n useBoardStatuses,\n useTagLabels,\n} from './boardDirectory'\nimport {\n EMPTY_BOARD_FILTERS,\n boardServerFilterKey,\n boardServerFilterParams,\n visibleBoardStatusIds,\n type BoardFilters,\n} from './boardFilters'\nimport type { BoardSummary } from './boardSummary'\nimport {\n computeSubtaskProgress,\n formatBoardMinutes,\n nextPositionAtColumnTop,\n readItems,\n readString,\n sortByPosition,\n toBoardTask,\n type BoardApiRow,\n type BoardTask,\n} from './kanbanBoardData'\n\nconst logger = createLogger('staff').child({ component: 'KanbanBoard' })\n\nexport { BOARD_PAGE_SIZE, BOARD_DIRECTORY_PAGE_SIZE }\nexport const BOARD_MAX_CHILD_PAGES = 5\nexport const MOVE_MUTATION_CONTEXT_ID = 'staff.time_tracking.board.move'\nexport const CREATE_MUTATION_CONTEXT_ID = 'staff.time_tracking.board.create'\nexport const MANAGE_COLUMNS_FEATURE = 'staff.timesheets.projects.manage'\nexport const MANAGE_TASKS_FEATURE = 'staff.timesheets.tasks.manage'\nexport const TASK_STATUS_CHANGED_EVENT = 'staff.timesheets.time_task.status_changed'\n\n/** Window a locally-originated move stays \"mine\" for, so a lost SSE cannot wedge the filter. */\nconst OWN_MOVE_ECHO_TTL_MS = 15_000\n\ntype ColumnCache = { items: BoardApiRow[]; total: number }\n\ntype PendingMove = {\n taskId: string\n targetStatusId: string\n}\n\nexport type KanbanBoardProps = {\n timeProjectId: string\n /** Used by the drawer's header; the page owns the breadcrumb and the rest of the chrome. */\n projectName?: string | null\n /** Board filters (T3.8). Assignee narrows the request, status picks columns, tag filters rows. */\n filters?: BoardFilters\n /** Reports what is on screen so the page head can describe it without a second fetch. */\n onSummaryChange?: (summary: BoardSummary) => void\n}\n\nfunction statusIdFromColumnKey(key: readonly unknown[]): string | null {\n const part = key.find((entry) => typeof entry === 'string' && entry.startsWith('status:'))\n return typeof part === 'string' ? part.slice('status:'.length) : null\n}\n\n/**\n * `true` when `candidate` names a strictly earlier version than `reference`.\n * Unparseable input answers `false`, so an unexpected format leaves whatever the\n * list handed us in charge rather than pinning the board to a remembered token.\n */\nfunction isOlderVersion(candidate: string, reference: string): boolean {\n const candidateAt = Date.parse(candidate)\n const referenceAt = Date.parse(reference)\n if (!Number.isFinite(candidateAt) || !Number.isFinite(referenceAt)) return false\n return candidateAt < referenceAt\n}\n\n/**\n * The Kanban board of screen 6 (T3.6, US-C1/US-C2).\n *\n * Four things carry the design intent and are worth reading before changing anything:\n *\n * 1. **The move is optimistic and the rollback is exact.** Before the PATCH the board\n * snapshots every column cache; the card is moved between them immediately. On any\n * failure the whole snapshot is written back, which returns the card to the column\n * it came from even when the drag crossed columns whose pages had shifted.\n * 2. **A 409 is not a retryable failure.** The PATCH carries the card's `updatedAt` in\n * the optimistic-lock header, so a 409 means somebody else moved this card while the\n * drag was in flight. `surfaceRecordConflict` raises the shared conflict bar, the\n * board refetches, and no Retry is offered \u2014 retrying would overwrite the other\n * move. Every other failure gets the retry affordance of note 2.\n * 3. **Echoes of your own move are ignored.** `status_changed` is broadcast to every\n * connected board, including the one that caused it. Each locally-issued move\n * registers a `taskId|statusId` key that the event handler consumes instead of\n * refetching, so a colleague's drag moves the card here and yours does not fight the\n * optimistic update that already landed.\n * 4. **The next move's version comes out of the last move's response.** A move bumps\n * the row's `updated_at`, so the version the board is holding for that card is spent\n * the moment the PATCH commits \u2014 and the optimistic write of note 1 carries the\n * pre-move version forward until a refetch replaces it. Reading the version back off\n * the response (as `TaskDrawer` already does) is what lets the same card be moved\n * twice in a row; waiting for the refetch made every second move answer 409 \"changed\n * by someone else\" with nobody else editing.\n */\nexport function KanbanBoard({\n timeProjectId,\n projectName,\n filters = EMPTY_BOARD_FILTERS,\n onSummaryChange,\n}: KanbanBoardProps): React.ReactElement {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const queryClient = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const { payload } = useBackendChrome()\n const canManageColumns = hasFeature(payload?.grantedFeatures, MANAGE_COLUMNS_FEATURE)\n const canManageTasks = hasFeature(payload?.grantedFeatures, MANAGE_TASKS_FEATURE)\n const serverFilterKey = boardServerFilterKey(filters)\n const serverFilterParams = boardServerFilterParams(filters)\n\n const [pagesByStatus, setPagesByStatus] = React.useState<Record<string, number>>({})\n const [activeDragTaskId, setActiveDragTaskId] = React.useState<string | null>(null)\n const [pendingTaskIds, setPendingTaskIds] = React.useState<ReadonlySet<string>>(new Set())\n const [failedMove, setFailedMove] = React.useState<PendingMove | null>(null)\n const [quickAddPendingStatusId, setQuickAddPendingStatusId] = React.useState<string | null>(null)\n const [composingStatus, setComposingStatus] = React.useState(false)\n const [statusDraft, setStatusDraft] = React.useState('')\n\n const ownMoveKeysRef = React.useRef(new Map<string, number>())\n\n // The version the server confirmed for a card in its own move response, kept until\n // a fetched row catches up with it (note 4). \"Newest wins\" never suppresses a real\n // conflict: somebody else's move produces a version NEWER than the one confirmed\n // here, and the row that carries it takes over \u2014 this only stops the board from\n // replaying a version its own last move already spent.\n const confirmedVersionsRef = React.useRef(new Map<string, string>())\n\n const resolveTaskVersion = React.useCallback(\n (taskId: string, rowVersion: string | null): string | null => {\n const confirmed = confirmedVersionsRef.current.get(taskId)\n if (!confirmed) return rowVersion\n if (rowVersion && !isOlderVersion(rowVersion, confirmed)) {\n confirmedVersionsRef.current.delete(taskId)\n return rowVersion\n }\n return confirmed\n },\n [],\n )\n\n const { runMutation: runMoveMutation, retryLastMutation: retryMoveMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: MOVE_MUTATION_CONTEXT_ID,\n blockedMessage: t('staff.time_tracking.board.move.error', 'Could not move the task.'),\n })\n\n const { runMutation: runCreateMutation, retryLastMutation: retryCreateMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: CREATE_MUTATION_CONTEXT_ID,\n blockedMessage: t('staff.time_tracking.board.quickAdd.error', 'Could not create the task.'),\n })\n\n const statusesQuery = useBoardStatuses(timeProjectId)\n\n const statuses = React.useMemo(() => statusesQuery.data ?? [], [statusesQuery.data])\n\n // A status filter is not a request parameter here \u2014 it selects which columns exist.\n const visibleStatuses = React.useMemo(\n () => visibleBoardStatusIds(statuses, filters),\n [filters, statuses],\n )\n\n const columnQueries = useQueries({\n queries: visibleStatuses.map((status) => {\n const pages = pagesByStatus[status.id] ?? 1\n return {\n queryKey: boardColumnQueryKey(scopeVersion, timeProjectId, status.id, pages, serverFilterKey),\n staleTime: 15_000,\n queryFn: async (): Promise<ColumnCache> =>\n fetchTaskPages(\n (page) =>\n `timeProjectId=${encodeURIComponent(timeProjectId)}&taskStatusId=${encodeURIComponent(status.id)}&topLevelOnly=true&page=${page}&pageSize=${BOARD_PAGE_SIZE}&sortField=position&sortDir=asc${serverFilterParams}`,\n pages,\n ),\n }\n }),\n })\n\n const tasksByStatusId = React.useMemo(() => {\n const map = new Map<string, { tasks: BoardTask[]; loaded: number; total: number }>()\n visibleStatuses.forEach((status, index) => {\n const data = columnQueries[index]?.data\n const loaded = (data?.items ?? [])\n .map(toBoardTask)\n .filter((task): task is BoardTask => task !== null)\n map.set(status.id, {\n tasks: sortByPosition(loaded),\n loaded: loaded.length,\n total: data?.total ?? loaded.length,\n })\n })\n return map\n }, [columnQueries, visibleStatuses])\n\n const allTasks = React.useMemo(() => {\n const rows: BoardTask[] = []\n for (const entry of tasksByStatusId.values()) rows.push(...entry.tasks)\n return rows\n }, [tasksByStatusId])\n\n const hasChildren = React.useMemo(() => allTasks.some((task) => task.childCount > 0), [allTasks])\n\n const childrenQuery = useQuery<BoardTask[]>({\n queryKey: [...BOARD_QUERY_ROOT, 'children', `scope:${scopeVersion}`, `project:${timeProjectId}`],\n enabled: hasChildren,\n staleTime: 30_000,\n queryFn: async () => {\n // The list route filters children only by a single `parentTaskId`, so a board-wide\n // sweep is the one request that answers \"how many of each card's subtasks are done\"\n // without one call per card. Bounded, because the count is decoration, not data.\n const { items } = await fetchTaskPages(\n (page) =>\n `timeProjectId=${encodeURIComponent(timeProjectId)}&page=${page}&pageSize=${BOARD_PAGE_SIZE}&sortField=position&sortDir=asc`,\n BOARD_MAX_CHILD_PAGES,\n )\n return items\n .map(toBoardTask)\n .filter((task): task is BoardTask => task !== null && !!task.parentTaskId)\n },\n })\n\n const doneStatusIds = React.useMemo(\n () => new Set(statuses.filter((status) => status.isDone).map((status) => status.id)),\n [statuses],\n )\n\n const subtasksByTaskId = React.useMemo(\n () => computeSubtaskProgress(childrenQuery.data ?? [], doneStatusIds),\n [childrenQuery.data, doneStatusIds],\n )\n\n const assigneeIds = React.useMemo(() => {\n const ids = new Set<string>()\n for (const task of allTasks) {\n if (task.assigneeStaffMemberId) ids.add(task.assigneeStaffMemberId)\n }\n return Array.from(ids).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }, [allTasks])\n\n const assigneeQuery = useAssigneeNames(assigneeIds)\n\n const tagIds = React.useMemo(() => {\n const ids = new Set<string>()\n for (const task of allTasks) {\n for (const id of task.tagIds) ids.add(id)\n }\n return Array.from(ids).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n }, [allTasks])\n\n const tagQuery = useTagLabels(tagIds)\n\n // A chip carries a tag's name or it is not drawn at all. The label lookup is a\n // separate request from the card's own row, so falling back to the id painted a\n // raw uuid on the card for as long as that request was in flight.\n const tagsByTaskId = React.useMemo(() => {\n const labels = tagQuery.data ?? new Map<string, string>()\n const map = new Map<string, KanbanTagOption[]>()\n for (const task of allTasks) {\n if (task.tagIds.length === 0) continue\n const named: KanbanTagOption[] = []\n for (const id of task.tagIds) {\n const label = labels.get(id)\n if (label) named.push({ id, label })\n }\n if (named.length === 0) continue\n map.set(task.id, named)\n }\n return map\n }, [allTasks, tagQuery.data])\n\n const selfQuery = useBoardSelf()\n\n const selfStaffMemberId = selfQuery.data?.id ?? null\n\n const runningTimerQuery = useQuery<{ entryId: string | null; taskId: string | null }>({\n queryKey: [...BOARD_QUERY_ROOT, 'running-timer', `scope:${scopeVersion}`, selfStaffMemberId ?? 'none'],\n enabled: !!selfStaffMemberId,\n staleTime: 15_000,\n refetchInterval: 30_000,\n queryFn: async () => {\n if (!selfStaffMemberId) return { entryId: null, taskId: null }\n const call = await apiCall<Record<string, unknown>>(\n `/api/staff/timesheets/time-entries?staffMemberId=${encodeURIComponent(selfStaffMemberId)}&running=true&pageSize=${BOARD_PAGE_SIZE}`,\n )\n if (!call.ok) return { entryId: null, taskId: null }\n for (const row of readItems(call.result)) {\n const endedAt = readString(row, 'ended_at', 'endedAt')\n const startedAt = readString(row, 'started_at', 'startedAt')\n if (!startedAt || endedAt) continue\n return { entryId: readString(row, 'id'), taskId: readString(row, 'task_id', 'taskId') }\n }\n return { entryId: null, taskId: null }\n },\n })\n\n const runningTimerTaskId = runningTimerQuery.data?.taskId ?? null\n const runningTimerEntryId = runningTimerQuery.data?.entryId ?? null\n\n const invalidateBoard = React.useCallback(() => {\n queryClient.invalidateQueries({ queryKey: [...BOARD_QUERY_ROOT, 'column'] }).catch(() => {})\n queryClient.invalidateQueries({ queryKey: [...BOARD_QUERY_ROOT, 'children'] }).catch(() => {})\n }, [queryClient])\n\n const invalidateStatuses = React.useCallback(() => {\n queryClient.invalidateQueries({ queryKey: [...BOARD_QUERY_ROOT, 'statuses'] }).catch(() => {})\n }, [queryClient])\n\n const markOwnMove = React.useCallback((taskId: string, statusId: string) => {\n ownMoveKeysRef.current.set(`${taskId}|${statusId}`, Date.now())\n }, [])\n\n const consumeOwnMove = React.useCallback((taskId: string, statusId: string): boolean => {\n const keys = ownMoveKeysRef.current\n const key = `${taskId}|${statusId}`\n const stamped = keys.get(key)\n // Drop stale entries so a broadcast that never arrived cannot suppress a later,\n // genuinely remote move of the same card into the same column.\n for (const [entry, at] of keys) {\n if (Date.now() - at > OWN_MOVE_ECHO_TTL_MS) keys.delete(entry)\n }\n if (stamped === undefined) return false\n keys.delete(key)\n return true\n }, [])\n\n useAppEvent(\n TASK_STATUS_CHANGED_EVENT,\n (event) => {\n const eventPayload = event.payload as Record<string, unknown> | null | undefined\n if (!eventPayload) return\n const projectId = typeof eventPayload.timeProjectId === 'string' ? eventPayload.timeProjectId : null\n if (projectId && projectId !== timeProjectId) return\n const taskId =\n typeof eventPayload.taskId === 'string'\n ? eventPayload.taskId\n : typeof eventPayload.id === 'string'\n ? eventPayload.id\n : null\n const statusId = typeof eventPayload.taskStatusId === 'string' ? eventPayload.taskStatusId : null\n if (taskId && statusId && consumeOwnMove(taskId, statusId)) return\n invalidateBoard()\n },\n [consumeOwnMove, invalidateBoard, timeProjectId],\n )\n\n const setTaskPending = React.useCallback((taskId: string, pending: boolean) => {\n setPendingTaskIds((previous) => {\n const next = new Set(previous)\n if (pending) next.add(taskId)\n else next.delete(taskId)\n return next\n })\n }, [])\n\n const moveTask = React.useCallback(\n (taskId: string, targetStatusId: string) => {\n const columnCaches = queryClient.getQueriesData<ColumnCache>({\n queryKey: [...BOARD_QUERY_ROOT, 'column'],\n })\n // The full pre-move picture. Restoring it wholesale is what puts the card back in\n // its origin column on failure, regardless of how many columns the drag touched.\n const snapshot = columnCaches.map(([key, data]) => [key, data] as const)\n\n let sourceStatusId: string | null = null\n let movingRow: BoardApiRow | null = null\n for (const [key, data] of columnCaches) {\n if (!data) continue\n const statusId = statusIdFromColumnKey(key as readonly unknown[])\n if (!statusId) continue\n const index = data.items.findIndex((item) => readString(item, 'id') === taskId)\n if (index < 0) continue\n sourceStatusId = statusId\n movingRow = { ...data.items[index], task_status_id: targetStatusId, taskStatusId: targetStatusId }\n queryClient.setQueryData(key, {\n items: data.items.filter((item) => readString(item, 'id') !== taskId),\n total: Math.max(0, data.total - 1),\n })\n break\n }\n\n if (!movingRow || !sourceStatusId || sourceStatusId === targetStatusId) {\n for (const [key, data] of snapshot) queryClient.setQueryData(key, data)\n return\n }\n\n const targetTasks = tasksByStatusId.get(targetStatusId)?.tasks ?? []\n const position = nextPositionAtColumnTop(targetTasks)\n const landed: BoardApiRow = { ...movingRow, position }\n\n for (const [key, data] of columnCaches) {\n if (!data) continue\n if (statusIdFromColumnKey(key as readonly unknown[]) !== targetStatusId) continue\n queryClient.setQueryData(key, {\n items: [landed, ...data.items],\n total: data.total + 1,\n })\n }\n\n const taskVersion = resolveTaskVersion(taskId, readString(movingRow, 'updated_at', 'updatedAt'))\n setTaskPending(taskId, true)\n setFailedMove(null)\n markOwnMove(taskId, targetStatusId)\n\n runMoveMutation({\n operation: async () => {\n const call = await withScopedApiRequestHeaders(buildOptimisticLockHeader(taskVersion), () =>\n apiCallOrThrow<Record<string, unknown>>(\n `/api/staff/timesheets/tasks/${encodeURIComponent(taskId)}/status`,\n {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ taskStatusId: targetStatusId, position }),\n },\n { errorMessage: t('staff.time_tracking.board.move.error', 'Could not move the task.') },\n ),\n )\n return readString(call.result ?? {}, 'updatedAt', 'updated_at')\n },\n context: {\n formId: MOVE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.task',\n resourceId: taskId,\n retryLastMutation: retryMoveMutation,\n },\n })\n .then((confirmedVersion) => {\n // Note 4: the card the optimistic write left in the target column still\n // carries the version this move just spent, so the response's version has\n // to take over until a fetched row carries a newer one.\n if (confirmedVersion) confirmedVersionsRef.current.set(taskId, confirmedVersion)\n invalidateBoard()\n })\n .catch((error: unknown) => {\n // Card first: it goes back where it came from before anything else is decided.\n for (const [key, data] of snapshot) queryClient.setQueryData(key, data)\n consumeOwnMove(taskId, targetStatusId)\n if (surfaceRecordConflict(error, t)) {\n // Somebody else moved this card. Refetch and let the conflict bar speak \u2014\n // retrying here would silently overwrite their move. The version this board\n // remembered is behind the server's, so the refetched row takes over.\n confirmedVersionsRef.current.delete(taskId)\n invalidateBoard()\n return\n }\n setFailedMove({ taskId, targetStatusId })\n const message =\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.move.error', 'Could not move the task.')\n flash(message, 'error')\n })\n .finally(() => {\n setTaskPending(taskId, false)\n })\n },\n [\n consumeOwnMove,\n invalidateBoard,\n markOwnMove,\n queryClient,\n resolveTaskVersion,\n retryMoveMutation,\n runMoveMutation,\n setTaskPending,\n t,\n tasksByStatusId,\n ],\n )\n\n // Pointer only. dnd-kit's keyboard sensor would have to own Enter/Space on the card \u2014\n // the key that opens the drawer \u2014 and it has no sortable context to traverse anyway;\n // keyboard moves go through the card's explicit \"Move\" menu, which calls `moveTask`\n // directly (U3).\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }))\n\n const collisionDetection = React.useCallback<CollisionDetection>((args) => pointerWithin(args), [])\n\n const measuringConfig = React.useMemo(\n () => ({ droppable: { strategy: MeasuringStrategy.BeforeDragging } }),\n [],\n )\n\n const statusIdByTaskId = React.useMemo(() => {\n const map = new Map<string, string>()\n for (const [statusId, entry] of tasksByStatusId) {\n for (const task of entry.tasks) map.set(task.id, statusId)\n }\n return map\n }, [tasksByStatusId])\n\n const activeDragTask = React.useMemo(\n () => (activeDragTaskId ? allTasks.find((task) => task.id === activeDragTaskId) ?? null : null),\n [activeDragTaskId, allTasks],\n )\n\n const handleDragStart = React.useCallback((event: DragStartEvent) => {\n setActiveDragTaskId(typeof event.active.id === 'string' ? event.active.id : null)\n }, [])\n\n const handleDragCancel = React.useCallback(() => setActiveDragTaskId(null), [])\n\n const targetStatusIdFor = React.useCallback(\n (overId: UniqueIdentifier | null | undefined): string | null => {\n if (typeof overId !== 'string') return null\n return overId.startsWith(KANBAN_COLUMN_DROPPABLE_PREFIX)\n ? overId.slice(KANBAN_COLUMN_DROPPABLE_PREFIX.length)\n : statusIdByTaskId.get(overId) ?? null\n },\n [statusIdByTaskId],\n )\n\n const handleDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n setActiveDragTaskId(null)\n const taskId = typeof event.active.id === 'string' ? event.active.id : null\n if (!taskId) return\n const targetStatusId = targetStatusIdFor(event.over?.id)\n if (!targetStatusId) return\n if (statusIdByTaskId.get(taskId) === targetStatusId) return\n moveTask(taskId, targetStatusId)\n },\n [moveTask, statusIdByTaskId, targetStatusIdFor],\n )\n\n const moveTargets = React.useMemo<KanbanMoveTarget[]>(\n () => visibleStatuses.map((status) => ({ id: status.id, name: status.name })),\n [visibleStatuses],\n )\n\n const describeTask = React.useCallback(\n (taskId: UniqueIdentifier | null | undefined): string => {\n if (typeof taskId !== 'string') return ''\n return allTasks.find((task) => task.id === taskId)?.title ?? taskId\n },\n [allTasks],\n )\n\n const describeColumn = React.useCallback(\n (overId: UniqueIdentifier | null | undefined): string | null => {\n const statusId = targetStatusIdFor(overId)\n if (!statusId) return null\n return statuses.find((status) => status.id === statusId)?.name ?? statusId\n },\n [statuses, targetStatusIdFor],\n )\n\n // dnd-kit narrates every drag through a live region. Left unset it narrates in English\n // regardless of locale (U9), so the board owns the strings.\n const announcements = React.useMemo<Announcements>(\n () => ({\n onDragStart: ({ active }) =>\n t('staff.time_tracking.board.dnd.dragStart', 'Picked up the task {task}.', {\n task: describeTask(active.id),\n }),\n onDragOver: ({ active, over }) => {\n const column = describeColumn(over?.id)\n return column\n ? t('staff.time_tracking.board.dnd.dragOver', 'The task {task} is over the column {column}.', {\n task: describeTask(active.id),\n column,\n })\n : t('staff.time_tracking.board.dnd.dragOverNothing', 'The task {task} is not over a column.', {\n task: describeTask(active.id),\n })\n },\n onDragEnd: ({ active, over }) => {\n const column = describeColumn(over?.id)\n return column\n ? t('staff.time_tracking.board.dnd.dragEnd', 'The task {task} was dropped into the column {column}.', {\n task: describeTask(active.id),\n column,\n })\n : t('staff.time_tracking.board.dnd.dragEndOutside', 'The task {task} was dropped outside the columns.', {\n task: describeTask(active.id),\n })\n },\n onDragCancel: ({ active }) =>\n t('staff.time_tracking.board.dnd.dragCancel', 'Moving the task {task} was cancelled.', {\n task: describeTask(active.id),\n }),\n }),\n [describeColumn, describeTask, t],\n )\n\n const screenReaderInstructions = React.useMemo<ScreenReaderInstructions>(\n () => ({\n draggable: t(\n 'staff.time_tracking.board.dnd.instructions',\n 'Drag a card with the pointer to move it between columns. With the keyboard, press Enter on a card to open it, or use the Move button in the card actions to choose a target column.',\n ),\n }),\n [t],\n )\n\n const accessibility = React.useMemo(\n () => ({ announcements, screenReaderInstructions }),\n [announcements, screenReaderInstructions],\n )\n\n const handleQuickAdd = React.useCallback(\n async (statusId: string, title: string) => {\n setQuickAddPendingStatusId(statusId)\n try {\n await runCreateMutation({\n operation: () =>\n apiCallOrThrow(\n '/api/staff/timesheets/tasks',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n timeProjectId,\n taskStatusId: statusId,\n title,\n // US-C1: the creator owns what they just typed until somebody reassigns it.\n assigneeStaffMemberId: selfStaffMemberId,\n }),\n },\n { errorMessage: t('staff.time_tracking.board.quickAdd.error', 'Could not create the task.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.task',\n resourceId: statusId,\n retryLastMutation: retryCreateMutation,\n },\n })\n invalidateBoard()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n logger.error('staff.time_tracking board quick add failed', { err: error })\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.quickAdd.error', 'Could not create the task.'),\n 'error',\n )\n } finally {\n setQuickAddPendingStatusId(null)\n }\n },\n [invalidateBoard, retryCreateMutation, runCreateMutation, selfStaffMemberId, t, timeProjectId],\n )\n\n const handleCreateStatus = React.useCallback(async () => {\n const name = statusDraft.trim()\n if (!name) {\n setComposingStatus(false)\n setStatusDraft('')\n return\n }\n try {\n await runCreateMutation({\n operation: () =>\n apiCallOrThrow(\n '/api/staff/timesheets/task-statuses',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ timeProjectId, name }),\n },\n { errorMessage: t('staff.time_tracking.board.addStatus.error', 'Could not add the column.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.task_status',\n resourceId: timeProjectId,\n retryLastMutation: retryCreateMutation,\n },\n })\n setStatusDraft('')\n setComposingStatus(false)\n invalidateStatuses()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.addStatus.error', 'Could not add the column.'),\n 'error',\n )\n }\n }, [invalidateStatuses, retryCreateMutation, runCreateMutation, statusDraft, t, timeProjectId])\n\n const handleLoadMore = React.useCallback((statusId: string) => {\n setPagesByStatus((previous) => ({ ...previous, [statusId]: (previous[statusId] ?? 1) + 1 }))\n }, [])\n\n const openTask = React.useCallback(\n (taskId: string) => {\n // Seam for the task drawer (T3.7): the drawer reads `?task=` and the board keeps\n // rendering underneath it.\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.set('task', taskId)\n router.push(`?${params.toString()}`, { scroll: false })\n },\n [router, searchParams],\n )\n\n const handleAddTime = React.useCallback(\n (taskId: string) => {\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.set('task', taskId)\n params.set('panel', 'time')\n router.push(`?${params.toString()}`, { scroll: false })\n },\n [router, searchParams],\n )\n\n const drawerTaskId = searchParams?.get('task') ?? null\n const drawerPanel = searchParams?.get('panel') ?? null\n\n const closeTaskDrawer = React.useCallback(() => {\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n params.delete('task')\n params.delete('panel')\n const query = params.toString()\n router.push(query.length > 0 ? `?${query}` : '?', { scroll: false })\n }, [router, searchParams])\n\n const handleStartTimer = React.useCallback(\n async (taskId: string) => {\n if (!selfStaffMemberId) return\n const task = allTasks.find((entry) => entry.id === taskId) ?? null\n try {\n const started = await runCreateMutation({\n operation: () =>\n apiCallOrThrow<Record<string, unknown>>(\n '/api/staff/timesheets/time-entries/start-timer',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n staffMemberId: selfStaffMemberId,\n timeProjectId,\n date: new Date().toISOString().slice(0, 10),\n notes: task?.title ?? null,\n }),\n },\n { errorMessage: t('staff.time_tracking.board.timer.startError', 'Could not start the timer.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: taskId,\n retryLastMutation: retryCreateMutation,\n },\n })\n const entryId = typeof started?.result?.id === 'string' ? started.result.id : null\n if (entryId) {\n // `start-timer` creates the entry atomically but takes no task, so the link is a\n // second write. A failure here leaves a running, project-level timer rather than\n // no timer at all \u2014 the lesser of the two wrong states.\n const linked = await apiCall(`/api/staff/timesheets/time-entries`, {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: entryId, taskId }),\n })\n if (!linked.ok) {\n flash(\n t(\n 'staff.time_tracking.board.timer.linkWarning',\n 'The timer is running but is not linked to this task yet.',\n ),\n 'warning',\n )\n }\n }\n await runningTimerQuery.refetch()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.timer.startError', 'Could not start the timer.'),\n 'error',\n )\n }\n },\n [allTasks, retryCreateMutation, runCreateMutation, runningTimerQuery, selfStaffMemberId, t, timeProjectId],\n )\n\n const handleStopTimer = React.useCallback(async () => {\n if (!runningTimerEntryId) return\n try {\n await runCreateMutation({\n operation: () =>\n apiCallOrThrow(\n `/api/staff/timesheets/time-entries/${encodeURIComponent(runningTimerEntryId)}/timer-stop`,\n { method: 'POST' },\n { errorMessage: t('staff.time_tracking.board.timer.stopError', 'Could not stop the timer.') },\n ),\n context: {\n formId: CREATE_MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: runningTimerEntryId,\n retryLastMutation: retryCreateMutation,\n },\n })\n await runningTimerQuery.refetch()\n invalidateBoard()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) return\n flash(\n error instanceof Error && error.message\n ? error.message\n : t('staff.time_tracking.board.timer.stopError', 'Could not stop the timer.'),\n 'error',\n )\n }\n }, [invalidateBoard, retryCreateMutation, runCreateMutation, runningTimerEntryId, runningTimerQuery, t])\n\n // Never fold `loggedMinutes` inline: a parent's figure already contains its children's,\n // so the shared helper \u2014 which drops any row whose parent is in the same set \u2014 is the\n // only thing standing between this number and risk R10.\n const summary = React.useMemo<BoardSummary>(\n () => ({ taskCount: allTasks.length, loggedMinutes: sumTaskLoggedMinutes(allTasks) }),\n [allTasks],\n )\n\n React.useEffect(() => {\n onSummaryChange?.(summary)\n }, [onSummaryChange, summary])\n\n if (statusesQuery.isLoading) {\n return <LoadingMessage label={t('staff.time_tracking.board.loading', 'Loading the board\u2026')} />\n }\n\n if (statusesQuery.isError) {\n return (\n <ErrorMessage\n label={t('staff.time_tracking.board.loadError', 'Could not load the board.')}\n action={\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void statusesQuery.refetch()}>\n {t('staff.time_tracking.board.reload', 'Try again')}\n </Button>\n }\n />\n )\n }\n\n if (statuses.length === 0) {\n return (\n <EmptyState\n title={t('staff.time_tracking.board.empty.title', 'This project has no columns yet')}\n description={t(\n 'staff.time_tracking.board.empty.description',\n 'A Team Leader configures the board columns for each project.',\n )}\n />\n )\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <InjectionSpot\n spotId={extensionPoints.hosts.taskBoardToolbar.spotId}\n context={{ timeProjectId, projectName: projectName ?? null, statusIds: visibleStatuses.map((status) => status.id) }}\n data={summary}\n />\n\n {failedMove ? (\n <Alert status=\"error\" data-testid=\"kanban-move-retry\">\n <AlertDescription className=\"flex flex-wrap items-center gap-3\">\n <span>\n {t('staff.time_tracking.board.move.rolledBack', 'The task was moved back \u2014 the change was not saved.')}\n </span>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n const retry = failedMove\n setFailedMove(null)\n moveTask(retry.taskId, retry.targetStatusId)\n }}\n >\n <RotateCcw className=\"size-3.5\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.move.retry', 'Retry')}\n </Button>\n </AlertDescription>\n </Alert>\n ) : null}\n\n <DndContext\n sensors={sensors}\n accessibility={accessibility}\n collisionDetection={collisionDetection}\n measuring={measuringConfig}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragCancel={handleDragCancel}\n >\n <div\n className={`flex min-w-0 gap-3.5 overflow-x-auto pb-6 ${\n activeDragTaskId ? 'cursor-grabbing select-none' : ''\n }`}\n >\n {visibleStatuses.map((status, index) => {\n const entry = tasksByStatusId.get(status.id)\n const serverTotal = entry?.total ?? 0\n const loaded = entry?.loaded ?? 0\n return (\n <KanbanColumn\n key={status.id}\n status={status}\n tasks={entry?.tasks ?? []}\n total={serverTotal}\n remaining={Math.max(0, serverTotal - loaded)}\n canQuickAdd={canManageTasks}\n loadingMore={columnQueries[index]?.isFetching ?? false}\n activeDragTaskId={activeDragTaskId}\n pendingTaskIds={pendingTaskIds}\n runningTimerTaskId={runningTimerTaskId}\n assigneeNames={assigneeQuery.data ?? new Map<string, string>()}\n tagsByTaskId={tagsByTaskId}\n subtasksByTaskId={subtasksByTaskId}\n quickAddPending={quickAddPendingStatusId === status.id}\n moveTargets={moveTargets}\n onQuickAdd={handleQuickAdd}\n onLoadMore={handleLoadMore}\n onOpenTask={openTask}\n onStartTimer={handleStartTimer}\n onStopTimer={handleStopTimer}\n onAddTime={handleAddTime}\n onMoveTask={moveTask}\n />\n )\n })}\n\n {canManageColumns ? (\n <div className=\"flex w-72 flex-none flex-col gap-3\">\n {composingStatus ? (\n <Input\n autoFocus\n value={statusDraft}\n onChange={(event) => setStatusDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n void handleCreateStatus()\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n setComposingStatus(false)\n setStatusDraft('')\n }\n }}\n placeholder={t('staff.time_tracking.board.addStatus.placeholder', 'Column name')}\n aria-label={t('staff.time_tracking.board.addStatus.cta', 'Add status')}\n data-testid=\"kanban-add-status-input\"\n />\n ) : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => setComposingStatus(true)}\n data-testid=\"kanban-add-status\"\n className=\"flex h-24 flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-muted-foreground/60 bg-muted/40 text-sm font-semibold leading-normal text-muted-foreground hover:text-foreground\"\n >\n <Plus className=\"size-5\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.addStatus.cta', 'Add status')}\n </Button>\n )}\n </div>\n ) : null}\n </div>\n\n <DragOverlay dropAnimation={null}>\n {activeDragTask ? (\n <div\n data-testid=\"kanban-drag-overlay\"\n className=\"pointer-events-none w-72 rotate-2 cursor-grabbing select-none rounded-lg border border-border bg-card px-4 py-3 opacity-80 shadow-xl\"\n >\n <div className=\"text-sm font-semibold leading-normal text-foreground\">\n {activeDragTask.title}\n </div>\n <div className=\"mt-2 text-xs font-semibold tabular-nums leading-normal text-muted-foreground\">\n {formatBoardMinutes(activeDragTask.loggedMinutes)}\n </div>\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n\n {drawerTaskId ? (\n <TaskDrawer\n taskId={drawerTaskId}\n open\n onOpenChange={(next) => {\n if (!next) closeTaskDrawer()\n }}\n projectName={projectName ?? null}\n focusPanel={drawerPanel}\n onChanged={invalidateBoard}\n />\n ) : null}\n </div>\n )\n}\n\nexport default KanbanBoard\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,360 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { z } from "zod";
5
+ import { useDraggable } from "@dnd-kit/core";
6
+ import { ArrowRightLeft, Check, Play, Plus, Square } from "lucide-react";
7
+ import { Avatar } from "@open-mercato/ui/primitives/avatar";
8
+ import { Badge } from "@open-mercato/ui/primitives/badge";
9
+ import { Button } from "@open-mercato/ui/primitives/button";
10
+ import { Progress } from "@open-mercato/ui/primitives/progress";
11
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
12
+ import { InjectionSpot } from "@open-mercato/ui/backend/injection/InjectionSpot";
13
+ import { extensionPoints } from "@open-mercato/core/modules/staff/extension-points";
14
+ import { registerComponent } from "@open-mercato/shared/modules/widgets/component-registry";
15
+ import { useRegisteredComponent } from "@open-mercato/ui/backend/injection/useRegisteredComponent";
16
+ import { callbackProp, opaqueProp, optionalCallbackProp } from "../time-tracking/componentContracts.js";
17
+ import {
18
+ formatBoardMinutes,
19
+ initialsFromName
20
+ } from "./kanbanBoardData.js";
21
+ function useCoarsePointer() {
22
+ const [coarse, setCoarse] = React.useState(false);
23
+ React.useEffect(() => {
24
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
25
+ const query = window.matchMedia("(hover: none)");
26
+ setCoarse(query.matches);
27
+ const listener = (event) => setCoarse(event.matches);
28
+ if (typeof query.addEventListener === "function") {
29
+ query.addEventListener("change", listener);
30
+ return () => query.removeEventListener("change", listener);
31
+ }
32
+ return void 0;
33
+ }, []);
34
+ return coarse;
35
+ }
36
+ const TASK_ENTITY_ID = "staff:staff_time_task";
37
+ const EMPTY_MOVE_TARGETS = [];
38
+ function KanbanCardImpl({
39
+ task,
40
+ assigneeName,
41
+ tags,
42
+ subtasks,
43
+ timerRunning,
44
+ pending,
45
+ isActiveDrag,
46
+ moveTargets = EMPTY_MOVE_TARGETS,
47
+ onOpen,
48
+ onStartTimer,
49
+ onStopTimer,
50
+ onAddTime,
51
+ onMoveToColumn
52
+ }) {
53
+ const t = useT();
54
+ const coarsePointer = useCoarsePointer();
55
+ const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
56
+ id: task.id,
57
+ data: { type: "task", taskStatusId: task.taskStatusId }
58
+ });
59
+ const dimmed = isActiveDrag || isDragging;
60
+ const stopPointerDown = React.useCallback((event) => {
61
+ event.stopPropagation();
62
+ }, []);
63
+ const handleCardClick = React.useCallback(
64
+ (event) => {
65
+ const target = event.target;
66
+ if (target.closest('[data-card-action="true"]')) return;
67
+ onOpen(task.id);
68
+ },
69
+ [onOpen, task.id]
70
+ );
71
+ const handleKeyDown = React.useCallback(
72
+ (event) => {
73
+ if (event.key !== "Enter") return;
74
+ const target = event.target;
75
+ if (target.closest('[data-card-action="true"]')) return;
76
+ event.preventDefault();
77
+ onOpen(task.id);
78
+ },
79
+ [onOpen, task.id]
80
+ );
81
+ const [moveMenuOpen, setMoveMenuOpen] = React.useState(false);
82
+ const moveTriggerRef = React.useRef(null);
83
+ const moveMenuRef = React.useRef(null);
84
+ const moveItemRefs = React.useRef([]);
85
+ const showMoveMenu = moveTargets.length > 0 && typeof onMoveToColumn === "function";
86
+ React.useEffect(() => {
87
+ if (!moveMenuOpen) return;
88
+ moveItemRefs.current[0]?.focus();
89
+ }, [moveMenuOpen]);
90
+ React.useEffect(() => {
91
+ if (!moveMenuOpen) return;
92
+ const handleOutside = (event) => {
93
+ const target = event.target;
94
+ if (moveMenuRef.current?.contains(target)) return;
95
+ if (moveTriggerRef.current?.contains(target)) return;
96
+ setMoveMenuOpen(false);
97
+ };
98
+ document.addEventListener("mousedown", handleOutside);
99
+ return () => document.removeEventListener("mousedown", handleOutside);
100
+ }, [moveMenuOpen]);
101
+ const closeMoveMenu = React.useCallback(() => {
102
+ setMoveMenuOpen(false);
103
+ moveTriggerRef.current?.focus();
104
+ }, []);
105
+ const handleMoveMenuKeyDown = React.useCallback(
106
+ (event) => {
107
+ if (event.key === "Escape") {
108
+ event.preventDefault();
109
+ closeMoveMenu();
110
+ return;
111
+ }
112
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
113
+ event.preventDefault();
114
+ const items = moveItemRefs.current.filter(
115
+ (item) => item !== null && item.isConnected
116
+ );
117
+ if (items.length === 0) return;
118
+ const current = items.indexOf(document.activeElement);
119
+ const step = event.key === "ArrowDown" ? 1 : -1;
120
+ const next = current < 0 ? 0 : (current + step + items.length) % items.length;
121
+ items[next]?.focus();
122
+ },
123
+ [closeMoveMenu]
124
+ );
125
+ const handleMoveSelect = React.useCallback(
126
+ (targetStatusId) => {
127
+ setMoveMenuOpen(false);
128
+ moveTriggerRef.current?.focus();
129
+ onMoveToColumn?.(task.id, targetStatusId);
130
+ },
131
+ [onMoveToColumn, task.id]
132
+ );
133
+ const quickActionsVisible = coarsePointer ? "opacity-100" : "opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100";
134
+ const cardInjectionContext = React.useMemo(
135
+ () => ({
136
+ entityId: TASK_ENTITY_ID,
137
+ recordId: task.id,
138
+ taskId: task.id,
139
+ timeProjectId: task.timeProjectId ?? null,
140
+ taskStatusId: task.taskStatusId ?? null,
141
+ timerRunning
142
+ }),
143
+ [task.id, task.taskStatusId, task.timeProjectId, timerRunning]
144
+ );
145
+ const subtaskPercent = subtasks && subtasks.total > 0 ? Math.round(subtasks.done / subtasks.total * 100) : 0;
146
+ return /* @__PURE__ */ jsxs(
147
+ "div",
148
+ {
149
+ ref: setNodeRef,
150
+ ...attributes,
151
+ ...listeners,
152
+ "data-task-card": task.id,
153
+ "aria-label": t("staff.time_tracking.board.card.aria", "Task: {title}", { title: task.title }),
154
+ onClick: handleCardClick,
155
+ onKeyDown: handleKeyDown,
156
+ className: `group relative flex w-full flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3 shadow-xs transition-shadow ${dimmed ? "cursor-grabbing opacity-30" : "cursor-grab hover:shadow-sm active:cursor-grabbing"} ${pending ? "opacity-70" : ""}`,
157
+ children: [
158
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold leading-normal text-foreground", children: task.title }),
159
+ tags.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "info", size: "sm", children: tag.label }, tag.id)) }) : null,
160
+ /* @__PURE__ */ jsx(
161
+ InjectionSpot,
162
+ {
163
+ spotId: extensionPoints.hosts.taskBoardCardBadges.spotId,
164
+ context: cardInjectionContext,
165
+ data: task
166
+ }
167
+ ),
168
+ subtasks && subtasks.total > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
169
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs font-medium leading-normal text-muted-foreground", children: [
170
+ /* @__PURE__ */ jsx(Check, { className: "size-3", "aria-hidden": "true" }),
171
+ t("staff.time_tracking.board.card.subtasks", "{done}/{total} subtasks", {
172
+ done: subtasks.done,
173
+ total: subtasks.total
174
+ })
175
+ ] }),
176
+ /* @__PURE__ */ jsx(Progress, { value: subtaskPercent, size: "sm", tone: "success" })
177
+ ] }) : null,
178
+ /* @__PURE__ */ jsx("div", { className: "h-px w-full bg-border", "aria-hidden": "true" }),
179
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
180
+ /* @__PURE__ */ jsx(
181
+ Avatar,
182
+ {
183
+ size: "xs",
184
+ label: initialsFromName(assigneeName),
185
+ ariaLabel: assigneeName ? t("staff.time_tracking.board.card.assignee", "Assigned to {name}", { name: assigneeName }) : t("staff.time_tracking.board.card.unassigned", "Unassigned")
186
+ }
187
+ ),
188
+ timerRunning ? /* @__PURE__ */ jsx(Badge, { variant: "success", size: "sm", dot: true, children: t("staff.time_tracking.board.card.timerRunning", "timer") }) : null,
189
+ /* @__PURE__ */ jsx("span", { className: "grow" }),
190
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold tabular-nums leading-normal text-foreground", children: formatBoardMinutes(task.loggedMinutes) })
191
+ ] }),
192
+ /* @__PURE__ */ jsxs(
193
+ "div",
194
+ {
195
+ "data-card-action": "true",
196
+ "data-testid": `kanban-card-actions-${task.id}`,
197
+ onPointerDown: stopPointerDown,
198
+ className: `flex flex-wrap items-center gap-1.5 ${moveMenuOpen ? "opacity-100" : quickActionsVisible}`,
199
+ children: [
200
+ timerRunning ? /* @__PURE__ */ jsxs(
201
+ Button,
202
+ {
203
+ type: "button",
204
+ variant: "outline",
205
+ size: "2xs",
206
+ "aria-label": t("staff.time_tracking.board.card.stopTimerAria", "Stop the timer for {title}", {
207
+ title: task.title
208
+ }),
209
+ onClick: () => onStopTimer(task.id),
210
+ children: [
211
+ /* @__PURE__ */ jsx(Square, { className: "size-3", "aria-hidden": "true" }),
212
+ t("staff.time_tracking.board.card.stopTimer", "Stop")
213
+ ]
214
+ }
215
+ ) : /* @__PURE__ */ jsxs(
216
+ Button,
217
+ {
218
+ type: "button",
219
+ variant: "outline",
220
+ size: "2xs",
221
+ "aria-label": t("staff.time_tracking.board.card.startTimerAria", "Start a timer for {title}", {
222
+ title: task.title
223
+ }),
224
+ onClick: () => onStartTimer(task.id),
225
+ children: [
226
+ /* @__PURE__ */ jsx(Play, { className: "size-3", "aria-hidden": "true" }),
227
+ t("staff.time_tracking.board.card.startTimer", "Start")
228
+ ]
229
+ }
230
+ ),
231
+ /* @__PURE__ */ jsxs(
232
+ Button,
233
+ {
234
+ type: "button",
235
+ variant: "outline",
236
+ size: "2xs",
237
+ "aria-label": t("staff.time_tracking.board.card.addTimeAria", "Add time to {title}", {
238
+ title: task.title
239
+ }),
240
+ onClick: () => onAddTime(task.id),
241
+ children: [
242
+ /* @__PURE__ */ jsx(Plus, { className: "size-3", "aria-hidden": "true" }),
243
+ t("staff.time_tracking.board.card.addTime", "Add time")
244
+ ]
245
+ }
246
+ ),
247
+ showMoveMenu ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
248
+ /* @__PURE__ */ jsxs(
249
+ Button,
250
+ {
251
+ ref: moveTriggerRef,
252
+ type: "button",
253
+ variant: "outline",
254
+ size: "2xs",
255
+ "aria-haspopup": "menu",
256
+ "aria-expanded": moveMenuOpen,
257
+ "aria-label": t("staff.time_tracking.board.card.moveTo.aria", "Move {title} to another column", {
258
+ title: task.title
259
+ }),
260
+ "data-testid": `kanban-card-move-${task.id}`,
261
+ onClick: () => setMoveMenuOpen((open) => !open),
262
+ onKeyDown: (event) => {
263
+ if (event.key !== "ArrowDown") return;
264
+ event.preventDefault();
265
+ setMoveMenuOpen(true);
266
+ },
267
+ children: [
268
+ /* @__PURE__ */ jsx(ArrowRightLeft, { className: "size-3", "aria-hidden": "true" }),
269
+ t("staff.time_tracking.board.card.moveTo.cta", "Move")
270
+ ]
271
+ }
272
+ ),
273
+ moveMenuOpen ? /* @__PURE__ */ jsx(
274
+ "div",
275
+ {
276
+ ref: moveMenuRef,
277
+ role: "menu",
278
+ "aria-label": t("staff.time_tracking.board.card.moveTo.menu", "Move {title} to", {
279
+ title: task.title
280
+ }),
281
+ "data-testid": `kanban-card-move-menu-${task.id}`,
282
+ onKeyDown: handleMoveMenuKeyDown,
283
+ className: "absolute bottom-full left-0 z-dropdown mb-1 flex min-w-40 flex-col gap-0.5 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
284
+ children: moveTargets.map((target, index) => /* @__PURE__ */ jsx(
285
+ Button,
286
+ {
287
+ ref: (node) => {
288
+ moveItemRefs.current[index] = node;
289
+ },
290
+ type: "button",
291
+ variant: "ghost",
292
+ size: "2xs",
293
+ role: "menuitem",
294
+ className: "justify-start",
295
+ "data-testid": `kanban-card-move-option-${task.id}-${target.id}`,
296
+ onClick: () => handleMoveSelect(target.id),
297
+ children: target.name
298
+ },
299
+ target.id
300
+ ))
301
+ }
302
+ ) : null
303
+ ] }) : null
304
+ ]
305
+ }
306
+ ),
307
+ /* @__PURE__ */ jsx(
308
+ InjectionSpot,
309
+ {
310
+ spotId: extensionPoints.hosts.taskBoardCardFooter.spotId,
311
+ context: cardInjectionContext,
312
+ data: task
313
+ }
314
+ )
315
+ ]
316
+ }
317
+ );
318
+ }
319
+ const DefaultKanbanCard = React.memo(KanbanCardImpl);
320
+ const kanbanTagOptionSchema = z.object({ id: z.string(), label: z.string() });
321
+ const kanbanMoveTargetSchema = z.object({ id: z.string(), name: z.string() });
322
+ const kanbanCardPropsSchema = z.object({
323
+ task: opaqueProp(),
324
+ assigneeName: z.string().nullable(),
325
+ tags: z.array(kanbanTagOptionSchema),
326
+ subtasks: opaqueProp().nullable(),
327
+ timerRunning: z.boolean(),
328
+ pending: z.boolean(),
329
+ isActiveDrag: z.boolean(),
330
+ moveTargets: z.array(kanbanMoveTargetSchema).optional(),
331
+ onOpen: callbackProp(),
332
+ onStartTimer: callbackProp(),
333
+ onStopTimer: callbackProp(),
334
+ onAddTime: callbackProp(),
335
+ onMoveToColumn: optionalCallbackProp()
336
+ });
337
+ registerComponent({
338
+ id: extensionPoints.hosts.kanbanCardComponent.componentId,
339
+ component: DefaultKanbanCard,
340
+ metadata: {
341
+ module: "staff",
342
+ description: "One task card on the time-tracking Kanban board.",
343
+ propsSchema: kanbanCardPropsSchema
344
+ }
345
+ });
346
+ function KanbanCardHost(props) {
347
+ const Resolved = useRegisteredComponent(
348
+ extensionPoints.hosts.kanbanCardComponent.componentId,
349
+ DefaultKanbanCard
350
+ );
351
+ return /* @__PURE__ */ jsx(Resolved, { ...props });
352
+ }
353
+ const KanbanCard = React.memo(KanbanCardHost);
354
+ var KanbanCard_default = KanbanCard;
355
+ export {
356
+ KanbanCard,
357
+ KanbanCard_default as default,
358
+ useCoarsePointer
359
+ };
360
+ //# sourceMappingURL=KanbanCard.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { useDraggable } from '@dnd-kit/core'\nimport { ArrowRightLeft, Check, Play, Plus, Square } from 'lucide-react'\nimport { Avatar } from '@open-mercato/ui/primitives/avatar'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport { registerComponent } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '@open-mercato/ui/backend/injection/useRegisteredComponent'\nimport { callbackProp, opaqueProp, optionalCallbackProp } from '../time-tracking/componentContracts'\nimport {\n formatBoardMinutes,\n initialsFromName,\n type BoardTask,\n type SubtaskProgress,\n} from './kanbanBoardData'\n\n/**\n * Quick actions are hover- and focus-revealed on a pointer device (mockup note 3),\n * which leaves them unreachable on a touch screen where neither state exists. The\n * media query is read at runtime rather than expressed as a Tailwind variant so the\n * card can hand the same `visible` decision to both the class list and the tests.\n */\nexport function useCoarsePointer(): boolean {\n const [coarse, setCoarse] = React.useState(false)\n React.useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return\n const query = window.matchMedia('(hover: none)')\n setCoarse(query.matches)\n const listener = (event: MediaQueryListEvent) => setCoarse(event.matches)\n if (typeof query.addEventListener === 'function') {\n query.addEventListener('change', listener)\n return () => query.removeEventListener('change', listener)\n }\n return undefined\n }, [])\n return coarse\n}\n\nconst TASK_ENTITY_ID = 'staff:staff_time_task'\n\nexport type KanbanTagOption = {\n id: string\n label: string\n}\n\n/** A column this card can be moved into \u2014 every board column except its own. */\nexport type KanbanMoveTarget = {\n id: string\n name: string\n}\n\nexport type KanbanCardProps = {\n task: BoardTask\n assigneeName: string | null\n tags: KanbanTagOption[]\n subtasks: SubtaskProgress | null\n /** A running timer marks the card permanently \u2014 never hover-dependent (note 3). */\n timerRunning: boolean\n pending: boolean\n isActiveDrag: boolean\n /**\n * Columns offered by the keyboard move menu. Empty (the default) hides the\n * control, which is what a single-column board should do.\n */\n moveTargets?: readonly KanbanMoveTarget[]\n onOpen: (taskId: string) => void\n onStartTimer: (taskId: string) => void\n onStopTimer: (taskId: string) => void\n onAddTime: (taskId: string) => void\n /** Same move the drag performs \u2014 optimistic update, lock header, rollback and all. */\n onMoveToColumn?: (taskId: string, targetStatusId: string) => void\n}\n\nconst EMPTY_MOVE_TARGETS: readonly KanbanMoveTarget[] = []\n\nfunction KanbanCardImpl({\n task,\n assigneeName,\n tags,\n subtasks,\n timerRunning,\n pending,\n isActiveDrag,\n moveTargets = EMPTY_MOVE_TARGETS,\n onOpen,\n onStartTimer,\n onStopTimer,\n onAddTime,\n onMoveToColumn,\n}: KanbanCardProps): React.ReactElement {\n const t = useT()\n const coarsePointer = useCoarsePointer()\n const { attributes, listeners, setNodeRef, isDragging } = useDraggable({\n id: task.id,\n data: { type: 'task', taskStatusId: task.taskStatusId },\n })\n const dimmed = isActiveDrag || isDragging\n\n // dnd-kit's draggable listeners take pointer capture on the card, which rewrites the\n // subsequent click's target to the card itself and swallows the inner buttons. Cutting\n // the pointerdown at the action row keeps Start / Stop / Add time clickable.\n const stopPointerDown = React.useCallback((event: React.PointerEvent) => {\n event.stopPropagation()\n }, [])\n\n const handleCardClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement\n if (target.closest('[data-card-action=\"true\"]')) return\n onOpen(task.id)\n },\n [onOpen, task.id],\n )\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key !== 'Enter') return\n const target = event.target as HTMLElement\n if (target.closest('[data-card-action=\"true\"]')) return\n event.preventDefault()\n onOpen(task.id)\n },\n [onOpen, task.id],\n )\n\n // Keyboard operability of the board does NOT go through dnd-kit: its keyboard sensor\n // would have to own Enter/Space on the card, and Enter is what opens the drawer. The\n // move is an explicit menu instead \u2014 same `onMoveToColumn` the drop calls, so a keyboard\n // move is the identical optimistic, version-locked request a drag issues.\n const [moveMenuOpen, setMoveMenuOpen] = React.useState(false)\n const moveTriggerRef = React.useRef<HTMLButtonElement | null>(null)\n const moveMenuRef = React.useRef<HTMLDivElement | null>(null)\n const moveItemRefs = React.useRef<(HTMLButtonElement | null)[]>([])\n const showMoveMenu = moveTargets.length > 0 && typeof onMoveToColumn === 'function'\n\n React.useEffect(() => {\n if (!moveMenuOpen) return\n moveItemRefs.current[0]?.focus()\n }, [moveMenuOpen])\n\n React.useEffect(() => {\n if (!moveMenuOpen) return\n const handleOutside = (event: MouseEvent) => {\n const target = event.target as Node\n if (moveMenuRef.current?.contains(target)) return\n if (moveTriggerRef.current?.contains(target)) return\n setMoveMenuOpen(false)\n }\n document.addEventListener('mousedown', handleOutside)\n return () => document.removeEventListener('mousedown', handleOutside)\n }, [moveMenuOpen])\n\n const closeMoveMenu = React.useCallback(() => {\n setMoveMenuOpen(false)\n moveTriggerRef.current?.focus()\n }, [])\n\n const handleMoveMenuKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault()\n closeMoveMenu()\n return\n }\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return\n event.preventDefault()\n const items = moveItemRefs.current.filter(\n (item): item is HTMLButtonElement => item !== null && item.isConnected,\n )\n if (items.length === 0) return\n const current = items.indexOf(document.activeElement as HTMLButtonElement)\n const step = event.key === 'ArrowDown' ? 1 : -1\n const next = current < 0 ? 0 : (current + step + items.length) % items.length\n items[next]?.focus()\n },\n [closeMoveMenu],\n )\n\n const handleMoveSelect = React.useCallback(\n (targetStatusId: string) => {\n setMoveMenuOpen(false)\n moveTriggerRef.current?.focus()\n onMoveToColumn?.(task.id, targetStatusId)\n },\n [onMoveToColumn, task.id],\n )\n\n const quickActionsVisible = coarsePointer\n ? 'opacity-100'\n : 'opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100'\n\n const cardInjectionContext = React.useMemo(\n () => ({\n entityId: TASK_ENTITY_ID,\n recordId: task.id,\n taskId: task.id,\n timeProjectId: task.timeProjectId ?? null,\n taskStatusId: task.taskStatusId ?? null,\n timerRunning,\n }),\n [task.id, task.taskStatusId, task.timeProjectId, timerRunning],\n )\n\n const subtaskPercent = subtasks && subtasks.total > 0\n ? Math.round((subtasks.done / subtasks.total) * 100)\n : 0\n\n return (\n <div\n ref={setNodeRef}\n {...attributes}\n {...listeners}\n data-task-card={task.id}\n aria-label={t('staff.time_tracking.board.card.aria', 'Task: {title}', { title: task.title })}\n onClick={handleCardClick}\n onKeyDown={handleKeyDown}\n className={`group relative flex w-full flex-col gap-2 rounded-lg border border-border bg-card px-4 py-3 shadow-xs transition-shadow ${\n dimmed ? 'cursor-grabbing opacity-30' : 'cursor-grab hover:shadow-sm active:cursor-grabbing'\n } ${pending ? 'opacity-70' : ''}`}\n >\n <div className=\"text-sm font-semibold leading-normal text-foreground\">{task.title}</div>\n\n {tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-1\">\n {tags.map((tag) => (\n <Badge key={tag.id} variant=\"info\" size=\"sm\">\n {tag.label}\n </Badge>\n ))}\n </div>\n ) : null}\n\n <InjectionSpot\n spotId={extensionPoints.hosts.taskBoardCardBadges.spotId}\n context={cardInjectionContext}\n data={task}\n />\n\n {subtasks && subtasks.total > 0 ? (\n <div className=\"flex flex-col gap-1\">\n <span className=\"flex items-center gap-1 text-xs font-medium leading-normal text-muted-foreground\">\n <Check className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.subtasks', '{done}/{total} subtasks', {\n done: subtasks.done,\n total: subtasks.total,\n })}\n </span>\n <Progress value={subtaskPercent} size=\"sm\" tone=\"success\" />\n </div>\n ) : null}\n\n <div className=\"h-px w-full bg-border\" aria-hidden=\"true\" />\n\n <div className=\"flex items-center gap-2\">\n <Avatar\n size=\"xs\"\n label={initialsFromName(assigneeName)}\n ariaLabel={\n assigneeName\n ? t('staff.time_tracking.board.card.assignee', 'Assigned to {name}', { name: assigneeName })\n : t('staff.time_tracking.board.card.unassigned', 'Unassigned')\n }\n />\n {timerRunning ? (\n <Badge variant=\"success\" size=\"sm\" dot>\n {t('staff.time_tracking.board.card.timerRunning', 'timer')}\n </Badge>\n ) : null}\n <span className=\"grow\" />\n <span className=\"text-xs font-semibold tabular-nums leading-normal text-foreground\">\n {formatBoardMinutes(task.loggedMinutes)}\n </span>\n </div>\n\n <div\n data-card-action=\"true\"\n data-testid={`kanban-card-actions-${task.id}`}\n onPointerDown={stopPointerDown}\n className={`flex flex-wrap items-center gap-1.5 ${moveMenuOpen ? 'opacity-100' : quickActionsVisible}`}\n >\n {timerRunning ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.board.card.stopTimerAria', 'Stop the timer for {title}', {\n title: task.title,\n })}\n onClick={() => onStopTimer(task.id)}\n >\n <Square className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.stopTimer', 'Stop')}\n </Button>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.board.card.startTimerAria', 'Start a timer for {title}', {\n title: task.title,\n })}\n onClick={() => onStartTimer(task.id)}\n >\n <Play className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.startTimer', 'Start')}\n </Button>\n )}\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.board.card.addTimeAria', 'Add time to {title}', {\n title: task.title,\n })}\n onClick={() => onAddTime(task.id)}\n >\n <Plus className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.addTime', 'Add time')}\n </Button>\n {showMoveMenu ? (\n <div className=\"relative\">\n <Button\n ref={moveTriggerRef}\n type=\"button\"\n variant=\"outline\"\n size=\"2xs\"\n aria-haspopup=\"menu\"\n aria-expanded={moveMenuOpen}\n aria-label={t('staff.time_tracking.board.card.moveTo.aria', 'Move {title} to another column', {\n title: task.title,\n })}\n data-testid={`kanban-card-move-${task.id}`}\n onClick={() => setMoveMenuOpen((open) => !open)}\n onKeyDown={(event) => {\n if (event.key !== 'ArrowDown') return\n event.preventDefault()\n setMoveMenuOpen(true)\n }}\n >\n <ArrowRightLeft className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.card.moveTo.cta', 'Move')}\n </Button>\n {moveMenuOpen ? (\n <div\n ref={moveMenuRef}\n role=\"menu\"\n aria-label={t('staff.time_tracking.board.card.moveTo.menu', 'Move {title} to', {\n title: task.title,\n })}\n data-testid={`kanban-card-move-menu-${task.id}`}\n onKeyDown={handleMoveMenuKeyDown}\n className=\"absolute bottom-full left-0 z-dropdown mb-1 flex min-w-40 flex-col gap-0.5 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n {moveTargets.map((target, index) => (\n <Button\n key={target.id}\n ref={(node: HTMLButtonElement | null) => {\n moveItemRefs.current[index] = node\n }}\n type=\"button\"\n variant=\"ghost\"\n size=\"2xs\"\n role=\"menuitem\"\n className=\"justify-start\"\n data-testid={`kanban-card-move-option-${task.id}-${target.id}`}\n onClick={() => handleMoveSelect(target.id)}\n >\n {target.name}\n </Button>\n ))}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n\n <InjectionSpot\n spotId={extensionPoints.hosts.taskBoardCardFooter.spotId}\n context={cardInjectionContext}\n data={task}\n />\n </div>\n )\n}\n\nconst DefaultKanbanCard = React.memo(KanbanCardImpl)\n\nconst kanbanTagOptionSchema = z.object({ id: z.string(), label: z.string() })\n\nconst kanbanMoveTargetSchema = z.object({ id: z.string(), name: z.string() })\n\nconst kanbanCardPropsSchema: z.ZodType<KanbanCardProps> = z.object({\n task: opaqueProp<BoardTask>(),\n assigneeName: z.string().nullable(),\n tags: z.array(kanbanTagOptionSchema),\n subtasks: opaqueProp<SubtaskProgress>().nullable(),\n timerRunning: z.boolean(),\n pending: z.boolean(),\n isActiveDrag: z.boolean(),\n moveTargets: z.array(kanbanMoveTargetSchema).optional(),\n onOpen: callbackProp<(taskId: string) => void>(),\n onStartTimer: callbackProp<(taskId: string) => void>(),\n onStopTimer: callbackProp<(taskId: string) => void>(),\n onAddTime: callbackProp<(taskId: string) => void>(),\n onMoveToColumn: optionalCallbackProp<(taskId: string, targetStatusId: string) => void>(),\n})\n\nregisterComponent<KanbanCardProps>({\n id: extensionPoints.hosts.kanbanCardComponent.componentId,\n component: DefaultKanbanCard,\n metadata: {\n module: 'staff',\n description: 'One task card on the time-tracking Kanban board.',\n propsSchema: kanbanCardPropsSchema,\n },\n})\n\nfunction KanbanCardHost(props: KanbanCardProps): React.ReactElement {\n const Resolved = useRegisteredComponent<KanbanCardProps>(\n extensionPoints.hosts.kanbanCardComponent.componentId,\n DefaultKanbanCard,\n )\n return <Resolved {...props} />\n}\n\nexport const KanbanCard = React.memo(KanbanCardHost)\n\nexport default KanbanCard\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }