@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/backend/staff/time-tracking/projects/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport { FilterBar } from '@open-mercato/ui/backend/FilterBar'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterOverlay'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport { StatusBadge, type StatusBadgeVariant } from '@open-mercato/ui/primitives/status-badge'\nimport { readApiResultOrThrow, 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 { createCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { groupBulkDeleteFailures, runBulkDelete } from '@open-mercato/ui/backend/utils/bulkDelete'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { useBackendChrome } from '@open-mercato/ui/backend/BackendChromeProvider'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { formatCurrency, formatDate } from '@open-mercato/ui/utils/format'\nimport { hasAllFeatures } from '@open-mercato/shared/security/features'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT, type TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { ProjectColorDot } from '../../../../lib/timesheets-ui/ProjectColorDot'\nimport { resolveProjectColorHex } from '../../../../lib/timesheets-ui/colors'\nimport { formatDuration } from '../../../../lib/time-tracking/duration'\nimport {\n ProjectsKpiStrip,\n type PmKpis,\n type CollabKpis,\n} from '../../../../lib/timesheets-projects-ui/ProjectsKpiStrip'\nimport { SavedViewTabs } from '../../../../lib/timesheets-projects-ui/SavedViewTabs'\nimport { HoursSparkline } from '../../../../lib/timesheets-projects-ui/HoursSparkline'\nimport {\n ProjectMembersAvatarStack,\n type AvatarMember,\n} from '../../../../lib/timesheets-projects-ui/ProjectMembersAvatarStack'\nimport { ViewModeToggle } from '../../../../lib/timesheets-projects-ui/ViewModeToggle'\nimport {\n useProjectsViewMode,\n type ProjectsViewMode,\n} from '../../../../lib/timesheets-projects-ui/useProjectsViewMode'\nimport {\n ProjectCard,\n type ProjectCardData,\n type ProjectCardLabels,\n} from '../../../../lib/timesheets-projects-ui/ProjectCard'\nimport { ProjectBudgetCell } from '../../../../lib/timesheets-projects-ui/ProjectBudgetCell'\nimport { ProjectsBulkActionsBar } from '../../../../lib/timesheets-projects-ui/ProjectsBulkActionsBar'\nimport {\n AssignMembersDialog,\n type AssignMembersSubmitInput,\n} from '../../../../lib/timesheets-projects-ui/AssignMembersDialog'\nimport { computeBudgetBurn, type ProjectBudgetKind } from '../../../../lib/timesheets-projects/budgetBurn'\nimport { resolveReportSelection } from '../../../../lib/timesheets-projects/reportSelection'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('staff')\n\nconst PAGE_SIZE = 50\nconst INCLUDE_FIELDS = 'hoursWeek,hoursTrend,members,myRole'\nconst MANAGE_FEATURE = 'staff.timesheets.projects.manage'\nconst RATES_FEATURE = 'staff.timesheets.rates.view'\nconst REPORTS_FEATURES = ['staff.timesheets.reports.view', 'staff.timesheets.reports.manage']\nconst REPORTS_HREF = '/backend/staff/time-tracking/reports'\n\ntype ProjectBudgetPayload = {\n kind?: unknown\n value?: unknown\n warnAtPercent?: unknown\n}\n\ntype StaffEnrichment = {\n hoursWeek?: number\n hoursTrend?: number[]\n myRole?: string | null\n members?: AvatarMember[]\n memberCount?: number\n customerName?: string | null\n totalMinutes?: number\n billableMinutes?: number\n budget?: ProjectBudgetPayload\n hourlyRate?: number | null\n cost?: number | null\n}\n\ntype ProjectRow = {\n id: string\n name: string\n code: string | null\n customerId: string | null\n customerName: string | null\n status: string\n projectType: string | null\n color: string | null\n startDate: string | null\n updatedAt: string | null\n currencyCode: string | null\n hoursWeek: number\n hoursTrend: number[]\n myRole: string | null\n members: AvatarMember[]\n memberCount: number\n totalMinutes: number\n hourlyRate: number | null\n cost: number | null\n budgetKind: ProjectBudgetKind\n budgetValue: number | null\n budgetWarnAtPercent: number | null\n}\n\ntype ProjectsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalIsCapped?: boolean\n totalPages?: number\n}\n\ntype KpisResponse = PmKpis | CollabKpis\n\nconst STATUS_VARIANTS: Record<string, StatusBadgeVariant> = {\n active: 'success',\n on_hold: 'warning',\n completed: 'neutral',\n}\n\nfunction readString(item: Record<string, unknown>, camel: string, snake: string): string | null {\n const camelValue = item[camel]\n if (typeof camelValue === 'string') return camelValue\n const snakeValue = item[snake]\n return typeof snakeValue === 'string' ? snakeValue : null\n}\n\nfunction readNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value)\n if (Number.isFinite(parsed)) return parsed\n }\n return null\n}\n\nfunction readBudgetKind(value: unknown): ProjectBudgetKind {\n return value === 'hours' || value === 'amount' ? value : 'none'\n}\n\nfunction formatRelativeTime(iso: string | null, fallback: string, t: TranslateFn): string {\n if (!iso) return fallback\n const parsed = new Date(iso)\n if (Number.isNaN(parsed.getTime())) return fallback\n const diffMs = Date.now() - parsed.getTime()\n const minutes = Math.round(diffMs / 60000)\n if (minutes < 1) return t('staff.timesheets.projects.portfolio.relativeTime.justNow', 'just now')\n if (minutes < 60) return t('staff.timesheets.projects.portfolio.relativeTime.minutesAgo', '{minutes}m ago', { minutes })\n const hours = Math.round(minutes / 60)\n if (hours < 24) return t('staff.timesheets.projects.portfolio.relativeTime.hoursAgo', '{hours}h ago', { hours })\n const days = Math.round(hours / 24)\n if (days < 14) return t('staff.timesheets.projects.portfolio.relativeTime.daysAgo', '{days}d ago', { days })\n return formatDateTime(iso) ?? fallback\n}\n\nfunction mapApiProject(item: Record<string, unknown>): ProjectRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const name = typeof item.name === 'string' ? item.name : id\n const code = typeof item.code === 'string' && item.code.trim().length ? item.code.trim() : null\n const customerId = readString(item, 'customerId', 'customer_id')\n const status = typeof item.status === 'string' ? item.status : 'active'\n const projectType = readString(item, 'projectType', 'project_type')\n const color = typeof item.color === 'string' ? item.color : null\n const startDate = readString(item, 'startDate', 'start_date')\n const updatedAt = readString(item, 'updatedAt', 'updated_at')\n const currencyCode = readString(item, 'currencyCode', 'currency_code')\n const enrichment = (item as { _staff?: StaffEnrichment })._staff ?? ({} as StaffEnrichment)\n const hoursWeek = typeof enrichment.hoursWeek === 'number' ? enrichment.hoursWeek : 0\n const hoursTrend = Array.isArray(enrichment.hoursTrend)\n ? enrichment.hoursTrend.filter((v): v is number => typeof v === 'number')\n : []\n const members = Array.isArray(enrichment.members)\n ? enrichment.members\n .filter((m): m is AvatarMember => !!m && typeof m === 'object' && typeof (m as AvatarMember).id === 'string')\n .map((m) => ({\n id: m.id,\n name: m.name ?? '',\n initials: m.initials ?? '',\n avatarUrl: m.avatarUrl ?? null,\n }))\n : []\n const memberCount = typeof enrichment.memberCount === 'number' ? enrichment.memberCount : members.length\n const myRole = typeof enrichment.myRole === 'string' ? enrichment.myRole : null\n const customerName =\n typeof enrichment.customerName === 'string' && enrichment.customerName.length > 0\n ? enrichment.customerName\n : readString(item, 'customerName', 'customer_name')\n\n return withDataTableNamespaces(\n {\n id,\n name,\n code,\n customerId,\n customerName,\n status,\n projectType,\n color,\n startDate,\n updatedAt,\n currencyCode,\n hoursWeek,\n hoursTrend,\n myRole,\n members,\n memberCount,\n totalMinutes: typeof enrichment.totalMinutes === 'number' ? enrichment.totalMinutes : 0,\n hourlyRate: readNumber(enrichment.hourlyRate),\n cost: readNumber(enrichment.cost),\n budgetKind: readBudgetKind(enrichment.budget?.kind),\n budgetValue: readNumber(enrichment.budget?.value),\n budgetWarnAtPercent: readNumber(enrichment.budget?.warnAtPercent),\n },\n item,\n )\n}\n\nexport default function TimesheetProjectsPage() {\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const { payload: chromePayload } = useBackendChrome()\n\n const [rows, setRows] = React.useState<ProjectRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'updatedAt', desc: true }])\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [isRefreshing, setIsRefreshing] = React.useState(false)\n const hasLoadedOnceRef = React.useRef(false)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [kpis, setKpis] = React.useState<KpisResponse | null>(null)\n const [isLoadingKpis, setIsLoadingKpis] = React.useState(true)\n const [selectedIds, setSelectedIds] = React.useState<string[]>([])\n const [assignDialogOpen, setAssignDialogOpen] = React.useState(false)\n const [isAssigning, setIsAssigning] = React.useState(false)\n\n const activeTab = searchParams.get('tab') ?? 'all'\n const urlViewMode = searchParams.get('view')\n const [viewMode, setViewMode] = useProjectsViewMode({\n userKey: null,\n urlOverride: urlViewMode,\n })\n\n const grantedFeatures = React.useMemo(\n () => chromePayload?.grantedFeatures ?? [],\n [chromePayload?.grantedFeatures],\n )\n const canManageProjects = hasAllFeatures(grantedFeatures, [MANAGE_FEATURE])\n const canViewRates = hasAllFeatures(grantedFeatures, [RATES_FEATURE])\n const canCreateReports = hasAllFeatures(grantedFeatures, REPORTS_FEATURES)\n const canSelectRows = canManageProjects || canCreateReports\n\n const labels = React.useMemo(\n () => ({\n title: t('staff.timesheets.projects.page.title', 'Projects'),\n table: {\n name: t('staff.timesheets.projects.table.name', 'Project'),\n status: t('staff.timesheets.projects.table.status', 'Status'),\n type: t('staff.timesheets.projects.table.type', 'Type'),\n updatedAt: t('staff.timesheets.projects.table.updatedAt', 'Updated'),\n empty: t('staff.timesheets.projects.table.empty', 'No projects yet.'),\n search: t('staff.timesheets.projects.table.search', 'Search projects...'),\n team: t('staff.timesheets.projects.portfolio.team', 'Team'),\n myRole: t('staff.timesheets.projects.portfolio.myRole', 'My role'),\n hoursWeek: t('staff.timesheets.projects.portfolio.hoursWeek', 'Hours / week'),\n myHoursWeek: t('staff.timesheets.projects.portfolio.myHoursWeek', 'My hours / week'),\n customer: t('staff.time_tracking.projects.columns.customer', 'Customer'),\n rate: t('staff.time_tracking.projects.columns.rate', 'Rate'),\n hours: t('staff.time_tracking.projects.columns.hours', 'Hours'),\n cost: t('staff.time_tracking.projects.columns.cost', 'Cost'),\n budget: t('staff.time_tracking.projects.columns.budget', 'Budget'),\n selectRow: t('staff.time_tracking.projects.selection.selectRow', 'Select project'),\n selectAll: t('staff.time_tracking.projects.selection.selectAll', 'Select all projects on this page'),\n },\n actions: {\n add: t('staff.timesheets.projects.actions.add', 'Add Project'),\n addFirst: t('staff.timesheets.projects.actions.addFirst', '+ Add first project'),\n viewDetails: t('staff.timesheets.projects.actions.viewDetails', 'View Details'),\n delete: t('staff.timesheets.projects.actions.delete', 'Delete'),\n deleteConfirm: t('staff.timesheets.projects.actions.deleteConfirm', 'Delete project \"{{name}}\"?'),\n refresh: t('staff.timesheets.projects.actions.refresh', 'Refresh'),\n assignCustomer: t('staff.time_tracking.projects.actions.assignCustomer', 'Assign a customer'),\n },\n messages: {\n deleted: t('staff.timesheets.projects.messages.deleted', 'Project deleted.'),\n },\n errors: {\n load: t('staff.timesheets.projects.errors.load', 'Failed to load projects.'),\n delete: t('staff.timesheets.projects.errors.delete', 'Failed to delete project.'),\n },\n statuses: {\n all: t('staff.timesheets.projects.statuses.all', 'All'),\n active: t('staff.timesheets.projects.statuses.active', 'Active'),\n on_hold: t('staff.timesheets.projects.statuses.onHold', 'On Hold'),\n completed: t('staff.timesheets.projects.statuses.completed', 'Completed'),\n },\n tabs: {\n all: t('staff.timesheets.projects.portfolio.tabs.all', 'All'),\n active: t('staff.timesheets.projects.portfolio.tabs.active', 'Active'),\n onHold: t('staff.timesheets.projects.portfolio.tabs.onHold', 'On Hold'),\n completed: t('staff.timesheets.projects.portfolio.tabs.completed', 'Completed'),\n mine: t('staff.timesheets.projects.portfolio.tabs.mine', 'Mine'),\n },\n viewMode: {\n table: t('staff.timesheets.projects.portfolio.viewMode.table', 'Table'),\n cards: t('staff.timesheets.projects.portfolio.viewMode.cards', 'Cards'),\n },\n kpi: {\n totalProjects: t('staff.timesheets.projects.portfolio.kpi.totalProjects', 'Total Projects'),\n hoursWeek: t('staff.timesheets.projects.portfolio.kpi.hoursWeek', 'Hours this week'),\n hoursWeekSub: t('staff.timesheets.projects.portfolio.kpi.hoursWeekSub', 'vs previous week'),\n assignedToMe: t('staff.timesheets.projects.portfolio.kpi.assignedToMe', 'Assigned to me'),\n hoursMonth: t('staff.timesheets.projects.portfolio.kpi.hoursMonth', 'Hours this month'),\n hoursMonthSub: t('staff.timesheets.projects.portfolio.kpi.hoursMonthSub', 'vs previous month'),\n teamActive: t('staff.timesheets.projects.portfolio.kpi.teamActive', 'Active team'),\n teamActiveSub: t('staff.timesheets.projects.portfolio.kpi.teamActiveSub', 'Members with entries this month'),\n myProjects: t('staff.timesheets.projects.portfolio.kpi.myProjects', 'My projects'),\n myHoursWeek: t('staff.timesheets.projects.portfolio.kpi.myHoursWeek', 'My hours this week'),\n myHoursMonth: t('staff.timesheets.projects.portfolio.kpi.myHoursMonth', 'My hours this month'),\n deltaFlat: t('staff.timesheets.projects.portfolio.kpi.deltaFlat', 'no change'),\n noPrevious: t('staff.timesheets.projects.portfolio.kpi.noPrevious', 'no previous data'),\n },\n card: {\n hoursPanelPm: t('staff.timesheets.projects.portfolio.card.hoursPanelPm', 'Team hours \u00B7 last 7w'),\n hoursPanelCollab: t('staff.timesheets.projects.portfolio.card.hoursPanelCollab', 'My hours \u00B7 last 7w'),\n sparklineAria: t('staff.timesheets.projects.portfolio.sparkline.ariaLabel', 'Hours per week, last 7 weeks'),\n role: t('staff.timesheets.projects.portfolio.card.role', 'Role'),\n },\n emptyState: {\n noProjects: t('staff.timesheets.projects.portfolio.emptyState.noProjects', 'No projects yet.'),\n noAssignments: t(\n 'staff.timesheets.projects.portfolio.emptyState.noAssignments',\n \"You aren't assigned to any projects yet. Ask a PM to add you.\",\n ),\n noMatches: t('staff.timesheets.projects.portfolio.emptyState.noMatches', 'No projects match these filters.'),\n },\n budget: {\n none: t('staff.time_tracking.projects.budget.none', 'no budget'),\n aria: t('staff.time_tracking.projects.budget.ariaLabel', 'Budget usage'),\n },\n bulk: {\n report: t('staff.time_tracking.projects.bulk.report', 'Report from selected'),\n assignMembers: t('staff.time_tracking.projects.bulk.assignMembers', 'Assign members'),\n clear: t('staff.time_tracking.projects.bulk.clear', 'Clear'),\n },\n assign: {\n title: t('staff.time_tracking.projects.assignMembers.title', 'Assign members'),\n searchPlaceholder: t('staff.timesheets.projects.employees.searchEmployee', 'Search team members...'),\n empty: t('staff.timesheets.projects.employees.noResults', 'No team members found'),\n loadError: t(\n 'staff.time_tracking.projects.assignMembers.loadError',\n 'Could not load team members. Check your connection and try again.',\n ),\n loading: t('staff.timesheets.projects.employees.loading', 'Loading employees...'),\n role: t('staff.timesheets.projects.employees.roleOnProject', 'Role on Project'),\n rolePlaceholder: t('staff.timesheets.projects.employees.rolePlaceholder', 'e.g. Developer, Designer...'),\n startDate: t('staff.timesheets.projects.employees.assignmentStartDate', 'Assignment Start Date'),\n cancel: t('staff.timesheets.projects.form.actions.cancel', 'Cancel'),\n confirm: t('staff.time_tracking.projects.assignMembers.confirm', 'Assign'),\n error: t('staff.time_tracking.projects.assignMembers.error', 'Failed to assign members.'),\n progressName: t('staff.time_tracking.projects.assignMembers.progressName', 'Assign members to projects'),\n },\n }),\n [t],\n )\n\n const kpiLabels = React.useMemo(\n () => ({\n totalProjects: labels.kpi.totalProjects,\n totalProjectsSub: ({ active, onHold }: { active: number; onHold: number }) =>\n `${active} ${labels.statuses.active.toLowerCase()} \u00B7 ${onHold} ${labels.statuses.on_hold.toLowerCase()}`,\n hoursWeek: labels.kpi.hoursWeek,\n hoursWeekSub: labels.kpi.hoursWeekSub,\n assignedToMe: labels.kpi.assignedToMe,\n assignedToMeSub: (active: number) => `${active} ${labels.statuses.active.toLowerCase()}`,\n hoursMonth: labels.kpi.hoursMonth,\n hoursMonthSub: labels.kpi.hoursMonthSub,\n teamActive: labels.kpi.teamActive,\n teamActiveSub: labels.kpi.teamActiveSub,\n myProjects: labels.kpi.myProjects,\n myProjectsSub: (active: number) => `${active} ${labels.statuses.active.toLowerCase()}`,\n myHoursWeek: labels.kpi.myHoursWeek,\n myHoursMonth: labels.kpi.myHoursMonth,\n deltaUp: (pct: number) => `up ${pct}%`,\n deltaDown: (pct: number) => `down ${pct}%`,\n deltaFlat: labels.kpi.deltaFlat,\n noPrevious: labels.kpi.noPrevious,\n }),\n [labels],\n )\n\n const isPmRole = kpis?.role === 'pm'\n\n const filters = React.useMemo<FilterDef[]>(\n () => [\n {\n id: 'status',\n label: labels.table.status,\n type: 'select',\n options: [\n { value: 'active', label: labels.statuses.active },\n { value: 'on_hold', label: labels.statuses.on_hold },\n { value: 'completed', label: labels.statuses.completed },\n ],\n },\n ],\n [labels.table.status, labels.statuses],\n )\n\n const tabs = React.useMemo(() => {\n const base = [\n { id: 'all', label: labels.tabs.all },\n { id: 'active', label: labels.tabs.active },\n ]\n if (isPmRole) {\n base.push({ id: 'on_hold', label: labels.tabs.onHold })\n }\n base.push({ id: 'completed', label: labels.tabs.completed })\n if (isPmRole) {\n base.push({ id: 'mine', label: labels.tabs.mine })\n }\n return base\n }, [labels.tabs, isPmRole])\n\n const statusFromTab = (tabId: string): string | null => {\n if (tabId === 'active' || tabId === 'on_hold' || tabId === 'completed') return tabId\n return null\n }\n const mineFromTab = (tabId: string): boolean => tabId === 'mine' || !isPmRole\n\n const loadKpis = React.useCallback(async () => {\n setIsLoadingKpis(true)\n try {\n const payload = await readApiResultOrThrow<KpisResponse>(\n '/api/staff/timesheets/projects/kpis',\n undefined,\n {\n errorMessage: labels.errors.load,\n fallback: null as unknown as KpisResponse,\n },\n )\n setKpis(payload)\n } catch {\n setKpis(null)\n } finally {\n setIsLoadingKpis(false)\n }\n }, [labels.errors.load])\n\n const loadProjects = React.useCallback(async () => {\n if (hasLoadedOnceRef.current) {\n setIsRefreshing(true)\n } else {\n setIsLoading(true)\n }\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n include: INCLUDE_FIELDS,\n })\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (search.trim()) params.set('q', search.trim())\n const tabStatus = statusFromTab(activeTab)\n if (tabStatus) params.set('status', tabStatus)\n else if (typeof filterValues.status === 'string' && filterValues.status.length > 0) {\n params.set('status', filterValues.status)\n }\n if (mineFromTab(activeTab)) params.set('mine', '1')\n\n const payload = await readApiResultOrThrow<ProjectsResponse>(\n `/api/staff/timesheets/time-projects?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(items.map(mapApiProject))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalIsCapped(payload.totalIsCapped === true)\n setTotalPages(\n typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(items.length / PAGE_SIZE)),\n )\n } catch (error) {\n logger.error('staff.timesheets.projects.list', { err: error })\n flash(labels.errors.load, 'error')\n } finally {\n setIsLoading(false)\n setIsRefreshing(false)\n hasLoadedOnceRef.current = true\n }\n }, [labels.errors.load, page, search, sorting, filterValues.status, activeTab, isPmRole])\n\n React.useEffect(() => {\n void loadKpis()\n }, [loadKpis, scopeVersion, reloadToken])\n\n React.useEffect(() => {\n void loadProjects()\n }, [loadProjects, scopeVersion, reloadToken])\n\n React.useEffect(() => {\n setSelectedIds([])\n }, [page, activeTab, search, filterValues.status, scopeVersion])\n\n const selectedRows = React.useMemo(\n () => rows.filter((row) => selectedIds.includes(row.id)),\n [rows, selectedIds],\n )\n\n const reportSelection = React.useMemo(\n () =>\n resolveReportSelection(\n selectedRows.map((row) => ({\n id: row.id,\n name: row.name,\n customerId: row.customerId,\n customerName: row.customerName,\n currencyCode: row.currencyCode,\n })),\n ),\n [selectedRows],\n )\n\n const reportBlockedReason = React.useMemo(() => {\n if (reportSelection.ok) return null\n const offenders = reportSelection.offenders.join(', ')\n if (reportSelection.reason === 'multiple_customers') {\n return t(\n 'staff.time_tracking.projects.bulk.reportBlocked.multipleCustomers',\n 'A report always covers one customer. Selected: {customers}.',\n { customers: offenders },\n )\n }\n if (reportSelection.reason === 'multiple_currencies') {\n return t(\n 'staff.time_tracking.projects.bulk.reportBlocked.multipleCurrencies',\n 'A report always covers one currency. Selected: {currencies}.',\n { currencies: offenders },\n )\n }\n if (reportSelection.reason === 'missing_customer') {\n return t(\n 'staff.time_tracking.projects.bulk.reportBlocked.missingCustomer',\n 'These projects have no customer yet: {projects}.',\n { projects: offenders },\n )\n }\n return null\n }, [reportSelection, t])\n\n const handleTabSelect = React.useCallback(\n (id: string) => {\n const params = new URLSearchParams(searchParams.toString())\n if (id === 'all') params.delete('tab')\n else params.set('tab', id)\n router.replace(`?${params.toString()}`)\n setPage(1)\n },\n [router, searchParams],\n )\n\n const handleViewModeChange = React.useCallback(\n (next: ProjectsViewMode) => {\n setViewMode(next)\n const params = new URLSearchParams(searchParams.toString())\n if (next === 'table') params.delete('view')\n else params.set('view', next)\n router.replace(`?${params.toString()}`)\n },\n [router, searchParams, setViewMode],\n )\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const projectsMutationContextId = 'staff-time-projects-list:assign-members'\n const { runMutation: runProjectsMutation, retryLastMutation: retryProjectsMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId?: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: projectsMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const handleDelete = React.useCallback(\n async (entry: ProjectRow) => {\n const message = labels.actions.deleteConfirm.replace('{{name}}', entry.name)\n const confirmed = await confirm({\n title: labels.actions.delete,\n text: message,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n await runProjectsMutation({\n operation: () =>\n withScopedApiRequestHeaders(\n buildOptimisticLockHeader(entry.updatedAt),\n () => deleteCrud('staff/timesheets/time-projects', entry.id, { errorMessage: labels.errors.delete }),\n ),\n context: {\n formId: projectsMutationContextId,\n resourceKind: 'staff.time_project',\n resourceId: entry.id,\n retryLastMutation: retryProjectsMutation,\n },\n mutationPayload: { id: entry.id },\n })\n flash(labels.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n if (surfaceRecordConflict(error, t)) { handleRefresh(); return }\n logger.error('staff.timesheets.projects.delete', { err: error })\n flash(labels.errors.delete, 'error')\n }\n },\n [confirm, handleRefresh, projectsMutationContextId, retryProjectsMutation, runProjectsMutation, t, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted],\n )\n\n const handleAssignMembers = React.useCallback(\n async (input: AssignMembersSubmitInput) => {\n const targets = selectedRows\n if (targets.length === 0 || input.staffMemberIds.length === 0) return\n setIsAssigning(true)\n try {\n const { succeeded, failures } = await runProjectsMutation({\n operation: () =>\n runBulkDelete(\n targets,\n async (row) => {\n for (const staffMemberId of input.staffMemberIds) {\n await createCrud(\n `staff/timesheets/time-projects/${row.id}/employees`,\n {\n timeProjectId: row.id,\n staffMemberId,\n role: input.role,\n assignedStartDate: input.assignedStartDate,\n },\n { errorMessage: labels.assign.error },\n )\n }\n },\n {\n fallbackErrorMessage: labels.assign.error,\n logTag: 'staff.timesheets.projects.assignMembers',\n progress: {\n jobType: 'staff.timesheets.projects.bulk_assign_members',\n name: labels.assign.progressName,\n },\n },\n ),\n context: {\n formId: projectsMutationContextId,\n resourceKind: 'staff.time_project_member',\n retryLastMutation: retryProjectsMutation,\n },\n mutationPayload: {\n projectIds: targets.map((row) => row.id),\n staffMemberIds: input.staffMemberIds,\n },\n })\n if (succeeded.length > 0) {\n flash(\n t('staff.time_tracking.projects.assignMembers.success', 'Members assigned to {count} projects.', {\n count: succeeded.length,\n }),\n 'success',\n )\n }\n for (const group of groupBulkDeleteFailures(failures)) {\n flash(group.sampleMessage, 'error')\n }\n setAssignDialogOpen(false)\n setSelectedIds([])\n handleRefresh()\n } catch (error) {\n logger.error('staff.timesheets.projects.assignMembers', { err: error })\n flash(labels.assign.error, 'error')\n } finally {\n setIsAssigning(false)\n }\n },\n [\n projectsMutationContextId,\n handleRefresh,\n labels.assign.error,\n labels.assign.progressName,\n retryProjectsMutation,\n runProjectsMutation,\n selectedRows,\n t,\n ],\n )\n\n const handleReportFromSelected = React.useCallback(() => {\n if (!reportSelection.ok) return\n const params = new URLSearchParams({\n customerId: reportSelection.customerId,\n projectIds: reportSelection.projectIds.join(','),\n })\n router.push(`${REPORTS_HREF}?${params.toString()}`)\n }, [reportSelection, router])\n\n const toggleRowSelection = React.useCallback((id: string, checked: boolean) => {\n setSelectedIds((prev) => (checked ? Array.from(new Set([...prev, id])) : prev.filter((value) => value !== id)))\n }, [])\n\n const toggleAllSelection = React.useCallback(\n (checked: boolean) => {\n setSelectedIds(checked ? rows.map((row) => row.id) : [])\n },\n [rows],\n )\n\n const allSelected = rows.length > 0 && selectedIds.length === rows.length\n const someSelected = selectedIds.length > 0 && !allSelected\n\n const columns = React.useMemo<ColumnDef<ProjectRow>[]>(() => {\n const rightHeader = (label: string) => () => <span className=\"block text-right\">{label}</span>\n const defs: ColumnDef<ProjectRow>[] = []\n\n if (canSelectRows) {\n defs.push({\n id: 'select',\n accessorKey: 'id',\n header: () => (\n <Checkbox\n checked={allSelected ? true : someSelected ? 'indeterminate' : false}\n onCheckedChange={(checked) => toggleAllSelection(Boolean(checked))}\n aria-label={labels.table.selectAll}\n />\n ),\n enableSorting: false,\n meta: { priority: 1 },\n cell: ({ row }) => (\n <Checkbox\n checked={selectedIds.includes(row.original.id)}\n onCheckedChange={(checked) => toggleRowSelection(row.original.id, Boolean(checked))}\n onClick={(event) => event.stopPropagation()}\n aria-label={labels.table.selectRow}\n />\n ),\n })\n }\n\n defs.push({\n accessorKey: 'name',\n header: labels.table.name,\n meta: { priority: 1 },\n cell: ({ row }) => {\n const startDate = row.original.startDate ? formatDate(row.original.startDate) : null\n return (\n <div className=\"flex items-center gap-2.5\">\n <ProjectColorDot colorKey={row.original.color} projectName={row.original.name} size=\"sm\" />\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"truncate text-sm font-medium text-foreground\">{row.original.name}</span>\n <span className=\"truncate font-mono text-xs text-muted-foreground\">\n {row.original.code ?? '\u2014'}\n {startDate ? ` \u00B7 ${startDate}` : ''}\n </span>\n </div>\n </div>\n )\n },\n })\n\n defs.push({\n accessorKey: 'customerName',\n id: 'customerName',\n header: labels.table.customer,\n enableSorting: false,\n meta: { priority: 2 },\n cell: ({ row }) => {\n if (row.original.customerName) {\n return <span className=\"text-sm text-muted-foreground\">{row.original.customerName}</span>\n }\n // Only a project that genuinely has no customer gets the call to action.\n // A row that carries the FK but no resolvable name (customer removed,\n // customers module absent) is unnamed, not unassigned \u2014 inviting an\n // assignment there would misstate the record.\n if (canManageProjects && !row.original.customerId) {\n return (\n <Link\n href={`/backend/staff/time-tracking/projects/${row.original.id}/edit`}\n className=\"text-sm text-primary underline-offset-2 hover:underline\"\n onClick={(event) => event.stopPropagation()}\n >\n {labels.actions.assignCustomer}\n </Link>\n )\n }\n return <span className=\"text-xs text-muted-foreground/70\">\u2014</span>\n },\n })\n\n defs.push({\n accessorKey: 'status',\n header: labels.table.status,\n meta: { priority: 3 },\n cell: ({ row }) => (\n <StatusBadge variant={STATUS_VARIANTS[row.original.status] ?? 'neutral'} dot>\n {labels.statuses[row.original.status as keyof typeof labels.statuses] ?? row.original.status}\n </StatusBadge>\n ),\n })\n\n defs.push(\n isPmRole\n ? {\n accessorKey: 'members',\n id: 'members',\n header: labels.table.team,\n enableSorting: false,\n meta: { priority: 4 },\n cell: ({ row }) => (\n <ProjectMembersAvatarStack\n members={row.original.members}\n total={row.original.memberCount}\n peopleCountLabel={`${row.original.memberCount}`}\n />\n ),\n }\n : {\n accessorKey: 'myRole',\n header: labels.table.myRole,\n enableSorting: false,\n meta: { priority: 4 },\n cell: ({ row }) =>\n row.original.myRole ? (\n <span className=\"text-sm text-foreground\">{row.original.myRole}</span>\n ) : (\n <span className=\"text-xs text-muted-foreground/70\">\u2014</span>\n ),\n },\n )\n\n if (canViewRates) {\n defs.push({\n accessorKey: 'hourlyRate',\n id: 'hourlyRate',\n header: rightHeader(labels.table.rate),\n enableSorting: false,\n meta: { priority: 5 },\n cell: ({ row }) => (\n <span className=\"block text-right font-mono text-sm tabular-nums text-foreground\">\n {formatCurrency(row.original.hourlyRate, row.original.currencyCode) ?? '\u2014'}\n </span>\n ),\n })\n }\n\n defs.push({\n accessorKey: 'totalMinutes',\n id: 'totalMinutes',\n header: rightHeader(labels.table.hours),\n enableSorting: false,\n meta: { priority: 5 },\n cell: ({ row }) => (\n <span className=\"block text-right font-mono text-sm font-semibold tabular-nums text-foreground\">\n {row.original.totalMinutes > 0 ? formatDuration(row.original.totalMinutes, 'clock') : '\u2014'}\n </span>\n ),\n })\n\n if (canViewRates) {\n defs.push({\n accessorKey: 'cost',\n id: 'cost',\n header: rightHeader(labels.table.cost),\n enableSorting: false,\n meta: { priority: 5 },\n cell: ({ row }) => (\n <span className=\"block text-right font-mono text-sm tabular-nums text-foreground\">\n {formatCurrency(row.original.cost, row.original.currencyCode) ?? '\u2014'}\n </span>\n ),\n })\n }\n\n defs.push({\n accessorKey: 'budgetValue',\n id: 'budget',\n header: labels.table.budget,\n enableSorting: false,\n meta: { priority: 5 },\n cell: ({ row }) => {\n if (row.original.budgetKind === 'amount' && !canViewRates) {\n return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n }\n const burn = computeBudgetBurn({\n kind: row.original.budgetKind,\n budgetValue: row.original.budgetValue,\n warnAtPercent: row.original.budgetWarnAtPercent,\n totalMinutes: row.original.totalMinutes,\n cost: row.original.cost,\n })\n const budgetLabel = burn\n ? burn.kind === 'hours'\n ? t('staff.time_tracking.projects.budget.hoursValue', '{value} h', {\n value: Math.round(burn.budgetValue * 10) / 10,\n })\n : formatCurrency(burn.budgetValue, row.original.currencyCode) ?? `${burn.budgetValue}`\n : null\n return (\n <ProjectBudgetCell\n burn={burn}\n usageLabel={\n burn\n ? t('staff.time_tracking.projects.budget.usage', '{percent}% of {value}', {\n percent: burn.percent,\n value: budgetLabel ?? '',\n })\n : null\n }\n noBudgetLabel={labels.budget.none}\n ariaLabel={labels.budget.aria}\n />\n )\n },\n })\n\n defs.push({\n accessorKey: 'hoursWeek',\n header: isPmRole ? labels.table.hoursWeek : labels.table.myHoursWeek,\n enableSorting: false,\n meta: { priority: 6 },\n cell: ({ row }) => {\n const stripe = resolveProjectColorHex(row.original.color, row.original.name)\n return (\n <div className=\"flex items-center justify-end gap-2\">\n <HoursSparkline\n values={row.original.hoursTrend}\n color={stripe}\n ariaLabel={labels.card.sparklineAria}\n />\n <span className=\"text-xs font-medium tabular-nums text-foreground\">\n {row.original.hoursWeek > 0 ? `${row.original.hoursWeek}h` : '\u2014'}\n </span>\n </div>\n )\n },\n })\n\n defs.push({\n accessorKey: 'projectType',\n header: labels.table.type,\n meta: { priority: 7 },\n cell: ({ row }) =>\n row.original.projectType ? (\n <span className=\"text-sm text-foreground\">{row.original.projectType}</span>\n ) : (\n <span className=\"text-xs text-muted-foreground/70\">\u2014</span>\n ),\n })\n\n defs.push({\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 8 },\n cell: ({ row }) => (\n <span className=\"text-xs text-muted-foreground\">\n {formatRelativeTime(row.original.updatedAt, '\u2014', t)}\n </span>\n ),\n })\n\n return defs\n }, [\n allSelected,\n canManageProjects,\n canSelectRows,\n canViewRates,\n isPmRole,\n labels,\n selectedIds,\n someSelected,\n t,\n toggleAllSelection,\n toggleRowSelection,\n ])\n\n const cardLabels = React.useMemo<ProjectCardLabels>(\n () => ({\n hoursPanelPm: labels.card.hoursPanelPm,\n hoursPanelCollab: labels.card.hoursPanelCollab,\n sparklineAria: labels.card.sparklineAria,\n peopleCount: (count: number) => `${count}`,\n role: labels.card.role,\n noCustomer: '\u2014',\n statuses: labels.statuses,\n }),\n [labels.card, labels.statuses],\n )\n\n const emptyStateCopy = React.useMemo(() => {\n const hasFiltersApplied = activeTab !== 'all' || search.trim().length > 0 || Object.values(filterValues).some(Boolean)\n if (hasFiltersApplied) return labels.emptyState.noMatches\n if (!canManageProjects) return labels.emptyState.noAssignments\n return labels.emptyState.noProjects\n }, [activeTab, search, filterValues, canManageProjects, labels.emptyState])\n\n const cardsData: ProjectCardData[] = rows.map((row) => ({\n id: row.id,\n name: row.name,\n code: row.code,\n customerName: row.customerName,\n color: row.color,\n status: row.status,\n hoursWeek: row.hoursWeek,\n hoursTrend: row.hoursTrend,\n members: row.members,\n memberCount: row.memberCount,\n myRole: row.myRole,\n updatedAt: row.updatedAt,\n }))\n\n const tableToolbar = (\n <FilterBar\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n filters={filters}\n values={filterValues}\n onApply={handleFiltersApply}\n onClear={handleFiltersClear}\n trailingItems={\n canSelectRows ? (\n <ProjectsBulkActionsBar\n selectedCount={selectedIds.length}\n labels={{\n selectedCount: t('staff.time_tracking.projects.bulk.selectedCount', '{count} selected', {\n count: selectedIds.length,\n }),\n report: labels.bulk.report,\n assignMembers: labels.bulk.assignMembers,\n clear: labels.bulk.clear,\n }}\n canReport={canCreateReports}\n canAssignMembers={canManageProjects}\n reportBlockedReason={reportBlockedReason}\n isBusy={isAssigning}\n onReport={handleReportFromSelected}\n onAssignMembers={() => setAssignDialogOpen(true)}\n onClear={() => setSelectedIds([])}\n />\n ) : null\n }\n />\n )\n\n return (\n <Page>\n <PageBody>\n <div className=\"mb-4\">\n <ProjectsKpiStrip kpis={kpis} labels={kpiLabels} isLoading={isLoadingKpis} />\n </div>\n\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-3\">\n <SavedViewTabs\n tabs={tabs}\n activeId={activeTab}\n onSelect={handleTabSelect}\n ariaLabel={t('staff.timesheets.projects.portfolio.savedViews.ariaLabel', 'Saved views')}\n />\n <ViewModeToggle\n mode={viewMode}\n onChange={handleViewModeChange}\n tableLabel={labels.viewMode.table}\n cardsLabel={labels.viewMode.cards}\n ariaLabel={t('staff.timesheets.projects.portfolio.viewMode.ariaLabel', 'View mode')}\n />\n </div>\n\n {viewMode === 'cards' ? (\n <div>\n {isLoading ? (\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3\">\n {Array.from({ length: 6 }).map((_, idx) => (\n <div key={idx} className=\"h-48 animate-pulse rounded-lg border border-border bg-muted/40\" />\n ))}\n </div>\n ) : rows.length === 0 ? (\n <div className=\"rounded-lg border border-dashed border-border bg-card p-10 text-center\">\n <p className=\"text-sm text-muted-foreground\">{emptyStateCopy}</p>\n {canManageProjects ? (\n <div className=\"mt-3\">\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/time-tracking/projects/create\">\n {labels.actions.addFirst}\n </Link>\n </Button>\n </div>\n ) : null}\n </div>\n ) : (\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3\">\n {cardsData.map((card) => (\n <ProjectCard\n key={card.id}\n data={card}\n labels={cardLabels}\n showTeam={isPmRole}\n href={`/backend/staff/time-tracking/projects/${card.id}`}\n />\n ))}\n </div>\n )}\n </div>\n ) : (\n <DataTable<ProjectRow>\n extensionTableId={extensionPoints.hosts.timeProjectsTable.tableId}\n title={labels.title}\n titleHeadingLevel={1}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n toolbar={tableToolbar}\n emptyState={\n <div className=\"py-12 text-center\">\n <p className=\"text-sm text-muted-foreground mb-4\">{emptyStateCopy}</p>\n {canManageProjects ? (\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/time-tracking/projects/create\">{labels.actions.addFirst}</Link>\n </Button>\n ) : null}\n </div>\n }\n actions={\n canManageProjects ? (\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/time-tracking/projects/create\">{labels.actions.add}</Link>\n </Button>\n ) : undefined\n }\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading || isRefreshing,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalIsCapped,\n totalPages,\n onPageChange: setPage,\n }}\n stickyActionsColumn\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'view',\n label: labels.actions.viewDetails,\n href: `/backend/staff/time-tracking/projects/${row.id}`,\n },\n ...(canManageProjects\n ? [\n {\n id: 'delete',\n label: labels.actions.delete,\n destructive: true,\n onSelect: () => {\n void handleDelete(row)\n },\n },\n ]\n : []),\n ]}\n />\n )}\n onRowClick={(row) => router.push(`/backend/staff/time-tracking/projects/${row.id}`)}\n />\n )}\n </PageBody>\n {canManageProjects ? (\n <AssignMembersDialog\n open={assignDialogOpen}\n onOpenChange={setAssignDialogOpen}\n isSaving={isAssigning}\n labels={{\n title: labels.assign.title,\n description: t(\n 'staff.time_tracking.projects.assignMembers.description',\n 'Selected projects: {count}.',\n { count: selectedIds.length },\n ),\n searchPlaceholder: labels.assign.searchPlaceholder,\n empty: labels.assign.empty,\n loadError: labels.assign.loadError,\n loading: labels.assign.loading,\n role: labels.assign.role,\n rolePlaceholder: labels.assign.rolePlaceholder,\n startDate: labels.assign.startDate,\n cancel: labels.assign.cancel,\n confirm: labels.assign.confirm,\n }}\n onConfirm={(input) => {\n void handleAssignMembers(input)\n }}\n />\n ) : null}\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,19 @@
1
+ const metadata = {
2
+ requireAuth: true,
3
+ requireFeatures: ["staff.timesheets.projects.view"],
4
+ navHidden: false,
5
+ pageTitle: "Projects",
6
+ pageTitleKey: "staff.time_tracking.nav.projects",
7
+ pageGroup: "Time tracking",
8
+ pageGroupKey: "staff.time_tracking.nav.group",
9
+ pageOrder: 20,
10
+ icon: "folder-tree",
11
+ breadcrumb: [
12
+ { label: "Time tracking", labelKey: "staff.time_tracking.nav.group", href: "/backend/staff/time-tracking" },
13
+ { label: "Projects", labelKey: "staff.time_tracking.nav.projects" }
14
+ ]
15
+ };
16
+ export {
17
+ metadata
18
+ };
19
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/staff/backend/staff/time-tracking/projects/page.meta.ts"],
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['staff.timesheets.projects.view'],\n navHidden: false,\n pageTitle: 'Projects',\n pageTitleKey: 'staff.time_tracking.nav.projects',\n pageGroup: 'Time tracking',\n pageGroupKey: 'staff.time_tracking.nav.group',\n pageOrder: 20,\n icon: 'folder-tree',\n breadcrumb: [\n { label: 'Time tracking', labelKey: 'staff.time_tracking.nav.group', href: '/backend/staff/time-tracking' },\n { label: 'Projects', labelKey: 'staff.time_tracking.nav.projects' },\n ],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,gCAAgC;AAAA,EAClD,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY;AAAA,IACV,EAAE,OAAO,iBAAiB,UAAU,iCAAiC,MAAM,+BAA+B;AAAA,IAC1G,EAAE,OAAO,YAAY,UAAU,mCAAmC;AAAA,EACpE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,353 @@
1
+ import * as React from "react";
2
+ import { z } from "zod";
3
+ import { Input } from "@open-mercato/ui/primitives/input";
4
+ import { SwitchField } from "@open-mercato/ui/primitives/switch-field";
5
+ import { ColorPicker } from "../../../../lib/timesheets-ui/ColorPicker.js";
6
+ import { PROJECT_COLOR_KEYS } from "../../../../lib/timesheets-ui/colors.js";
7
+ import { PROJECT_CODE_MAX_LENGTH } from "../../../../lib/time-tracking/projectCode.js";
8
+ import { CustomerPickerBinding } from "../../../../lib/time-tracking-ui/CustomerPicker.js";
9
+ import { ProjectCodeFieldBinding } from "../../../../lib/time-tracking-ui/ProjectCodeField.js";
10
+ import { ProjectCurrencyFieldBinding } from "../../../../lib/time-tracking-ui/ProjectCurrencyField.js";
11
+ import {
12
+ DEFAULT_BUDGET_WARN_AT_PERCENT,
13
+ ProjectBudgetSection,
14
+ ProjectRoundingNotice,
15
+ ProjectTeamSection
16
+ } from "../../../../lib/time-tracking-ui/ProjectFormSections.js";
17
+ const CUSTOM_FIELD_KEY_PATTERN = /^cf[_:]/;
18
+ function pickCustomFieldValues(values) {
19
+ const picked = {};
20
+ for (const [key, value] of Object.entries(values)) {
21
+ if (CUSTOM_FIELD_KEY_PATTERN.test(key)) picked[key] = value;
22
+ }
23
+ return picked;
24
+ }
25
+ const decimalPattern = /^\d+([.,]\d{1,4})?$/;
26
+ function createProjectFormSchema() {
27
+ return z.object({
28
+ id: z.string().optional(),
29
+ updatedAt: z.string().optional().nullable(),
30
+ name: z.string().min(1, "staff.time_tracking.projects.validation.nameRequired"),
31
+ code: z.string().min(1, "staff.time_tracking.projects.validation.codeRequired").max(PROJECT_CODE_MAX_LENGTH).regex(/^[A-Za-z0-9-]+$/, "staff.time_tracking.projects.validation.codeFormat"),
32
+ codeManual: z.boolean().optional(),
33
+ // D-9 / US-B1: time is organised per customer, so a project cannot be saved without one.
34
+ customerId: z.string().uuid("staff.time_tracking.projects.validation.customerRequired"),
35
+ customerName: z.string().optional().nullable(),
36
+ customerKind: z.string().optional().nullable(),
37
+ customerTaxId: z.string().optional().nullable(),
38
+ description: z.string().max(2e3).optional().nullable(),
39
+ hourlyRate: z.string().regex(decimalPattern, "staff.time_tracking.projects.validation.rateFormat").optional().nullable().or(z.literal("")),
40
+ currencyCode: z.string().min(3).max(10).optional().nullable().or(z.literal("")),
41
+ currencyLocked: z.boolean().optional(),
42
+ entryCount: z.number().optional(),
43
+ billableByDefault: z.boolean().optional(),
44
+ budgetEnabled: z.boolean().optional(),
45
+ budgetKind: z.enum(["none", "hours", "amount"]).optional(),
46
+ budgetValue: z.string().regex(decimalPattern, "staff.time_tracking.projects.validation.budgetFormat").optional().nullable().or(z.literal("")),
47
+ budgetWarnAtPercent: z.string().optional().nullable(),
48
+ projectType: z.string().max(100).optional().nullable(),
49
+ color: z.string().refine(
50
+ (value) => PROJECT_COLOR_KEYS.includes(value),
51
+ { message: "staff.time_tracking.projects.validation.color" }
52
+ ).optional().nullable(),
53
+ startDate: z.string().optional().nullable(),
54
+ costCenter: z.string().max(100).optional().nullable(),
55
+ status: z.enum(["active", "on_hold", "completed"]).optional()
56
+ });
57
+ }
58
+ function readText(values, key) {
59
+ const value = values?.[key];
60
+ return typeof value === "string" ? value : "";
61
+ }
62
+ function createProjectFormFields(t, options = {}) {
63
+ return [
64
+ {
65
+ id: "name",
66
+ type: "text",
67
+ label: t("staff.time_tracking.projects.form.name", "Project name"),
68
+ placeholder: t("staff.time_tracking.projects.form.namePlaceholder", "e.g. Nordvik \u2014 service portal"),
69
+ required: true
70
+ },
71
+ {
72
+ id: "code",
73
+ type: "custom",
74
+ label: t("staff.time_tracking.projects.form.code", "Project code"),
75
+ rendersOwnError: true,
76
+ component: (props) => React.createElement(ProjectCodeFieldBinding, {
77
+ value: props.value,
78
+ values: props.values,
79
+ error: props.error,
80
+ disabled: props.disabled,
81
+ setValue: props.setValue,
82
+ setFormValue: props.setFormValue
83
+ })
84
+ },
85
+ {
86
+ id: "customerId",
87
+ type: "custom",
88
+ label: t("staff.time_tracking.projects.form.customer", "Customer"),
89
+ description: t(
90
+ "staff.time_tracking.projects.form.customerHint",
91
+ "Time is organised per customer \u2014 a project cannot be saved without one."
92
+ ),
93
+ required: true,
94
+ component: (props) => React.createElement(CustomerPickerBinding, {
95
+ value: props.value,
96
+ values: props.values,
97
+ disabled: props.disabled,
98
+ setValue: props.setValue,
99
+ setFormValue: props.setFormValue
100
+ })
101
+ },
102
+ {
103
+ id: "description",
104
+ type: "textarea",
105
+ label: t("staff.time_tracking.projects.form.description", "Description"),
106
+ placeholder: t(
107
+ "staff.time_tracking.projects.form.descriptionPlaceholder",
108
+ "Scope of work, what was agreed with the customer\u2026"
109
+ ),
110
+ rows: 4
111
+ },
112
+ {
113
+ id: "hourlyRate",
114
+ type: "custom",
115
+ label: t("staff.time_tracking.projects.form.hourlyRate", "Hourly rate"),
116
+ layout: "half",
117
+ component: (props) => React.createElement(
118
+ "div",
119
+ { className: "flex items-center gap-2" },
120
+ React.createElement(Input, {
121
+ inputMode: "decimal",
122
+ value: typeof props.value === "string" ? props.value : "",
123
+ disabled: props.disabled,
124
+ "aria-invalid": Boolean(props.error),
125
+ onChange: (event) => props.setValue(event.target.value)
126
+ }),
127
+ React.createElement(
128
+ "span",
129
+ { className: "shrink-0 text-sm text-muted-foreground" },
130
+ t("staff.time_tracking.projects.form.perHour", "/ h")
131
+ )
132
+ )
133
+ },
134
+ {
135
+ id: "currencyCode",
136
+ type: "custom",
137
+ label: t("staff.time_tracking.projects.form.currency", "Currency"),
138
+ layout: "half",
139
+ component: (props) => React.createElement(ProjectCurrencyFieldBinding, {
140
+ value: props.value,
141
+ values: props.values,
142
+ disabled: props.disabled,
143
+ setValue: props.setValue,
144
+ onCurrencyChanged: options.onCurrencyChanged
145
+ })
146
+ },
147
+ {
148
+ id: "billableByDefault",
149
+ type: "custom",
150
+ label: t("staff.time_tracking.projects.form.billableByDefault", "Billable by default"),
151
+ component: (props) => React.createElement(SwitchField, {
152
+ checked: props.value !== false,
153
+ disabled: props.disabled,
154
+ onCheckedChange: (next) => props.setValue(next === true),
155
+ label: t("staff.time_tracking.projects.form.billableByDefault", "Billable by default"),
156
+ description: t(
157
+ "staff.time_tracking.projects.form.billableByDefaultHint",
158
+ "New entries in this project start as billable."
159
+ )
160
+ })
161
+ },
162
+ {
163
+ id: "status",
164
+ type: "select",
165
+ label: t("staff.time_tracking.projects.form.status", "Status"),
166
+ options: [
167
+ { value: "active", label: t("staff.timesheets.projects.statuses.active", "Active") },
168
+ { value: "on_hold", label: t("staff.timesheets.projects.statuses.onHold", "On Hold") },
169
+ { value: "completed", label: t("staff.timesheets.projects.statuses.completed", "Completed") }
170
+ ]
171
+ },
172
+ {
173
+ id: "color",
174
+ type: "custom",
175
+ label: t("staff.timesheets.projects.form.color", "Project color"),
176
+ component: (props) => React.createElement(ColorPicker, {
177
+ value: typeof props.value === "string" ? props.value : null,
178
+ onChange: (next) => props.setValue(next),
179
+ resetLabel: t("staff.timesheets.projects.form.colorAuto", "Auto")
180
+ })
181
+ },
182
+ {
183
+ id: "projectType",
184
+ type: "text",
185
+ label: t("staff.timesheets.projects.form.projectType", "Project type"),
186
+ placeholder: t("staff.timesheets.projects.form.projectTypePlaceholder", "e.g. Internal, Client, R&D")
187
+ },
188
+ {
189
+ id: "startDate",
190
+ type: "date",
191
+ label: t("staff.timesheets.projects.form.startDate", "Start date")
192
+ },
193
+ {
194
+ id: "costCenter",
195
+ type: "text",
196
+ label: t("staff.timesheets.projects.form.costCenter", "Cost center"),
197
+ placeholder: t("staff.timesheets.projects.form.costCenterPlaceholder", "Cost center code")
198
+ }
199
+ ];
200
+ }
201
+ const PROJECT_FORM_GROUP_IDS = [
202
+ "basics",
203
+ "billing",
204
+ "budget",
205
+ "status",
206
+ "team",
207
+ "rounding",
208
+ "details"
209
+ ];
210
+ const PROJECT_FORM_COMPACT_GROUP_IDS = ["basics", "billing"];
211
+ function createProjectFormGroups(t, options = {}) {
212
+ if (options.compact) {
213
+ return [
214
+ {
215
+ id: "basics",
216
+ column: 1,
217
+ title: t("staff.time_tracking.projects.form.groupBasics", "Basics"),
218
+ fields: ["name", "code", "customerId", "description"]
219
+ },
220
+ {
221
+ id: "billing",
222
+ column: 1,
223
+ title: t("staff.time_tracking.projects.form.groupBilling", "Billing"),
224
+ description: t(
225
+ "staff.time_tracking.projects.form.groupBillingHint",
226
+ "You can leave this empty and fill it in before the first report."
227
+ ),
228
+ fields: ["hourlyRate", "currencyCode", "billableByDefault"]
229
+ }
230
+ ];
231
+ }
232
+ return [
233
+ {
234
+ id: "basics",
235
+ column: 1,
236
+ title: t("staff.time_tracking.projects.form.groupBasics", "Basics"),
237
+ fields: ["name", "code", "customerId", "description"]
238
+ },
239
+ {
240
+ id: "billing",
241
+ column: 1,
242
+ title: t("staff.time_tracking.projects.form.groupBilling", "Billing"),
243
+ description: t(
244
+ "staff.time_tracking.projects.form.groupBillingHint",
245
+ "You can leave this empty and fill it in before the first report."
246
+ ),
247
+ fields: ["hourlyRate", "currencyCode", "billableByDefault"]
248
+ },
249
+ {
250
+ id: "budget",
251
+ column: 1,
252
+ title: t("staff.time_tracking.projects.form.groupBudget", "Budget"),
253
+ component: (ctx) => React.createElement(ProjectBudgetSection, {
254
+ enabled: ctx.values.budgetEnabled === true,
255
+ kind: ctx.values.budgetKind ?? "hours",
256
+ value: readText(ctx.values, "budgetValue"),
257
+ warnAtPercent: readText(ctx.values, "budgetWarnAtPercent") || String(DEFAULT_BUDGET_WARN_AT_PERCENT),
258
+ currencyCode: readText(ctx.values, "currencyCode") || null,
259
+ onChange: (patch) => {
260
+ if (patch.enabled !== void 0) ctx.setValue("budgetEnabled", patch.enabled);
261
+ if (patch.kind !== void 0) ctx.setValue("budgetKind", patch.kind);
262
+ if (patch.value !== void 0) ctx.setValue("budgetValue", patch.value);
263
+ if (patch.warnAtPercent !== void 0) ctx.setValue("budgetWarnAtPercent", patch.warnAtPercent);
264
+ }
265
+ })
266
+ },
267
+ {
268
+ id: "status",
269
+ column: 2,
270
+ title: t("staff.time_tracking.projects.form.groupStatus", "Status"),
271
+ fields: ["status"]
272
+ },
273
+ {
274
+ id: "team",
275
+ column: 2,
276
+ title: t("staff.time_tracking.projects.form.groupTeam", "Team"),
277
+ component: (ctx) => React.createElement(ProjectTeamSection, {
278
+ projectId: typeof ctx.values.id === "string" ? ctx.values.id : null
279
+ })
280
+ },
281
+ {
282
+ id: "rounding",
283
+ column: 2,
284
+ bare: true,
285
+ component: () => React.createElement(ProjectRoundingNotice, {})
286
+ },
287
+ {
288
+ id: "details",
289
+ column: 2,
290
+ title: t("staff.timesheets.projects.form.groupDetails", "Additional Information"),
291
+ fields: ["color", "projectType", "startDate", "costCenter"]
292
+ }
293
+ ];
294
+ }
295
+ function trimmedOrNull(value) {
296
+ if (typeof value !== "string") return null;
297
+ const trimmed = value.trim();
298
+ return trimmed.length > 0 ? trimmed : null;
299
+ }
300
+ function numericOrNull(value) {
301
+ const trimmed = trimmedOrNull(value);
302
+ if (trimmed === null) return null;
303
+ return trimmed.replace(",", ".");
304
+ }
305
+ function buildCustomerSnapshot(values) {
306
+ const name = trimmedOrNull(values.customerName);
307
+ if (!values.customerId || !name) return null;
308
+ const snapshot = { name };
309
+ const kind = trimmedOrNull(values.customerKind);
310
+ if (kind) snapshot.kind = kind;
311
+ const taxId = trimmedOrNull(values.customerTaxId);
312
+ if (taxId) snapshot.taxId = taxId;
313
+ return snapshot;
314
+ }
315
+ function buildProjectPayload(values) {
316
+ const budgetEnabled = values.budgetEnabled === true;
317
+ const budgetKind = budgetEnabled ? values.budgetKind && values.budgetKind !== "none" ? values.budgetKind : "hours" : "none";
318
+ const warnAt = Number.parseInt(trimmedOrNull(values.budgetWarnAtPercent) ?? "", 10);
319
+ const payload = {
320
+ name: values.name.trim(),
321
+ code: values.code.trim().toUpperCase(),
322
+ customerId: values.customerId ?? null,
323
+ customerSnapshot: buildCustomerSnapshot(values),
324
+ description: trimmedOrNull(values.description),
325
+ projectType: trimmedOrNull(values.projectType),
326
+ color: trimmedOrNull(values.color),
327
+ startDate: values.startDate || null,
328
+ costCenter: trimmedOrNull(values.costCenter),
329
+ hourlyRate: numericOrNull(values.hourlyRate),
330
+ billableByDefault: values.billableByDefault !== false,
331
+ budgetKind,
332
+ budgetValue: budgetEnabled ? numericOrNull(values.budgetValue) : null,
333
+ budgetWarnAtPercent: Number.isFinite(warnAt) ? warnAt : DEFAULT_BUDGET_WARN_AT_PERCENT
334
+ };
335
+ if (!values.id) {
336
+ payload.currencyCode = trimmedOrNull(values.currencyCode);
337
+ } else {
338
+ payload.id = values.id;
339
+ }
340
+ if (values.status) payload.status = values.status;
341
+ Object.assign(payload, pickCustomFieldValues(values));
342
+ return payload;
343
+ }
344
+ export {
345
+ PROJECT_FORM_COMPACT_GROUP_IDS,
346
+ PROJECT_FORM_GROUP_IDS,
347
+ buildProjectPayload,
348
+ createProjectFormFields,
349
+ createProjectFormGroups,
350
+ createProjectFormSchema,
351
+ pickCustomFieldValues
352
+ };
353
+ //# sourceMappingURL=projectFormConfig.js.map