@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/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\n/**\n * Screen 1 \u2014 My work, the Team Member's landing page (T5.6).\n *\n * Everything on it comes from one request (`GET \u2026/timesheets/my-work`), so the\n * four KPIs, today's entries and the project budget bars can never disagree with\n * each other the way six independent list calls could.\n *\n * The mockup's five notes:\n *\n * 1. The running-timer pill lives in the top bar and is contributed by the\n * `timer-sidebar-indicator` injection widget, not by this page.\n * 2. **TL-only navigation is absent, not disabled** \u2014 the sidebar is built from\n * page metadata whose `requireFeatures` are evaluated per user, so a TM never\n * receives the Projects / Reports / Settings entries at all (confirmed at\n * `nav.ts`: an unmet feature `continue`s past the entry).\n * 3. The quick-entry row uses the same duration parser as the rest of the module\n * and saves with `\u2318\u21B5`.\n * 4. Budget bars come from the project's own budget; a project without one shows\n * hours and no bar. An `amount` budget is money, so it is absent for a caller\n * without `staff.timesheets.rates.view` rather than rendered at zero.\n * 5. \"Copy yesterday\" duplicates the previous day's entries as drafts to correct\n * (US-D6), and reports what it skipped \u2014 a locked entry is skipped, never\n * silently dropped.\n *\n * Screen 2 (no assignments) is the same page with `projects: []`: it renders\n * `NoTimeProjectAssignments`, which already carries the copy and the single\n * available action.\n */\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { CalendarDays, Copy, Lock, Pencil, Plus } from 'lucide-react'\nimport { Page, PageBody, PageHeader } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Progress } from '@open-mercato/ui/primitives/progress'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-badge'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { KpiCard } from '@open-mercato/ui/backend/charts'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { InjectionSpot } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport { useBackendChrome } from '@open-mercato/ui/backend/BackendChromeProvider'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { hasFeature } from '@open-mercato/shared/security/features'\nimport { formatCurrency } from '@open-mercato/ui/utils/format'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { DurationInput } from '../../../lib/time-tracking-ui/DurationInput'\nimport {\n EntryDetailsFields,\n emptyEntryDetails,\n type EntryDetailsValue,\n} from '../../../lib/time-tracking-ui/EntryDetailsFields'\nimport { buildEntryClocks } from '../../../lib/time-tracking-ui/taskDrawerData'\nimport { slugifyProjectName } from '../../../lib/time-tracking/projectCode'\nimport type { TagOption } from '../../../lib/time-tracking-ui/timeEntryDialogState'\nimport { TimeEntryDialog } from '../../../lib/time-tracking-ui/TimeEntryDialog'\nimport { NoTimeProjectAssignments } from '../../../lib/time-tracking-ui/NoProjectAccess'\nimport { formatDuration } from '../../../lib/time-tracking/duration'\nimport { formatLongDayLabel, todayIso } from '../../../lib/time-tracking-ui/timesheetPeriod'\nimport { buildLogTargets, parseTargetKey, targetLabel } from '../../../lib/time-tracking-ui/timesheetTargets'\nimport { isEntryLockedError } from '../../../lib/time-tracking-ui/timeEntryListData'\n\nconst logger = createLogger('staff').child({ component: 'time-tracking/my-work' })\n\nconst MY_WORK_ENDPOINT = '/api/staff/timesheets/my-work'\nconst ENTRIES_API_PATH = 'staff/timesheets/time-entries'\nconst MANAGE_OWN_FEATURE = 'staff.timesheets.manage_own'\nconst MUTATION_CONTEXT_ID = 'staff.time_tracking.myWork'\nconst TIMESHEET_HREF = '/backend/staff/time-tracking/timesheet'\nconst ENTRIES_HREF = '/backend/staff/time-tracking/entries'\n\ntype MyWorkEntry = {\n id: string\n date: string\n taskId: string | null\n taskTitle: string | null\n timeProjectId: string | null\n projectName: string | null\n description: string | null\n startedAt: string | null\n endedAt: string | null\n durationMinutes: number\n isBillable: boolean\n isLocked: boolean\n}\n\ntype MyWorkProject = {\n id: string\n name: string\n code: string | null\n color: string | null\n customerName: string | null\n myMinutes: number\n totalMinutes: number\n hourlyRate?: number | null\n currencyCode?: string | null\n budget: {\n kind: 'hours' | 'amount'\n budgetValue: number\n usedValue: number\n percent: number\n barPercent: number\n tone: string\n } | null\n}\n\ntype MyWorkTask = {\n id: string\n title: string\n timeProjectId: string\n projectName: string | null\n}\n\ntype MyWorkPayload = {\n staffMember: { id: string; displayName: string } | null\n today: string\n kpis: {\n todayMinutes: number\n weekMinutes: number\n monthMinutes: number\n monthNonBillableMinutes: number\n dailyTargetMinutes: number | null\n weekTargetMinutes: number | null\n monthTargetMinutes: number | null\n weekWorkingDays: number\n monthWorkingDays: number\n nonBillableSharePercent: number | null\n }\n entries: MyWorkEntry[]\n projects: MyWorkProject[]\n recentTasks: MyWorkTask[]\n}\n\nconst EMPTY_PAYLOAD: MyWorkPayload = {\n staffMember: null,\n today: todayIso(),\n kpis: {\n todayMinutes: 0,\n weekMinutes: 0,\n monthMinutes: 0,\n monthNonBillableMinutes: 0,\n dailyTargetMinutes: null,\n weekTargetMinutes: null,\n monthTargetMinutes: null,\n weekWorkingDays: 0,\n monthWorkingDays: 0,\n nonBillableSharePercent: null,\n },\n entries: [],\n projects: [],\n recentTasks: [],\n}\n\nfunction formatClockRange(entry: MyWorkEntry, locale?: string): string | null {\n if (!entry.startedAt || !entry.endedAt) return null\n const format = (iso: string) => {\n const parsed = new Date(iso)\n if (Number.isNaN(parsed.getTime())) return ''\n try {\n return new Intl.DateTimeFormat(locale, { hour: '2-digit', minute: '2-digit', hour12: false }).format(parsed)\n } catch {\n return ''\n }\n }\n const start = format(entry.startedAt)\n const end = format(entry.endedAt)\n return start && end ? `${start} \u2013 ${end}` : null\n}\n\nexport default function TimeTrackingMyWorkPage() {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const { payload: chrome } = useBackendChrome()\n const canManageOwn = hasFeature(chrome?.grantedFeatures, MANAGE_OWN_FEATURE)\n\n const [data, setData] = React.useState<MyWorkPayload>(EMPTY_PAYLOAD)\n const [loadState, setLoadState] = React.useState<'loading' | 'ready' | 'error'>('loading')\n const [dialog, setDialog] = React.useState<{ open: boolean; entryId: string | null }>({\n open: false,\n entryId: null,\n })\n const [quickTargetKey, setQuickTargetKey] = React.useState('')\n const [quickMinutes, setQuickMinutes] = React.useState<number | null>(null)\n const [quickEpoch, setQuickEpoch] = React.useState(0)\n const [quickDetails, setQuickDetails] = React.useState<EntryDetailsValue>(() => emptyEntryDetails(''))\n const [tagOptions, setTagOptions] = React.useState<TagOption[]>([])\n\n // The date defaults to the day the page is showing, once that is known.\n React.useEffect(() => {\n if (!data.today) return\n setQuickDetails((current) => (current.date ? current : { ...current, date: data.today }))\n }, [data.today])\n\n React.useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const res = await Promise.resolve(\n apiCall<{ items?: Array<Record<string, unknown>> }>('/api/staff/timesheets/tags?page=1&pageSize=100'),\n )\n if (cancelled || !res?.ok) return\n const items = Array.isArray(res.result?.items) ? res.result.items : []\n setTagOptions(\n items\n .map((row: Record<string, unknown>) => {\n const id = typeof row.id === 'string' ? row.id : null\n const label = typeof row.label === 'string' ? row.label : null\n return id && label\n ? { id, label, color: typeof row.color === 'string' ? row.color : null }\n : null\n })\n .filter((tag): tag is TagOption => tag !== null),\n )\n } catch {\n // A missing tag vocabulary leaves the picker empty rather than the page broken.\n }\n })()\n return () => { cancelled = true }\n }, [])\n\n const createTag = React.useCallback(\n async (label: string): Promise<TagOption | null> => {\n try {\n const created = await createCrud('/api/staff/timesheets/tags', {\n label,\n slug: slugifyProjectName(label).toLowerCase(),\n }, { errorMessage: t('staff.time_tracking.entryDialog.errors.createTag', 'Could not create the tag.') })\n const payload = created as unknown as Record<string, unknown> | null\n const raw = payload?.id ?? (payload?.result as Record<string, unknown> | undefined)?.id\n const id = typeof raw === 'string' ? raw : null\n if (!id) return null\n const tag: TagOption = { id, label, color: null }\n setTagOptions((current) => [...current, tag])\n return tag\n } catch (error) {\n logger.warn('staff.time_tracking.my-work tag create failed', { err: error })\n return null\n }\n },\n [t],\n )\n const [quickSaving, setQuickSaving] = React.useState(false)\n\n const loadError = t('staff.time_tracking.myWork.errors.load', 'Failed to load your work summary.')\n\n // A failed request leaves `data` at EMPTY_PAYLOAD, which reads as screen 2 \u2014 \"no\n // assignments\" \u2014 so the failure has to be a state of its own or the page reports a\n // server fault as an empty account.\n const load = React.useCallback(async () => {\n try {\n const result = await readApiResultOrThrow<MyWorkPayload>(MY_WORK_ENDPOINT, undefined, {\n errorMessage: loadError,\n fallback: EMPTY_PAYLOAD,\n })\n setData({ ...EMPTY_PAYLOAD, ...result })\n setLoadState('ready')\n } catch (error) {\n logger.error('staff.time_tracking.my-work load failed', { err: error })\n setLoadState('error')\n }\n }, [loadError])\n\n const retryLoad = React.useCallback(() => {\n setLoadState('loading')\n void load()\n }, [load])\n\n React.useEffect(() => {\n void load()\n }, [load, scopeVersion])\n\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: MUTATION_CONTEXT_ID,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const mutationContext = React.useMemo(\n () => ({\n formId: MUTATION_CONTEXT_ID,\n resourceKind: 'staff.timesheets.time_entry',\n retryLastMutation,\n }),\n [retryLastMutation],\n )\n\n const myWorkInjectionContext = React.useMemo(\n () => ({\n staffMemberId: data.staffMember?.id ?? null,\n today: data.today,\n projectIds: data.projects.map((project) => project.id),\n retryLastMutation,\n }),\n [data.projects, data.staffMember?.id, data.today, retryLastMutation],\n )\n\n const quickTargets = React.useMemo(\n () =>\n buildLogTargets(\n data.projects.map((project) => ({\n id: project.id,\n name: project.name,\n code: project.code,\n color: project.color,\n })),\n data.recentTasks.map((task) => ({\n id: task.id,\n title: task.title,\n timeProjectId: task.timeProjectId,\n })),\n ),\n [data.projects, data.recentTasks],\n )\n\n React.useEffect(() => {\n if (quickTargetKey || quickTargets.length === 0) return\n setQuickTargetKey(quickTargets[0].key)\n }, [quickTargetKey, quickTargets])\n\n const todayTotal = data.entries.reduce((sum, entry) => sum + entry.durationMinutes, 0)\n\n const submitQuickEntry = React.useCallback(async () => {\n if (!quickTargetKey || quickMinutes === null || quickMinutes <= 0 || quickSaving) return\n const target = parseTargetKey(quickTargetKey)\n const body = {\n staffMemberId: data.staffMember?.id,\n date: quickDetails.date || data.today,\n timeProjectId: target.timeProjectId,\n taskId: target.taskId,\n durationMinutes: quickMinutes,\n description: quickDetails.description.trim() || null,\n isBillable: quickDetails.isBillable,\n tagIds: quickDetails.tagIds.length > 0 ? quickDetails.tagIds : undefined,\n // Paired or omitted \u2014 a lone start is how the list identifies a running\n // timer, and a manual entry has no segment to stop.\n ...buildEntryClocks({\n date: quickDetails.date || data.today,\n startClock: quickDetails.startClock || null,\n endClock: quickDetails.endClock || null,\n minutes: quickMinutes,\n }),\n source: 'manual',\n }\n setQuickSaving(true)\n try {\n await runMutation({\n operation: () =>\n createCrud(ENTRIES_API_PATH, body, {\n errorMessage: t('staff.timesheets.my.errors.save', 'Failed to save timesheets.'),\n }),\n context: mutationContext,\n mutationPayload: body as unknown as Record<string, unknown>,\n })\n setQuickMinutes(null)\n setQuickEpoch((epoch) => epoch + 1)\n // The date and the billable flag survive; the rest clears. Logging three\n // lines against yesterday should not mean re-picking yesterday each time.\n setQuickDetails((current) => ({\n ...emptyEntryDetails(current.date, current.isBillable),\n }))\n await load()\n } catch (error) {\n logger.error('staff.time_tracking.my-work quick entry failed', { err: error })\n flash(t('staff.timesheets.my.errors.save', 'Failed to save timesheets.'), 'error')\n } finally {\n setQuickSaving(false)\n }\n }, [data.staffMember?.id, data.today, load, mutationContext, quickDetails, quickMinutes, quickSaving, quickTargetKey, runMutation, t])\n\n const copyYesterday = React.useCallback(async () => {\n const today = new Date(`${data.today}T00:00:00.000Z`)\n const yesterday = new Date(today)\n yesterday.setUTCDate(yesterday.getUTCDate() - 1)\n const body = {\n fromDate: yesterday.toISOString().slice(0, 10),\n toDate: data.today,\n }\n try {\n const result = await runMutation({\n operation: () =>\n createCrud<{ copied?: number; skipped?: unknown[] }>(`${ENTRIES_API_PATH}/copy-day`, body, {\n errorMessage: t('staff.time_tracking.entries.errors.copyDay', 'Could not copy the day.'),\n }),\n context: mutationContext,\n mutationPayload: body,\n })\n const copied = (result?.result as { copied?: number } | undefined)?.copied ?? 0\n flash(\n t('staff.time_tracking.myWork.copyDay.done', 'Copied {count} entries from yesterday.', {\n count: String(copied),\n }),\n 'success',\n )\n await load()\n } catch (error) {\n if (isEntryLockedError(error)) {\n flash(\n t(\n 'staff.time_tracking.entries.errors.entryLocked',\n 'This time entry is locked in a closed report and cannot be changed. Unlock the report first.',\n ),\n 'error',\n )\n return\n }\n logger.error('staff.time_tracking.my-work copy day failed', { err: error })\n flash(t('staff.time_tracking.entries.errors.copyDay', 'Could not copy the day.'), 'error')\n }\n }, [data.today, load, mutationContext, runMutation, t])\n\n if (loadState === 'loading') {\n return (\n <Page>\n <PageHeader title={t('staff.time_tracking.nav.my_work', 'My work')} />\n <PageBody>\n <LoadingMessage label={t('staff.timesheets.my.loading', 'Loading timesheets...')} />\n </PageBody>\n </Page>\n )\n }\n\n if (loadState === 'error') {\n return (\n <Page>\n <PageHeader title={t('staff.time_tracking.nav.my_work', 'My work')} />\n <PageBody>\n <ErrorMessage\n label={loadError}\n action={\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={retryLoad}>\n {t('staff.time_tracking.myWork.errors.retry', 'Try again')}\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const subtitle = [formatLongDayLabel(data.today), data.staffMember?.displayName]\n .filter((part): part is string => Boolean(part))\n .join(' \u00B7 ')\n\n const noAssignments = data.projects.length === 0 && data.entries.length === 0\n\n return (\n <Page>\n <PageHeader\n title={t('staff.time_tracking.nav.my_work', 'My work')}\n description={subtitle}\n actions={\n <div className=\"flex items-center gap-2\">\n <Button variant=\"outline\" asChild>\n <Link href={TIMESHEET_HREF}>\n <CalendarDays className=\"size-4\" aria-hidden=\"true\" />\n {t('staff.time_tracking.nav.timesheet', 'Timesheet')}\n </Link>\n </Button>\n {canManageOwn && !noAssignments ? (\n <Button type=\"button\" onClick={() => setDialog({ open: true, entryId: null })}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {t('staff.time_tracking.entries.actions.add', 'Add entry')}\n </Button>\n ) : null}\n </div>\n }\n />\n <PageBody>\n {noAssignments ? (\n <NoTimeProjectAssignments />\n ) : (\n <div className=\"flex flex-col gap-6\">\n <InjectionSpot\n spotId={extensionPoints.hosts.myWorkBeforeSections.spotId}\n context={myWorkInjectionContext}\n data={data}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <KpiCard\n title={t('staff.time_tracking.myWork.kpi.today', 'Today')}\n value={data.kpis.todayMinutes}\n formatValue={(value) => formatDuration(value, 'clock')}\n comparisonLabel={\n data.kpis.dailyTargetMinutes !== null\n ? t('staff.time_tracking.myWork.kpi.targetGap', 'target {target} \u2014 {gap} to go', {\n target: formatDuration(data.kpis.dailyTargetMinutes, 'clock'),\n gap: formatDuration(\n Math.max(0, data.kpis.dailyTargetMinutes - data.kpis.todayMinutes),\n 'clock',\n ),\n })\n : undefined\n }\n />\n <KpiCard\n title={t('staff.time_tracking.myWork.kpi.week', 'This week')}\n value={data.kpis.weekMinutes}\n formatValue={(value) => formatDuration(value, 'clock')}\n comparisonLabel={\n data.kpis.weekTargetMinutes !== null\n ? t('staff.time_tracking.myWork.kpi.ofTarget', 'of {target}', {\n target: formatDuration(data.kpis.weekTargetMinutes, 'clock'),\n })\n : undefined\n }\n />\n <KpiCard\n title={t('staff.time_tracking.myWork.kpi.month', 'This month')}\n value={data.kpis.monthMinutes}\n formatValue={(value) => formatDuration(value, 'clock')}\n comparisonLabel={t('staff.time_tracking.myWork.kpi.workingDays', '{days} working days', {\n days: String(data.kpis.monthWorkingDays),\n })}\n />\n <KpiCard\n title={t('staff.time_tracking.myWork.kpi.nonBillable', 'Non-billable')}\n value={data.kpis.monthNonBillableMinutes}\n formatValue={(value) => formatDuration(value, 'clock')}\n comparisonLabel={\n data.kpis.nonBillableSharePercent !== null\n ? t('staff.time_tracking.myWork.kpi.shareOfMonth', '{percent}% of the month', {\n percent: String(data.kpis.nonBillableSharePercent),\n })\n : undefined\n }\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-6 xl:grid-cols-3\">\n <section className=\"rounded-lg border xl:col-span-2\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b p-4\">\n <h2 className=\"text-sm font-semibold\">\n {t('staff.time_tracking.myWork.today.title', 'Today\u2019s entries')}\n </h2>\n <div className=\"flex items-center gap-2\">\n {canManageOwn ? (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void copyYesterday()}>\n <Copy className=\"size-4\" aria-hidden=\"true\" />\n {t('staff.time_tracking.myWork.today.copyYesterday', 'Copy yesterday')}\n </Button>\n ) : null}\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link href={ENTRIES_HREF}>\n {t('staff.time_tracking.myWork.today.allEntries', 'All entries')}\n </Link>\n </Button>\n </div>\n </div>\n\n {data.entries.length === 0 ? (\n <p className=\"p-4 text-sm text-muted-foreground\">\n {t('staff.time_tracking.myWork.today.empty', 'Nothing logged today yet.')}\n </p>\n ) : (\n <table className=\"w-full text-sm\">\n <tbody>\n {data.entries.map((entry) => (\n <tr key={entry.id} className=\"border-b last:border-0\">\n <td className=\"p-3 align-top\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium\">\n {entry.taskTitle ??\n entry.description ??\n t('staff.time_tracking.entries.table.noTask', 'No task')}\n </span>\n {entry.isBillable ? null : (\n <StatusBadge variant=\"neutral\">\n {t('staff.time_tracking.entries.badges.nonBillable', 'non-billable')}\n </StatusBadge>\n )}\n {entry.isLocked ? (\n <StatusBadge variant=\"neutral\">\n <Lock className=\"size-3\" aria-hidden=\"true\" />\n {t('staff.time_tracking.entries.badges.locked', 'locked')}\n </StatusBadge>\n ) : null}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {[entry.projectName, entry.taskTitle ? entry.description : null]\n .filter((part): part is string => Boolean(part))\n .join(' \u00B7 ')}\n </div>\n </td>\n <td className=\"w-32 p-3 align-top text-xs text-muted-foreground\">\n {formatClockRange(entry) ?? '\u2014'}\n </td>\n <td className=\"w-20 p-3 text-right align-top font-mono font-semibold tabular-nums\">\n {formatDuration(entry.durationMinutes, 'clock')}\n </td>\n <td className=\"w-16 p-3 text-right align-top\">\n {canManageOwn && !entry.isLocked ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"2xs\"\n aria-label={t('staff.time_tracking.timesheet.list.edit', 'Edit')}\n onClick={() => setDialog({ open: true, entryId: entry.id })}\n >\n <Pencil className=\"size-3.5\" aria-hidden=\"true\" />\n </Button>\n ) : null}\n </td>\n </tr>\n ))}\n {canManageOwn && quickTargets.length > 0 ? (\n <tr>\n <td colSpan={4} className=\"p-3\">\n <div\n className=\"flex flex-wrap items-start gap-2\"\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void submitQuickEntry()\n }\n }}\n >\n <Select value={quickTargetKey} onValueChange={setQuickTargetKey}>\n <SelectTrigger\n className=\"w-72\"\n aria-label={t('staff.time_tracking.myWork.quickEntry.target', 'Project or task')}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {quickTargets.map((target) => (\n <SelectItem key={target.key} value={target.key}>\n {targetLabel(target)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <div className=\"w-32\">\n <DurationInput\n key={quickEpoch}\n variant=\"compact\"\n value={quickMinutes}\n onChange={(minutes) => setQuickMinutes(minutes)}\n ariaLabel={t('staff.time_tracking.myWork.quickEntry.duration', 'Duration')}\n />\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={quickSaving || quickMinutes === null || quickMinutes <= 0}\n onClick={() => void submitQuickEntry()}\n >\n {t('staff.time_tracking.myWork.quickEntry.save', 'Save')}\n </Button>\n <span className=\"self-center text-xs text-muted-foreground\">\n {t('staff.time_tracking.entryDialog.shortcutSave', '\u2318\u21B5 to save')}\n </span>\n {/*\n * The same block the task drawer offers, from the same\n * component: a row that can log an hour but not say what\n * it was for, or when, sends people to the full dialog\n * for the one field they were missing.\n */}\n <div className=\"w-full\">\n <EntryDetailsFields\n idPrefix=\"my-work-quick\"\n value={quickDetails}\n onChange={setQuickDetails}\n tagOptions={tagOptions}\n onCreateTag={createTag}\n disabled={quickSaving}\n />\n </div>\n </div>\n </td>\n </tr>\n ) : null}\n </tbody>\n <tfoot>\n <tr className=\"border-t bg-muted/40 font-medium\">\n <td className=\"p-3\" colSpan={2}>\n {t('staff.time_tracking.myWork.today.total', 'Total today')}\n </td>\n <td className=\"p-3 text-right font-mono tabular-nums\">\n {formatDuration(todayTotal, 'clock')}\n </td>\n <td />\n </tr>\n </tfoot>\n </table>\n )}\n </section>\n\n <div className=\"flex flex-col gap-6\">\n <section className=\"rounded-lg border\">\n <div className=\"flex items-center justify-between border-b p-4\">\n <h2 className=\"text-sm font-semibold\">\n {t('staff.time_tracking.myWork.projects.title', 'My projects')}\n </h2>\n <span className=\"text-xs text-muted-foreground\">{data.projects.length}</span>\n </div>\n <div className=\"flex flex-col gap-4 p-4\">\n {data.projects.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('staff.time_tracking.myWork.projects.empty', 'No projects assigned yet.')}\n </p>\n ) : (\n data.projects.map((project) => (\n <div key={project.id} className=\"flex flex-col gap-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <Link\n href={`/backend/staff/time-tracking/projects/${project.id}`}\n className=\"min-w-0 truncate font-medium hover:underline\"\n >\n {project.name}\n </Link>\n <span className=\"shrink-0 font-mono text-xs tabular-nums text-muted-foreground\">\n {formatDuration(project.myMinutes, 'clock')}\n </span>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {[\n project.customerName,\n project.hourlyRate != null && project.currencyCode\n ? t('staff.time_tracking.myWork.projects.rate', '{rate}/h', {\n rate: formatCurrency(project.hourlyRate, project.currencyCode) ?? '',\n })\n : null,\n ]\n .filter((part): part is string => Boolean(part))\n .join(' \u00B7 ')}\n </p>\n {project.budget ? (\n <>\n <Progress\n value={project.budget.barPercent}\n size=\"sm\"\n tone={\n project.budget.tone === 'destructive'\n ? 'destructive'\n : project.budget.tone === 'warning'\n ? 'warning'\n : 'accent'\n }\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('staff.time_tracking.myWork.projects.budget', '{percent}% of budget ({value})', {\n percent: String(project.budget.percent),\n value:\n project.budget.kind === 'hours'\n ? t('staff.time_tracking.myWork.projects.budgetHours', '{hours} h', {\n hours: String(project.budget.budgetValue),\n })\n : formatCurrency(project.budget.budgetValue, project.currencyCode ?? undefined) ??\n String(project.budget.budgetValue),\n })}\n </p>\n </>\n ) : null}\n </div>\n ))\n )}\n </div>\n </section>\n\n <section className=\"rounded-lg border\">\n <div className=\"border-b p-4\">\n <h2 className=\"text-sm font-semibold\">\n {t('staff.time_tracking.myWork.recentTasks.title', 'Recent tasks')}\n </h2>\n </div>\n <div className=\"flex flex-col gap-2 p-4\">\n {data.recentTasks.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('staff.time_tracking.myWork.recentTasks.empty', 'No tasks logged against yet.')}\n </p>\n ) : (\n data.recentTasks.map((task) => (\n <Link\n key={task.id}\n href={`/backend/staff/time-tracking/projects/${task.timeProjectId}/board?task=${task.id}`}\n className=\"flex items-center justify-between gap-2 truncate text-sm hover:underline\"\n >\n <span className=\"truncate\">{task.title}</span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">{task.projectName}</span>\n </Link>\n ))\n )}\n </div>\n </section>\n </div>\n </div>\n <InjectionSpot\n spotId={extensionPoints.hosts.myWorkAfterSections.spotId}\n context={myWorkInjectionContext}\n data={data}\n />\n </div>\n )}\n </PageBody>\n\n <TimeEntryDialog\n open={dialog.open}\n onOpenChange={(open) => setDialog((current) => ({ ...current, open }))}\n entryId={dialog.entryId}\n defaults={{ date: data.today }}\n onSaved={() => {\n void load()\n }}\n />\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,15 @@
1
+ const metadata = {
2
+ requireAuth: true,
3
+ requireFeatures: ["staff.timesheets.view"],
4
+ pageTitle: "My work",
5
+ pageTitleKey: "staff.time_tracking.nav.my_work",
6
+ pageGroup: "Time tracking",
7
+ pageGroupKey: "staff.time_tracking.nav.group",
8
+ pageOrder: 10,
9
+ icon: "clock",
10
+ breadcrumb: [{ label: "My work", labelKey: "staff.time_tracking.nav.my_work" }]
11
+ };
12
+ export {
13
+ metadata
14
+ };
15
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/staff/backend/staff/time-tracking/page.meta.ts"],
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['staff.timesheets.view'],\n pageTitle: 'My work',\n pageTitleKey: 'staff.time_tracking.nav.my_work',\n pageGroup: 'Time tracking',\n pageGroupKey: 'staff.time_tracking.nav.group',\n pageOrder: 10,\n icon: 'clock',\n breadcrumb: [{ label: 'My work', labelKey: 'staff.time_tracking.nav.my_work' }],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,uBAAuB;AAAA,EACzC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY,CAAC,EAAE,OAAO,WAAW,UAAU,kCAAkC,CAAC;AAChF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import Link from "next/link";
4
+ import { useQuery } from "@tanstack/react-query";
5
+ import { ArrowLeft } from "lucide-react";
6
+ import { Page, PageBody, PageHeader } from "@open-mercato/ui/backend/Page";
7
+ import { Button } from "@open-mercato/ui/primitives/button";
8
+ import { LoadingMessage } from "@open-mercato/ui/backend/detail";
9
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
10
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
11
+ import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
12
+ import { TaskBoardScreen } from "../../../../../../lib/time-tracking-ui/TaskBoardScreen.js";
13
+ import { NoProjectAccess } from "../../../../../../lib/time-tracking-ui/NoProjectAccess.js";
14
+ import { readItems, readString } from "../../../../../../lib/time-tracking-ui/kanbanBoardData.js";
15
+ const PROJECTS_HREF = "/backend/staff/time-tracking/projects";
16
+ function ProjectBoardPage({ params }) {
17
+ const t = useT();
18
+ const scopeVersion = useOrganizationScopeVersion();
19
+ const rawId = params?.id;
20
+ const projectId = Array.isArray(rawId) ? rawId[0] ?? null : rawId ?? null;
21
+ const projectQuery = useQuery({
22
+ queryKey: ["staff", "time-tracking", "board", "project", `scope:${scopeVersion}`, projectId ?? "none"],
23
+ enabled: !!projectId,
24
+ staleTime: 6e4,
25
+ queryFn: async () => {
26
+ if (!projectId) return null;
27
+ const call = await apiCall(
28
+ `/api/staff/timesheets/time-projects?ids=${encodeURIComponent(projectId)}&pageSize=1`
29
+ );
30
+ if (!call.ok) return null;
31
+ const row = readItems(call.result)[0];
32
+ if (!row) return null;
33
+ const id = readString(row, "id");
34
+ if (!id) return null;
35
+ return { id, name: readString(row, "name") ?? id };
36
+ }
37
+ });
38
+ if (!projectId) {
39
+ return /* @__PURE__ */ jsx(NoProjectAccess, {});
40
+ }
41
+ if (projectQuery.isLoading) {
42
+ return /* @__PURE__ */ jsxs(Page, { children: [
43
+ /* @__PURE__ */ jsx(PageHeader, { title: t("staff.time_tracking.nav.tasks", "Tasks") }),
44
+ /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("staff.time_tracking.board.loading", "Loading the board\u2026") }) })
45
+ ] });
46
+ }
47
+ if (!projectQuery.data) {
48
+ return /* @__PURE__ */ jsx(NoProjectAccess, { timeProjectId: projectId });
49
+ }
50
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(
51
+ TaskBoardScreen,
52
+ {
53
+ timeProjectId: projectId,
54
+ projectName: projectQuery.data.name,
55
+ headerActions: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsxs(Link, { href: `${PROJECTS_HREF}/${projectId}`, children: [
56
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "size-4", "aria-hidden": "true" }),
57
+ t("staff.time_tracking.board.backToProject", "Back to project")
58
+ ] }) })
59
+ }
60
+ ) });
61
+ }
62
+ export {
63
+ ProjectBoardPage as default
64
+ };
65
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../src/modules/staff/backend/staff/time-tracking/projects/%5Bid%5D/board/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery } from '@tanstack/react-query'\nimport { ArrowLeft } from 'lucide-react'\nimport { Page, PageBody, PageHeader } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { TaskBoardScreen } from '../../../../../../lib/time-tracking-ui/TaskBoardScreen'\nimport { NoProjectAccess } from '../../../../../../lib/time-tracking-ui/NoProjectAccess'\nimport { readItems, readString } from '../../../../../../lib/time-tracking-ui/kanbanBoardData'\n\nconst PROJECTS_HREF = '/backend/staff/time-tracking/projects'\n\n/** The project board of screen 6 \u2014 the same screen, with the project already known. */\nexport default function ProjectBoardPage({ params }: { params?: { id?: string | string[] } }) {\n const t = useT()\n // From the prop, not `useParams()`: backend pages render under the\n // `/backend/[[...slug]]` catch-all, whose params carry `slug`, never `id`.\n const scopeVersion = useOrganizationScopeVersion()\n const rawId = params?.id\n const projectId = Array.isArray(rawId) ? rawId[0] ?? null : rawId ?? null\n\n const projectQuery = useQuery<{ id: string; name: string } | null>({\n queryKey: ['staff', 'time-tracking', 'board', 'project', `scope:${scopeVersion}`, projectId ?? 'none'],\n enabled: !!projectId,\n staleTime: 60_000,\n queryFn: async () => {\n if (!projectId) return null\n const call = await apiCall<Record<string, unknown>>(\n `/api/staff/timesheets/time-projects?ids=${encodeURIComponent(projectId)}&pageSize=1`,\n )\n if (!call.ok) return null\n const row = readItems(call.result)[0]\n if (!row) return null\n const id = readString(row, 'id')\n if (!id) return null\n return { id, name: readString(row, 'name') ?? id }\n },\n })\n\n if (!projectId) {\n return <NoProjectAccess />\n }\n\n if (projectQuery.isLoading) {\n return (\n <Page>\n <PageHeader title={t('staff.time_tracking.nav.tasks', 'Tasks')} />\n <PageBody>\n <LoadingMessage label={t('staff.time_tracking.board.loading', 'Loading the board\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (!projectQuery.data) {\n return <NoProjectAccess timeProjectId={projectId} />\n }\n\n return (\n <Page>\n <TaskBoardScreen\n timeProjectId={projectId}\n projectName={projectQuery.data.name}\n headerActions={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href={`${PROJECTS_HREF}/${projectId}`}>\n <ArrowLeft className=\"size-4\" aria-hidden=\"true\" />\n {t('staff.time_tracking.board.backToProject', 'Back to project')}\n </Link>\n </Button>\n }\n />\n </Page>\n )\n}\n"],
5
+ "mappings": ";AA8CW,cAKL,YALK;AA3CX,OAAO,UAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,MAAM,UAAU,kBAAkB;AAC3C,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,mCAAmC;AAC5C,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAChC,SAAS,WAAW,kBAAkB;AAEtC,MAAM,gBAAgB;AAGP,SAAR,iBAAkC,EAAE,OAAO,GAA4C;AAC5F,QAAM,IAAI,KAAK;AAGf,QAAM,eAAe,4BAA4B;AACjD,QAAM,QAAQ,QAAQ;AACtB,QAAM,YAAY,MAAM,QAAQ,KAAK,IAAI,MAAM,CAAC,KAAK,OAAO,SAAS;AAErE,QAAM,eAAe,SAA8C;AAAA,IACjE,UAAU,CAAC,SAAS,iBAAiB,SAAS,WAAW,SAAS,YAAY,IAAI,aAAa,MAAM;AAAA,IACrG,SAAS,CAAC,CAAC;AAAA,IACX,WAAW;AAAA,IACX,SAAS,YAAY;AACnB,UAAI,CAAC,UAAW,QAAO;AACvB,YAAM,OAAO,MAAM;AAAA,QACjB,2CAA2C,mBAAmB,SAAS,CAAC;AAAA,MAC1E;AACA,UAAI,CAAC,KAAK,GAAI,QAAO;AACrB,YAAM,MAAM,UAAU,KAAK,MAAM,EAAE,CAAC;AACpC,UAAI,CAAC,IAAK,QAAO;AACjB,YAAM,KAAK,WAAW,KAAK,IAAI;AAC/B,UAAI,CAAC,GAAI,QAAO;AAChB,aAAO,EAAE,IAAI,MAAM,WAAW,KAAK,MAAM,KAAK,GAAG;AAAA,IACnD;AAAA,EACF,CAAC;AAED,MAAI,CAAC,WAAW;AACd,WAAO,oBAAC,mBAAgB;AAAA,EAC1B;AAEA,MAAI,aAAa,WAAW;AAC1B,WACE,qBAAC,QACC;AAAA,0BAAC,cAAW,OAAO,EAAE,iCAAiC,OAAO,GAAG;AAAA,MAChE,oBAAC,YACC,8BAAC,kBAAe,OAAO,EAAE,qCAAqC,yBAAoB,GAAG,GACvF;AAAA,OACF;AAAA,EAEJ;AAEA,MAAI,CAAC,aAAa,MAAM;AACtB,WAAO,oBAAC,mBAAgB,eAAe,WAAW;AAAA,EACpD;AAEA,SACE,oBAAC,QACC;AAAA,IAAC;AAAA;AAAA,MACC,eAAe;AAAA,MACf,aAAa,aAAa,KAAK;AAAA,MAC/B,eACE,oBAAC,UAAO,SAAO,MAAC,SAAQ,WAAU,MAAK,MACrC,+BAAC,QAAK,MAAM,GAAG,aAAa,IAAI,SAAS,IACvC;AAAA,4BAAC,aAAU,WAAU,UAAS,eAAY,QAAO;AAAA,QAChD,EAAE,2CAA2C,iBAAiB;AAAA,SACjE,GACF;AAAA;AAAA,EAEJ,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,16 @@
1
+ const metadata = {
2
+ requireAuth: true,
3
+ requireFeatures: ["staff.timesheets.tasks.view"],
4
+ navHidden: true,
5
+ pageTitle: "Tasks",
6
+ pageTitleKey: "staff.time_tracking.nav.tasks",
7
+ breadcrumb: [
8
+ { label: "Time tracking", labelKey: "staff.time_tracking.nav.group", href: "/backend/staff/time-tracking" },
9
+ { label: "Projects", labelKey: "staff.time_tracking.nav.projects", href: "/backend/staff/time-tracking/projects" },
10
+ { label: "Tasks", labelKey: "staff.time_tracking.nav.tasks" }
11
+ ]
12
+ };
13
+ export {
14
+ metadata
15
+ };
16
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../src/modules/staff/backend/staff/time-tracking/projects/%5Bid%5D/board/page.meta.ts"],
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['staff.timesheets.tasks.view'],\n navHidden: true,\n pageTitle: 'Tasks',\n pageTitleKey: 'staff.time_tracking.nav.tasks',\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', href: '/backend/staff/time-tracking/projects' },\n { label: 'Tasks', labelKey: 'staff.time_tracking.nav.tasks' },\n ],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,6BAA6B;AAAA,EAC/C,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAAA,EACd,YAAY;AAAA,IACV,EAAE,OAAO,iBAAiB,UAAU,iCAAiC,MAAM,+BAA+B;AAAA,IAC1G,EAAE,OAAO,YAAY,UAAU,oCAAoC,MAAM,wCAAwC;AAAA,IACjH,EAAE,OAAO,SAAS,UAAU,gCAAgC;AAAA,EAC9D;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,229 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { extensionPoints } from "@open-mercato/core/modules/staff/extension-points";
4
+ import * as React from "react";
5
+ import { useRouter } from "next/navigation";
6
+ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
+ import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
8
+ import { updateCrud, deleteCrud } from "@open-mercato/ui/backend/utils/crud";
9
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
10
+ import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
11
+ import { E } from "../../../../../../../../generated/entities.ids.generated.js";
12
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
13
+ import { LoadingMessage, ErrorMessage, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
14
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
15
+ import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
16
+ import { DEFAULT_BUDGET_WARN_AT_PERCENT } from "../../../../../../lib/time-tracking-ui/ProjectFormSections.js";
17
+ import { NoProjectAccess } from "../../../../../../lib/time-tracking-ui/NoProjectAccess.js";
18
+ import {
19
+ buildProjectPayload,
20
+ createProjectFormFields,
21
+ createProjectFormGroups,
22
+ createProjectFormSchema,
23
+ pickCustomFieldValues
24
+ } from "../../projectFormConfig.js";
25
+ const LIST_HREF = "/backend/staff/time-tracking/projects";
26
+ const NO_PROJECT_ACCESS_REASON = "no_project_access";
27
+ class ProjectAccessDeniedError extends Error {
28
+ constructor() {
29
+ super("[internal] no project access");
30
+ this.name = "ProjectAccessDeniedError";
31
+ }
32
+ }
33
+ function readString(record, ...keys) {
34
+ for (const key of keys) {
35
+ const value = record[key];
36
+ if (typeof value === "string" && value.length > 0) return value;
37
+ if (typeof value === "number") return String(value);
38
+ }
39
+ return null;
40
+ }
41
+ function readSnapshot(record) {
42
+ const raw = record.customerSnapshot ?? record.customer_snapshot;
43
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) return raw;
44
+ return null;
45
+ }
46
+ function toValues(record) {
47
+ const snapshot = readSnapshot(record);
48
+ const budgetKindRaw = readString(record, "budgetKind", "budget_kind") ?? "none";
49
+ const budgetKind = budgetKindRaw === "hours" || budgetKindRaw === "amount" ? budgetKindRaw : "none";
50
+ const entryCount = typeof record.entryCount === "number" ? record.entryCount : 0;
51
+ return {
52
+ id: String(record.id ?? ""),
53
+ updatedAt: readString(record, "updatedAt", "updated_at"),
54
+ name: String(record.name ?? ""),
55
+ code: String(record.code ?? ""),
56
+ // D-10: an existing project keeps the code it was saved with — the name no
57
+ // longer drives it.
58
+ codeManual: true,
59
+ customerId: readString(record, "customerId", "customer_id"),
60
+ customerName: typeof snapshot?.name === "string" ? snapshot.name : null,
61
+ customerKind: typeof snapshot?.kind === "string" ? snapshot.kind : null,
62
+ customerTaxId: typeof snapshot?.taxId === "string" ? snapshot.taxId : null,
63
+ description: readString(record, "description"),
64
+ hourlyRate: readString(record, "hourlyRate", "hourly_rate"),
65
+ currencyCode: readString(record, "currencyCode", "currency_code"),
66
+ currencyLocked: record.currencyLocked === true,
67
+ entryCount,
68
+ billableByDefault: (record.billableByDefault ?? record.billable_by_default) !== false,
69
+ budgetEnabled: budgetKind !== "none",
70
+ budgetKind: budgetKind === "none" ? "hours" : budgetKind,
71
+ budgetValue: readString(record, "budgetValue", "budget_value"),
72
+ budgetWarnAtPercent: readString(record, "budgetWarnAtPercent", "budget_warn_at_percent") ?? String(DEFAULT_BUDGET_WARN_AT_PERCENT),
73
+ projectType: readString(record, "projectType", "project_type"),
74
+ color: readString(record, "color"),
75
+ startDate: readString(record, "startDate", "start_date"),
76
+ costCenter: readString(record, "costCenter", "cost_center"),
77
+ status: readString(record, "status") ?? "active",
78
+ // `decorateCustomFields` on the list route returns the saved values as
79
+ // `cf_<key>`, which is exactly what `CrudForm` looks an initial value up by.
80
+ ...pickCustomFieldValues(record)
81
+ };
82
+ }
83
+ function TimeTrackingProjectEditPage({ params }) {
84
+ const projectId = params?.id;
85
+ const t = useT();
86
+ const router = useRouter();
87
+ const scopeVersion = useOrganizationScopeVersion();
88
+ const [initialValues, setInitialValues] = React.useState(null);
89
+ const [loading, setLoading] = React.useState(true);
90
+ const [error, setError] = React.useState(null);
91
+ const [isNotFound, setIsNotFound] = React.useState(false);
92
+ const [accessDenied, setAccessDenied] = React.useState(false);
93
+ const fetchProject = React.useCallback(async () => {
94
+ const call = await apiCall(
95
+ `/api/staff/timesheets/time-projects?ids=${projectId}&pageSize=1`
96
+ );
97
+ if (call.status === 404 && call.result?.reason === NO_PROJECT_ACCESS_REASON) {
98
+ throw new ProjectAccessDeniedError();
99
+ }
100
+ if (!call.ok) {
101
+ throw new Error(t("staff.timesheets.projects.errors.load", "Failed to load project."));
102
+ }
103
+ const record = Array.isArray(call.result?.items) ? call.result.items[0] : null;
104
+ return record ?? null;
105
+ }, [projectId, t]);
106
+ const handleCurrencyChanged = React.useCallback(() => {
107
+ if (!projectId) return;
108
+ void fetchProject().then((record) => {
109
+ if (record) setInitialValues(toValues(record));
110
+ }).catch(() => {
111
+ });
112
+ }, [fetchProject, projectId]);
113
+ const formSchema = React.useMemo(() => createProjectFormSchema(), []);
114
+ const fields = React.useMemo(
115
+ () => createProjectFormFields(t, { onCurrencyChanged: handleCurrencyChanged }),
116
+ [t, handleCurrencyChanged]
117
+ );
118
+ const groups = React.useMemo(() => createProjectFormGroups(t), [t]);
119
+ React.useEffect(() => {
120
+ if (!projectId) return;
121
+ let cancelled = false;
122
+ async function load() {
123
+ setLoading(true);
124
+ setError(null);
125
+ setIsNotFound(false);
126
+ setAccessDenied(false);
127
+ try {
128
+ const record = await fetchProject();
129
+ if (!record) {
130
+ if (!cancelled) setIsNotFound(true);
131
+ return;
132
+ }
133
+ if (!cancelled) setInitialValues(toValues(record));
134
+ } catch (err) {
135
+ if (cancelled) return;
136
+ if (err instanceof ProjectAccessDeniedError) {
137
+ setAccessDenied(true);
138
+ return;
139
+ }
140
+ setError(
141
+ err instanceof Error ? err.message : t("staff.timesheets.projects.errors.load", "Failed to load project.")
142
+ );
143
+ } finally {
144
+ if (!cancelled) setLoading(false);
145
+ }
146
+ }
147
+ load();
148
+ return () => {
149
+ cancelled = true;
150
+ };
151
+ }, [projectId, fetchProject, scopeVersion, t]);
152
+ if (loading) {
153
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("staff.timesheets.projects.loading", "Loading project...") }) }) });
154
+ }
155
+ if (accessDenied) {
156
+ return /* @__PURE__ */ jsx(NoProjectAccess, { timeProjectId: projectId });
157
+ }
158
+ if (isNotFound) {
159
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
160
+ RecordNotFoundState,
161
+ {
162
+ label: t("staff.timesheets.projects.errors.notFound", "Project not found."),
163
+ backHref: LIST_HREF,
164
+ backLabel: t("staff.timesheets.projects.actions.backToList", "Back to projects")
165
+ }
166
+ ) }) });
167
+ }
168
+ if (error || !initialValues) {
169
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(ErrorMessage, { label: error ?? t("staff.timesheets.projects.errors.load", "Failed to load project.") }) }) });
170
+ }
171
+ const detailHref = `/backend/staff/time-tracking/projects/${projectId}`;
172
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
173
+ CrudForm,
174
+ {
175
+ title: t("staff.time_tracking.projects.form.editTitle", "Edit project"),
176
+ titleHeadingLevel: 1,
177
+ backHref: detailHref,
178
+ cancelHref: detailHref,
179
+ fields,
180
+ groups,
181
+ schema: formSchema,
182
+ initialValues,
183
+ entityIds: [E.staff.staff_time_project],
184
+ injectionSpotId: extensionPoints.hosts.projectForm.spotId,
185
+ submitLabel: t("staff.timesheets.projects.form.actions.save", "Save"),
186
+ onDelete: async () => {
187
+ await deleteCrud("staff/timesheets/time-projects", projectId, {
188
+ errorMessage: t("staff.timesheets.projects.errors.delete", "Failed to delete project.")
189
+ });
190
+ flash(t("staff.timesheets.projects.messages.deleted", "Project deleted."), "success");
191
+ router.push(LIST_HREF);
192
+ },
193
+ onSubmit: async (values) => {
194
+ if (!values.name?.trim() || !values.code?.trim() || !values.customerId) {
195
+ const fieldErrors = {};
196
+ if (!values.name?.trim()) {
197
+ fieldErrors.name = t("staff.time_tracking.projects.validation.nameRequired", "A project name is required.");
198
+ }
199
+ if (!values.code?.trim()) {
200
+ fieldErrors.code = t("staff.time_tracking.projects.validation.codeRequired", "A project code is required.");
201
+ }
202
+ if (!values.customerId) {
203
+ fieldErrors.customerId = t("staff.time_tracking.projects.validation.customerRequired", "A customer is required.");
204
+ }
205
+ throw createCrudFormError(
206
+ t("staff.time_tracking.projects.errors.required", "Fill in the required fields."),
207
+ fieldErrors
208
+ );
209
+ }
210
+ const payload = buildProjectPayload({ ...values, id: projectId });
211
+ await updateCrud("staff/timesheets/time-projects", payload, {
212
+ errorMessage: t("staff.timesheets.projects.errors.save", "Failed to save project.")
213
+ });
214
+ flash(t("staff.timesheets.projects.messages.saved", "Project saved."), "success");
215
+ router.push(detailHref);
216
+ },
217
+ versionHistory: {
218
+ resourceKind: "staff.timesheets.time_project",
219
+ resourceId: projectId,
220
+ canUndoRedo: true,
221
+ autoCheckAcl: true
222
+ }
223
+ }
224
+ ) }) });
225
+ }
226
+ export {
227
+ TimeTrackingProjectEditPage as default
228
+ };
229
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../src/modules/staff/backend/staff/time-tracking/projects/%5Bid%5D/edit/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport { extensionPoints } from '@open-mercato/core/modules/staff/extension-points'\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LoadingMessage, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { DEFAULT_BUDGET_WARN_AT_PERCENT, type ProjectBudgetKind } from '../../../../../../lib/time-tracking-ui/ProjectFormSections'\nimport { NoProjectAccess } from '../../../../../../lib/time-tracking-ui/NoProjectAccess'\nimport {\n buildProjectPayload,\n createProjectFormFields,\n createProjectFormGroups,\n createProjectFormSchema,\n pickCustomFieldValues,\n type ProjectFormValues,\n} from '../../projectFormConfig'\n\nconst LIST_HREF = '/backend/staff/time-tracking/projects'\n\n/**\n * Mirrors `NO_PROJECT_ACCESS_REASON` from\n * `api/timesheets/time-projects/route.ts`. The route module is server-only, so\n * the literal is restated here rather than imported into the client bundle;\n * `__tests__/no-project-access-contract.test.ts` pins the two together.\n */\nconst NO_PROJECT_ACCESS_REASON = 'no_project_access'\n\n/** Thrown by the loader so the caller can branch on the guard state. */\nclass ProjectAccessDeniedError extends Error {\n constructor() {\n super('[internal] no project access')\n this.name = 'ProjectAccessDeniedError'\n }\n}\n\ntype ProjectRecord = Record<string, unknown>\n\nfunction readString(record: ProjectRecord, ...keys: string[]): string | null {\n for (const key of keys) {\n const value = record[key]\n if (typeof value === 'string' && value.length > 0) return value\n if (typeof value === 'number') return String(value)\n }\n return null\n}\n\nfunction readSnapshot(record: ProjectRecord): Record<string, unknown> | null {\n const raw = record.customerSnapshot ?? record.customer_snapshot\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) return raw as Record<string, unknown>\n return null\n}\n\nfunction toValues(record: ProjectRecord): ProjectFormValues {\n const snapshot = readSnapshot(record)\n const budgetKindRaw = readString(record, 'budgetKind', 'budget_kind') ?? 'none'\n const budgetKind: ProjectBudgetKind =\n budgetKindRaw === 'hours' || budgetKindRaw === 'amount' ? budgetKindRaw : 'none'\n const entryCount = typeof record.entryCount === 'number' ? record.entryCount : 0\n\n return {\n id: String(record.id ?? ''),\n updatedAt: readString(record, 'updatedAt', 'updated_at'),\n name: String(record.name ?? ''),\n code: String(record.code ?? ''),\n // D-10: an existing project keeps the code it was saved with \u2014 the name no\n // longer drives it.\n codeManual: true,\n customerId: readString(record, 'customerId', 'customer_id'),\n customerName: typeof snapshot?.name === 'string' ? snapshot.name : null,\n customerKind: typeof snapshot?.kind === 'string' ? snapshot.kind : null,\n customerTaxId: typeof snapshot?.taxId === 'string' ? snapshot.taxId : null,\n description: readString(record, 'description'),\n hourlyRate: readString(record, 'hourlyRate', 'hourly_rate'),\n currencyCode: readString(record, 'currencyCode', 'currency_code'),\n currencyLocked: record.currencyLocked === true,\n entryCount,\n billableByDefault: (record.billableByDefault ?? record.billable_by_default) !== false,\n budgetEnabled: budgetKind !== 'none',\n budgetKind: budgetKind === 'none' ? 'hours' : budgetKind,\n budgetValue: readString(record, 'budgetValue', 'budget_value'),\n budgetWarnAtPercent:\n readString(record, 'budgetWarnAtPercent', 'budget_warn_at_percent') ?? String(DEFAULT_BUDGET_WARN_AT_PERCENT),\n projectType: readString(record, 'projectType', 'project_type'),\n color: readString(record, 'color'),\n startDate: readString(record, 'startDate', 'start_date'),\n costCenter: readString(record, 'costCenter', 'cost_center'),\n status: readString(record, 'status') ?? 'active',\n // `decorateCustomFields` on the list route returns the saved values as\n // `cf_<key>`, which is exactly what `CrudForm` looks an initial value up by.\n ...pickCustomFieldValues(record as Record<string, unknown>),\n }\n}\n\nexport default function TimeTrackingProjectEditPage({ params }: { params?: { id?: string } }) {\n const projectId = params?.id\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n\n const [initialValues, setInitialValues] = React.useState<ProjectFormValues | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [accessDenied, setAccessDenied] = React.useState(false)\n\n const fetchProject = React.useCallback(async (): Promise<ProjectRecord | null> => {\n const call = await apiCall<{ items?: ProjectRecord[]; reason?: unknown }>(\n `/api/staff/timesheets/time-projects?ids=${projectId}&pageSize=1`,\n )\n if (call.status === 404 && call.result?.reason === NO_PROJECT_ACCESS_REASON) {\n throw new ProjectAccessDeniedError()\n }\n if (!call.ok) {\n throw new Error(t('staff.timesheets.projects.errors.load', 'Failed to load project.'))\n }\n const record = Array.isArray(call.result?.items) ? call.result.items[0] : null\n return record ?? null\n }, [projectId, t])\n\n /**\n * D-3: the change-currency action writes to the project directly, so it bumped\n * both the currency and `updated_at`. Reload the record \u2014 the form derives its\n * optimistic-lock version from `initialValues.updatedAt`, and a stale one would\n * fail the next save with a conflict this same user had just caused. `CrudForm`\n * merges refreshed initial values without discarding fields being edited.\n */\n const handleCurrencyChanged = React.useCallback(() => {\n if (!projectId) return\n void fetchProject()\n .then((record) => { if (record) setInitialValues(toValues(record)) })\n .catch(() => {\n // Best effort: the optimistic-lock conflict bar remains the backstop.\n })\n }, [fetchProject, projectId])\n\n const formSchema = React.useMemo(() => createProjectFormSchema(), [])\n const fields = React.useMemo(\n () => createProjectFormFields(t, { onCurrencyChanged: handleCurrencyChanged }),\n [t, handleCurrencyChanged],\n )\n const groups = React.useMemo(() => createProjectFormGroups(t), [t])\n\n React.useEffect(() => {\n if (!projectId) return\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n setIsNotFound(false)\n setAccessDenied(false)\n try {\n const record = await fetchProject()\n if (!record) {\n if (!cancelled) setIsNotFound(true)\n return\n }\n if (!cancelled) setInitialValues(toValues(record))\n } catch (err) {\n if (cancelled) return\n if (err instanceof ProjectAccessDeniedError) {\n setAccessDenied(true)\n return\n }\n setError(\n err instanceof Error\n ? err.message\n : t('staff.timesheets.projects.errors.load', 'Failed to load project.'),\n )\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [projectId, fetchProject, scopeVersion, t])\n\n if (loading) {\n return <Page><PageBody><LoadingMessage label={t('staff.timesheets.projects.loading', 'Loading project...')} /></PageBody></Page>\n }\n\n // Screen 17 \u2014 the caller may not open this project. Same guard state the\n // detail page renders; it names neither the customer nor the project.\n if (accessDenied) {\n return <NoProjectAccess timeProjectId={projectId} />\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('staff.timesheets.projects.errors.notFound', 'Project not found.')}\n backHref={LIST_HREF}\n backLabel={t('staff.timesheets.projects.actions.backToList', 'Back to projects')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !initialValues) {\n return <Page><PageBody><ErrorMessage label={error ?? t('staff.timesheets.projects.errors.load', 'Failed to load project.')} /></PageBody></Page>\n }\n\n const detailHref = `/backend/staff/time-tracking/projects/${projectId}`\n\n return (\n <Page>\n <PageBody>\n <CrudForm<ProjectFormValues>\n title={t('staff.time_tracking.projects.form.editTitle', 'Edit project')}\n titleHeadingLevel={1}\n backHref={detailHref}\n cancelHref={detailHref}\n fields={fields}\n groups={groups}\n schema={formSchema}\n initialValues={initialValues}\n entityIds={[E.staff.staff_time_project]}\n injectionSpotId={extensionPoints.hosts.projectForm.spotId}\n submitLabel={t('staff.timesheets.projects.form.actions.save', 'Save')}\n onDelete={async () => {\n await deleteCrud('staff/timesheets/time-projects', projectId!, {\n errorMessage: t('staff.timesheets.projects.errors.delete', 'Failed to delete project.'),\n })\n flash(t('staff.timesheets.projects.messages.deleted', 'Project deleted.'), 'success')\n router.push(LIST_HREF)\n }}\n onSubmit={async (values) => {\n if (!values.name?.trim() || !values.code?.trim() || !values.customerId) {\n const fieldErrors: Record<string, string> = {}\n if (!values.name?.trim()) {\n fieldErrors.name = t('staff.time_tracking.projects.validation.nameRequired', 'A project name is required.')\n }\n if (!values.code?.trim()) {\n fieldErrors.code = t('staff.time_tracking.projects.validation.codeRequired', 'A project code is required.')\n }\n if (!values.customerId) {\n fieldErrors.customerId = t('staff.time_tracking.projects.validation.customerRequired', 'A customer is required.')\n }\n throw createCrudFormError(\n t('staff.time_tracking.projects.errors.required', 'Fill in the required fields.'),\n fieldErrors,\n )\n }\n\n const payload = buildProjectPayload({ ...values, id: projectId })\n\n await updateCrud('staff/timesheets/time-projects', payload, {\n errorMessage: t('staff.timesheets.projects.errors.save', 'Failed to save project.'),\n })\n\n flash(t('staff.timesheets.projects.messages.saved', 'Project saved.'), 'success')\n router.push(detailHref)\n }}\n versionHistory={{\n resourceKind: 'staff.timesheets.time_project',\n resourceId: projectId!,\n canUndoRedo: true,\n autoCheckAcl: true,\n }}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,16 @@
1
+ const metadata = {
2
+ requireAuth: true,
3
+ requireFeatures: ["staff.timesheets.projects.manage"],
4
+ navHidden: true,
5
+ pageTitle: "Edit Project",
6
+ pageTitleKey: "staff.timesheets.nav.edit_project",
7
+ breadcrumb: [
8
+ { label: "Time tracking", labelKey: "staff.time_tracking.nav.group", href: "/backend/staff/time-tracking" },
9
+ { label: "Projects", labelKey: "staff.time_tracking.nav.projects", href: "/backend/staff/time-tracking/projects" },
10
+ { label: "Edit", labelKey: "staff.timesheets.nav.edit_project" }
11
+ ]
12
+ };
13
+ export {
14
+ metadata
15
+ };
16
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../src/modules/staff/backend/staff/time-tracking/projects/%5Bid%5D/edit/page.meta.ts"],
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['staff.timesheets.projects.manage'],\n navHidden: true,\n pageTitle: 'Edit Project',\n pageTitleKey: 'staff.timesheets.nav.edit_project',\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', href: '/backend/staff/time-tracking/projects' },\n { label: 'Edit', labelKey: 'staff.timesheets.nav.edit_project' },\n ],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,kCAAkC;AAAA,EACpD,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAAA,EACd,YAAY;AAAA,IACV,EAAE,OAAO,iBAAiB,UAAU,iCAAiC,MAAM,+BAA+B;AAAA,IAC1G,EAAE,OAAO,YAAY,UAAU,oCAAoC,MAAM,wCAAwC;AAAA,IACjH,EAAE,OAAO,QAAQ,UAAU,oCAAoC;AAAA,EACjE;AACF;",
6
+ "names": []
7
+ }