@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,151 @@
1
+ import {
2
+ clockFromApiValue,
3
+ dateFromApiValue,
4
+ readRowBoolean,
5
+ readRowNumber,
6
+ readRowString
7
+ } from "./timeEntryDialogState.js";
8
+ const TIME_ENTRY_LOCKED_CODE = "time_entry_locked";
9
+ const COPY_DAY_TARGET_NOT_EMPTY_CODE = "copy_day_target_not_empty";
10
+ const EMPTY_TIME_ENTRY_DIRECTORY = {
11
+ taskTitles: /* @__PURE__ */ new Map(),
12
+ projectLabels: /* @__PURE__ */ new Map()
13
+ };
14
+ function readTagIds(row) {
15
+ const tags = Array.isArray(row.tags) ? row.tags : [];
16
+ return tags.map((tag) => tag && typeof tag === "object" ? readRowString(tag, "id") : null).filter((value) => value !== null);
17
+ }
18
+ function toTimeEntryListRow(row, directory = EMPTY_TIME_ENTRY_DIRECTORY) {
19
+ const id = readRowString(row, "id");
20
+ if (!id) return null;
21
+ const taskId = readRowString(row, "task_id", "taskId");
22
+ const timeProjectId = readRowString(row, "time_project_id", "timeProjectId");
23
+ return {
24
+ id,
25
+ date: dateFromApiValue(readRowString(row, "date")),
26
+ taskId,
27
+ taskTitle: taskId ? directory.taskTitles.get(taskId) ?? null : null,
28
+ timeProjectId,
29
+ projectLabel: timeProjectId ? directory.projectLabels.get(timeProjectId) ?? null : null,
30
+ description: readRowString(row, "description", "notes"),
31
+ startText: clockFromApiValue(readRowString(row, "started_at", "startedAt")),
32
+ endText: clockFromApiValue(readRowString(row, "ended_at", "endedAt")),
33
+ durationMinutes: readRowNumber(row, "duration_minutes", "durationMinutes") ?? 0,
34
+ roundedMinutes: readRowNumber(row, "rounded_minutes", "roundedMinutes"),
35
+ isBillable: readRowBoolean(row, true, "is_billable", "isBillable"),
36
+ cost: readRowNumber(row, "cost"),
37
+ currencyCode: readRowString(row, "currencyCode", "rate_currency_code", "rateCurrencyCode"),
38
+ rateOverrideAmount: readRowNumber(row, "rate_override_amount", "rateOverrideAmount"),
39
+ isLocked: readRowBoolean(row, false, "isLocked", "is_locked"),
40
+ lockedReportId: readRowString(row, "lockedReportId", "locked_report_id"),
41
+ updatedAt: readRowString(row, "updated_at", "updatedAt"),
42
+ tagIds: readTagIds(row)
43
+ };
44
+ }
45
+ function summarizeTimeEntries(rows) {
46
+ const byCurrency = /* @__PURE__ */ new Map();
47
+ let totalMinutes = 0;
48
+ for (const row of rows) {
49
+ totalMinutes += Number.isFinite(row.durationMinutes) ? row.durationMinutes : 0;
50
+ if (row.cost === null || !Number.isFinite(row.cost)) continue;
51
+ const key = row.currencyCode ?? "";
52
+ const current = byCurrency.get(key);
53
+ if (current) current.amount += row.cost;
54
+ else byCurrency.set(key, { currencyCode: row.currencyCode ?? null, amount: row.cost });
55
+ }
56
+ return {
57
+ visibleCount: rows.length,
58
+ totalMinutes,
59
+ money: Array.from(byCurrency.values())
60
+ };
61
+ }
62
+ function errorPayloads(error) {
63
+ if (!error || typeof error !== "object") return [];
64
+ const bags = [error];
65
+ const nested = error.body;
66
+ if (nested && typeof nested === "object") bags.push(nested);
67
+ return bags;
68
+ }
69
+ function readErrorCode(error) {
70
+ for (const bag of errorPayloads(error)) {
71
+ if (typeof bag.code === "string" && bag.code.length > 0) return bag.code;
72
+ }
73
+ return null;
74
+ }
75
+ function readErrorStatus(error) {
76
+ for (const bag of errorPayloads(error)) {
77
+ if (typeof bag.status === "number" && Number.isFinite(bag.status)) return bag.status;
78
+ }
79
+ return null;
80
+ }
81
+ function isEntryLockedError(error) {
82
+ const code = readErrorCode(error);
83
+ return code === TIME_ENTRY_LOCKED_CODE || code === "entry_locked";
84
+ }
85
+ function readCopyDayTargetConflict(error) {
86
+ if (readErrorCode(error) !== COPY_DAY_TARGET_NOT_EMPTY_CODE) return null;
87
+ for (const bag of errorPayloads(error)) {
88
+ if (bag.code !== COPY_DAY_TARGET_NOT_EMPTY_CODE) continue;
89
+ const count = bag.existingEntryCount;
90
+ const ids = Array.isArray(bag.existingEntryIds) ? bag.existingEntryIds.length : 0;
91
+ return {
92
+ toDate: typeof bag.toDate === "string" ? bag.toDate : null,
93
+ existingEntryCount: typeof count === "number" && Number.isFinite(count) ? count : ids
94
+ };
95
+ }
96
+ return { toDate: null, existingEntryCount: 0 };
97
+ }
98
+ function toIsoDay(date) {
99
+ const year = date.getFullYear();
100
+ const month = String(date.getMonth() + 1).padStart(2, "0");
101
+ const day = String(date.getDate()).padStart(2, "0");
102
+ return `${year}-${month}-${day}`;
103
+ }
104
+ function currentWeekRange(now = /* @__PURE__ */ new Date()) {
105
+ const start = new Date(now.getFullYear(), now.getMonth(), now.getDate());
106
+ const weekday = (start.getDay() + 6) % 7;
107
+ start.setDate(start.getDate() - weekday);
108
+ const end = new Date(start);
109
+ end.setDate(end.getDate() + 6);
110
+ return { from: toIsoDay(start), to: toIsoDay(end) };
111
+ }
112
+ function formatEntryDay(isoDate, locale) {
113
+ if (!isoDate) return "";
114
+ const parsed = /* @__PURE__ */ new Date(`${isoDate}T00:00:00`);
115
+ if (Number.isNaN(parsed.getTime())) return isoDate;
116
+ try {
117
+ return new Intl.DateTimeFormat(locale, { weekday: "short", day: "numeric", month: "short" }).format(parsed);
118
+ } catch {
119
+ return isoDate;
120
+ }
121
+ }
122
+ function formatEntryClockRange(row) {
123
+ if (!row.startText && !row.endText) return null;
124
+ if (row.startText && row.endText) return `${row.startText} \u2013 ${row.endText}`;
125
+ return row.startText || row.endText;
126
+ }
127
+ function collectDirectoryIds(rows) {
128
+ const taskIds = /* @__PURE__ */ new Set();
129
+ const projectIds = /* @__PURE__ */ new Set();
130
+ for (const row of rows) {
131
+ if (row.taskId) taskIds.add(row.taskId);
132
+ if (row.timeProjectId) projectIds.add(row.timeProjectId);
133
+ }
134
+ return { taskIds: Array.from(taskIds), projectIds: Array.from(projectIds) };
135
+ }
136
+ export {
137
+ COPY_DAY_TARGET_NOT_EMPTY_CODE,
138
+ EMPTY_TIME_ENTRY_DIRECTORY,
139
+ TIME_ENTRY_LOCKED_CODE,
140
+ collectDirectoryIds,
141
+ currentWeekRange,
142
+ formatEntryClockRange,
143
+ formatEntryDay,
144
+ isEntryLockedError,
145
+ readCopyDayTargetConflict,
146
+ readErrorCode,
147
+ readErrorStatus,
148
+ summarizeTimeEntries,
149
+ toTimeEntryListRow
150
+ };
151
+ //# sourceMappingURL=timeEntryListData.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/timeEntryListData.ts"],
4
+ "sourcesContent": ["/**\n * The reading half of screen 10 \u2014 everything the entries list needs that is not\n * React. Kept out of the page so the rules the mockup's notes describe can be\n * tested as arithmetic rather than through a rendered table.\n *\n * Three of those rules live here:\n *\n * 1. **Money is never summed across currencies.** `summarizeTimeEntries`\n * returns one subtotal PER currency instead of a single number. A tenant\n * billing one client in PLN and another in EUR would otherwise read a\n * footer total that is arithmetically valid and financially meaningless.\n * The renderer decides between \"one currency \u2192 show it\" and \"several \u2192\n * show them apart\", but it can never be handed a pre-added figure.\n * 2. **A non-billable entry has no cost, not a zero cost.** The list route\n * already answers `null` for it (screen 10 note 5); nothing here turns that\n * into `0`, and the totals skip it rather than adding nothing to a currency\n * that would then appear in the footer.\n * 3. **The lock and the copy-day refusal are read off the response body, not\n * off the status code.** `409` covers an optimistic-lock conflict, a locked\n * entry and a non-empty copy-day target, and each one needs a different\n * sentence in front of the user.\n */\n\nimport {\n clockFromApiValue,\n dateFromApiValue,\n readRowBoolean,\n readRowNumber,\n readRowString,\n type ApiRow,\n} from './timeEntryDialogState'\n\n/** The shared refusal code every write path answers when an entry is frozen in a report. */\nexport const TIME_ENTRY_LOCKED_CODE = 'time_entry_locked'\n\n/** The refusal a second \"copy yesterday\" click gets instead of a doubled day. */\nexport const COPY_DAY_TARGET_NOT_EMPTY_CODE = 'copy_day_target_not_empty'\n\nexport type TimeEntryListRow = {\n id: string\n date: string\n taskId: string | null\n taskTitle: string | null\n timeProjectId: string | null\n projectLabel: string | null\n description: string | null\n startText: string\n endText: string\n durationMinutes: number\n roundedMinutes: number | null\n isBillable: boolean\n cost: number | null\n currencyCode: string | null\n rateOverrideAmount: number | null\n isLocked: boolean\n lockedReportId: string | null\n updatedAt: string | null\n tagIds: string[]\n}\n\nexport type TimeEntryDirectory = {\n taskTitles: ReadonlyMap<string, string>\n projectLabels: ReadonlyMap<string, string>\n}\n\nexport const EMPTY_TIME_ENTRY_DIRECTORY: TimeEntryDirectory = {\n taskTitles: new Map<string, string>(),\n projectLabels: new Map<string, string>(),\n}\n\nfunction readTagIds(row: ApiRow): string[] {\n const tags = Array.isArray(row.tags) ? row.tags : []\n return tags\n .map((tag) => (tag && typeof tag === 'object' ? readRowString(tag as ApiRow, 'id') : null))\n .filter((value): value is string => value !== null)\n}\n\nexport function toTimeEntryListRow(\n row: ApiRow,\n directory: TimeEntryDirectory = EMPTY_TIME_ENTRY_DIRECTORY,\n): TimeEntryListRow | null {\n const id = readRowString(row, 'id')\n if (!id) return null\n const taskId = readRowString(row, 'task_id', 'taskId')\n const timeProjectId = readRowString(row, 'time_project_id', 'timeProjectId')\n return {\n id,\n date: dateFromApiValue(readRowString(row, 'date')),\n taskId,\n taskTitle: taskId ? directory.taskTitles.get(taskId) ?? null : null,\n timeProjectId,\n projectLabel: timeProjectId ? directory.projectLabels.get(timeProjectId) ?? null : null,\n description: readRowString(row, 'description', 'notes'),\n startText: clockFromApiValue(readRowString(row, 'started_at', 'startedAt')),\n endText: clockFromApiValue(readRowString(row, 'ended_at', 'endedAt')),\n durationMinutes: readRowNumber(row, 'duration_minutes', 'durationMinutes') ?? 0,\n roundedMinutes: readRowNumber(row, 'rounded_minutes', 'roundedMinutes'),\n isBillable: readRowBoolean(row, true, 'is_billable', 'isBillable'),\n cost: readRowNumber(row, 'cost'),\n currencyCode: readRowString(row, 'currencyCode', 'rate_currency_code', 'rateCurrencyCode'),\n rateOverrideAmount: readRowNumber(row, 'rate_override_amount', 'rateOverrideAmount'),\n isLocked: readRowBoolean(row, false, 'isLocked', 'is_locked'),\n lockedReportId: readRowString(row, 'lockedReportId', 'locked_report_id'),\n updatedAt: readRowString(row, 'updated_at', 'updatedAt'),\n tagIds: readTagIds(row),\n }\n}\n\nexport type MoneySubtotal = {\n currencyCode: string | null\n amount: number\n}\n\nexport type TimeEntriesSummary = {\n visibleCount: number\n totalMinutes: number\n /** One entry per currency present among the priced rows; never pre-added. */\n money: MoneySubtotal[]\n}\n\n/**\n * The mockup's `Razem (5 z 23 wpis\u00F3w) \u00B7 15:15 \u00B7 4 315,00 PLN`.\n *\n * The time total is the sum of the durations the table SHOWS, so the footer\n * always reconciles against the column above it; cost is the server's `cost`,\n * which is derived from rounded minutes and is therefore not a function of the\n * displayed duration.\n */\nexport function summarizeTimeEntries(rows: readonly TimeEntryListRow[]): TimeEntriesSummary {\n const byCurrency = new Map<string, MoneySubtotal>()\n let totalMinutes = 0\n for (const row of rows) {\n totalMinutes += Number.isFinite(row.durationMinutes) ? row.durationMinutes : 0\n if (row.cost === null || !Number.isFinite(row.cost)) continue\n const key = row.currencyCode ?? ''\n const current = byCurrency.get(key)\n if (current) current.amount += row.cost\n else byCurrency.set(key, { currencyCode: row.currencyCode ?? null, amount: row.cost })\n }\n return {\n visibleCount: rows.length,\n totalMinutes,\n money: Array.from(byCurrency.values()),\n }\n}\n\ntype ErrorBag = Record<string, unknown>\n\n/**\n * `raiseCrudError` spreads the response body onto the thrown Error, but a\n * caller that re-wraps it can leave the payload one level down. Both shapes are\n * read so a lock refusal never degrades into \"something went wrong\".\n */\nfunction errorPayloads(error: unknown): ErrorBag[] {\n if (!error || typeof error !== 'object') return []\n const bags: ErrorBag[] = [error as ErrorBag]\n const nested = (error as { body?: unknown }).body\n if (nested && typeof nested === 'object') bags.push(nested as ErrorBag)\n return bags\n}\n\nexport function readErrorCode(error: unknown): string | null {\n for (const bag of errorPayloads(error)) {\n if (typeof bag.code === 'string' && bag.code.length > 0) return bag.code\n }\n return null\n}\n\nexport function readErrorStatus(error: unknown): number | null {\n for (const bag of errorPayloads(error)) {\n if (typeof bag.status === 'number' && Number.isFinite(bag.status)) return bag.status\n }\n return null\n}\n\n/**\n * True for the `409 time_entry_locked` every write path answers for an entry a\n * closed report has frozen. `entry_locked` is accepted as well so a route that\n * spells the code without its resource prefix still reads as a lock rather than\n * as a generic failure.\n */\nexport function isEntryLockedError(error: unknown): boolean {\n const code = readErrorCode(error)\n return code === TIME_ENTRY_LOCKED_CODE || code === 'entry_locked'\n}\n\nexport type CopyDayTargetConflict = {\n toDate: string | null\n existingEntryCount: number\n}\n\n/**\n * The `409 copy_day_target_not_empty` that names what is already on the target\n * day. Returning the count is the whole point: the user has to be told what\n * they would be adding to before they are offered `allowDuplicates`.\n */\nexport function readCopyDayTargetConflict(error: unknown): CopyDayTargetConflict | null {\n if (readErrorCode(error) !== COPY_DAY_TARGET_NOT_EMPTY_CODE) return null\n for (const bag of errorPayloads(error)) {\n if (bag.code !== COPY_DAY_TARGET_NOT_EMPTY_CODE) continue\n const count = bag.existingEntryCount\n const ids = Array.isArray(bag.existingEntryIds) ? bag.existingEntryIds.length : 0\n return {\n toDate: typeof bag.toDate === 'string' ? bag.toDate : null,\n existingEntryCount: typeof count === 'number' && Number.isFinite(count) ? count : ids,\n }\n }\n return { toDate: null, existingEntryCount: 0 }\n}\n\nexport type IsoDateRange = {\n from: string\n to: string\n}\n\nfunction toIsoDay(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\n/**\n * Monday-to-Sunday, matching the mockup's \"Okres: ten tydzie\u0144\" default. The\n * week is computed in local time because a time entry is addressed by its\n * calendar day, not by an instant.\n */\nexport function currentWeekRange(now: Date = new Date()): IsoDateRange {\n const start = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const weekday = (start.getDay() + 6) % 7\n start.setDate(start.getDate() - weekday)\n const end = new Date(start)\n end.setDate(end.getDate() + 6)\n return { from: toIsoDay(start), to: toIsoDay(end) }\n}\n\n/**\n * `pon 20 lip` \u2014 the weekday the mockup leads each row with. The locale is left\n * to the runtime by default, exactly as `formatDate`/`formatCurrency` do, so a\n * date on this page reads the same way as a date anywhere else in the backoffice.\n */\nexport function formatEntryDay(isoDate: string, locale?: string): string {\n if (!isoDate) return ''\n const parsed = new Date(`${isoDate}T00:00:00`)\n if (Number.isNaN(parsed.getTime())) return isoDate\n try {\n return new Intl.DateTimeFormat(locale, { weekday: 'short', day: 'numeric', month: 'short' }).format(parsed)\n } catch {\n return isoDate\n }\n}\n\n/** `09:00 \u2013 11:30`, or an em-dash when the entry carries no clock times. */\nexport function formatEntryClockRange(row: Pick<TimeEntryListRow, 'startText' | 'endText'>): string | null {\n if (!row.startText && !row.endText) return null\n if (row.startText && row.endText) return `${row.startText} \u2013 ${row.endText}`\n return row.startText || row.endText\n}\n\nexport function collectDirectoryIds(rows: readonly TimeEntryListRow[]): {\n taskIds: string[]\n projectIds: string[]\n} {\n const taskIds = new Set<string>()\n const projectIds = new Set<string>()\n for (const row of rows) {\n if (row.taskId) taskIds.add(row.taskId)\n if (row.timeProjectId) projectIds.add(row.timeProjectId)\n }\n return { taskIds: Array.from(taskIds), projectIds: Array.from(projectIds) }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,105 @@
1
+ import { formatDuration } from "../time-tracking/duration.js";
2
+ import { roundMinutes } from "../time-tracking/rounding.js";
3
+ import { contributedTimeTrackingSettingKeys } from "../time-tracking/settingKeys.js";
4
+ import { readTimeTrackingSettingValue } from "../time-tracking/settings.js";
5
+ const ROUNDING_UNIT_OPTIONS = [0, 5, 10, 15];
6
+ const ROUNDING_EXAMPLE_MINUTES = [62, 76, 3, 120];
7
+ function buildRoundingExamples(rounding) {
8
+ return ROUNDING_EXAMPLE_MINUTES.map((rawMinutes) => {
9
+ const roundedMinutes = roundMinutes(rawMinutes, rounding);
10
+ return {
11
+ rawMinutes,
12
+ roundedMinutes,
13
+ rawLabel: formatDuration(rawMinutes, "clock"),
14
+ roundedLabel: formatDuration(roundedMinutes, "clock")
15
+ };
16
+ });
17
+ }
18
+ function formatSignedMinutes(minutes) {
19
+ const safe = Number.isFinite(minutes) ? Math.round(minutes) : 0;
20
+ const magnitude = formatDuration(Math.abs(safe), "clock");
21
+ if (safe > 0) return `+${magnitude}`;
22
+ if (safe < 0) return `\u2212${magnitude}`;
23
+ return magnitude;
24
+ }
25
+ const MAX_ASSIGNMENT_GRACE_DAYS_INPUT = 365;
26
+ function toSettingsDraft(settings) {
27
+ return {
28
+ roundingUnitMinutes: settings.rounding.unitMinutes,
29
+ roundingDirection: settings.rounding.direction,
30
+ defaultsBillable: settings.defaults.billable,
31
+ defaultsChainStartFromPreviousEnd: settings.defaults.chainStartFromPreviousEnd,
32
+ dailyHoursText: settings.targets.dailyHours === null ? "" : String(settings.targets.dailyHours),
33
+ warningsOverlap: settings.warnings.overlap,
34
+ warningsRunningTimer: settings.warnings.runningTimer,
35
+ assignmentGraceDaysText: String(settings.access.assignmentGraceDays),
36
+ contributed: Object.fromEntries(
37
+ contributedTimeTrackingSettingKeys().map((entry) => [
38
+ entry.id,
39
+ readTimeTrackingSettingValue(settings, entry.id)
40
+ ])
41
+ )
42
+ };
43
+ }
44
+ function parseDailyHours(text) {
45
+ const trimmed = text.trim();
46
+ if (trimmed.length === 0) return null;
47
+ const parsed = Number(trimmed.replace(",", "."));
48
+ if (!Number.isFinite(parsed) || parsed < 0 || parsed > 24) return void 0;
49
+ return parsed;
50
+ }
51
+ function parseGraceDays(text) {
52
+ const trimmed = text.trim();
53
+ if (trimmed.length === 0) return void 0;
54
+ const parsed = Number(trimmed);
55
+ if (!Number.isInteger(parsed) || parsed < 0 || parsed > MAX_ASSIGNMENT_GRACE_DAYS_INPUT) return void 0;
56
+ return parsed;
57
+ }
58
+ function settingsDraftErrors(draft) {
59
+ const errors = [];
60
+ if (parseDailyHours(draft.dailyHoursText) === void 0) errors.push("dailyHours");
61
+ if (parseGraceDays(draft.assignmentGraceDaysText) === void 0) errors.push("assignmentGraceDays");
62
+ return errors;
63
+ }
64
+ function draftRounding(draft) {
65
+ return { unitMinutes: draft.roundingUnitMinutes, direction: draft.roundingDirection };
66
+ }
67
+ function toSettingsPayload(draft) {
68
+ const dailyHours = parseDailyHours(draft.dailyHoursText);
69
+ const assignmentGraceDays = parseGraceDays(draft.assignmentGraceDaysText);
70
+ if (dailyHours === void 0 || assignmentGraceDays === void 0) return null;
71
+ const payload = {
72
+ rounding: draftRounding(draft),
73
+ defaults: {
74
+ billable: draft.defaultsBillable,
75
+ chainStartFromPreviousEnd: draft.defaultsChainStartFromPreviousEnd
76
+ },
77
+ targets: { dailyHours },
78
+ warnings: { overlap: draft.warningsOverlap, runningTimer: draft.warningsRunningTimer },
79
+ access: { assignmentGraceDays }
80
+ };
81
+ for (const entry of contributedTimeTrackingSettingKeys()) {
82
+ const group = payload[entry.group] ?? {};
83
+ group[entry.key] = draft.contributed[entry.id];
84
+ payload[entry.group] = group;
85
+ }
86
+ return payload;
87
+ }
88
+ function isSettingsDraftDirty(draft, baseline) {
89
+ return draft.roundingUnitMinutes !== baseline.roundingUnitMinutes || draft.roundingDirection !== baseline.roundingDirection || draft.defaultsBillable !== baseline.defaultsBillable || draft.defaultsChainStartFromPreviousEnd !== baseline.defaultsChainStartFromPreviousEnd || draft.dailyHoursText.trim() !== baseline.dailyHoursText.trim() || draft.warningsOverlap !== baseline.warningsOverlap || draft.warningsRunningTimer !== baseline.warningsRunningTimer || draft.assignmentGraceDaysText.trim() !== baseline.assignmentGraceDaysText.trim() || contributedTimeTrackingSettingKeys().some(
90
+ (entry) => !Object.is(draft.contributed[entry.id], baseline.contributed[entry.id])
91
+ );
92
+ }
93
+ export {
94
+ MAX_ASSIGNMENT_GRACE_DAYS_INPUT,
95
+ ROUNDING_EXAMPLE_MINUTES,
96
+ ROUNDING_UNIT_OPTIONS,
97
+ buildRoundingExamples,
98
+ draftRounding,
99
+ formatSignedMinutes,
100
+ isSettingsDraftDirty,
101
+ settingsDraftErrors,
102
+ toSettingsDraft,
103
+ toSettingsPayload
104
+ };
105
+ //# sourceMappingURL=timeTrackingSettingsForm.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts"],
4
+ "sourcesContent": ["/**\n * Pure state for the module settings screen (T7.1, screen 16).\n *\n * The screen edits two numbers that are legitimately empty-able or bounded\n * (`targets.dailyHours` may be blank = no target; `access.assignmentGraceDays` is\n * an integer day count), so the draft keeps them as the TEXT the user typed and\n * converts only at the edges. Stripping a half-typed number back into the field is\n * the same defect `DurationInput` was built to avoid.\n *\n * `buildRoundingExamples` is the screen's most load-bearing function: note 1 of the\n * mockup requires the worked examples to recompute live, because rounding is a rule\n * people misread and its effect is otherwise invisible until an invoice. It calls\n * `roundMinutes` \u2014 the same function the write path calls \u2014 so a preview that\n * disagreed with reality is not expressible here.\n */\n\nimport { formatDuration } from '../time-tracking/duration'\nimport { roundMinutes, type RoundingSettings, type RoundingUnitMinutes } from '../time-tracking/rounding'\nimport { contributedTimeTrackingSettingKeys } from '../time-tracking/settingKeys'\nimport { readTimeTrackingSettingValue, type TimeTrackingSettings } from '../time-tracking/settings'\n\nexport const ROUNDING_UNIT_OPTIONS: readonly RoundingUnitMinutes[] = [0, 5, 10, 15]\n\n/**\n * The four cases from the mockup: just over a unit, past the halfway point, a\n * minimum-charge case, and one that is already exact and must not move.\n */\nexport const ROUNDING_EXAMPLE_MINUTES: readonly number[] = [62, 76, 3, 120]\n\nexport type RoundingExample = {\n rawMinutes: number\n roundedMinutes: number\n rawLabel: string\n roundedLabel: string\n}\n\nexport function buildRoundingExamples(rounding: RoundingSettings): RoundingExample[] {\n return ROUNDING_EXAMPLE_MINUTES.map((rawMinutes) => {\n const roundedMinutes = roundMinutes(rawMinutes, rounding)\n return {\n rawMinutes,\n roundedMinutes,\n rawLabel: formatDuration(rawMinutes, 'clock'),\n roundedLabel: formatDuration(roundedMinutes, 'clock'),\n }\n })\n}\n\n/** `+38:15` / `\u221212:30` / `0:00`, for the impact card's delta against raw time. */\nexport function formatSignedMinutes(minutes: number): string {\n const safe = Number.isFinite(minutes) ? Math.round(minutes) : 0\n const magnitude = formatDuration(Math.abs(safe), 'clock')\n if (safe > 0) return `+${magnitude}`\n if (safe < 0) return `\u2212${magnitude}`\n return magnitude\n}\n\nexport type TimeTrackingSettingsDraft = {\n roundingUnitMinutes: RoundingUnitMinutes\n roundingDirection: RoundingSettings['direction']\n defaultsBillable: boolean\n defaultsChainStartFromPreviousEnd: boolean\n /** Free text: empty means \"no daily target\", which is a real, storable value. */\n dailyHoursText: string\n warningsOverlap: boolean\n warningsRunningTimer: boolean\n assignmentGraceDaysText: string\n /**\n * EP-42 \u2014 every contributed setting key, by its `<group>.<key>` id, carried through\n * the draft untouched so the page's own Save round-trips a contribution it knows\n * nothing about. The eight built-ins are NOT in here: the page renders those itself.\n */\n contributed: Record<string, unknown>\n}\n\n\nexport const MAX_ASSIGNMENT_GRACE_DAYS_INPUT = 365\n\nexport function toSettingsDraft(settings: TimeTrackingSettings): TimeTrackingSettingsDraft {\n return {\n roundingUnitMinutes: settings.rounding.unitMinutes,\n roundingDirection: settings.rounding.direction,\n defaultsBillable: settings.defaults.billable,\n defaultsChainStartFromPreviousEnd: settings.defaults.chainStartFromPreviousEnd,\n dailyHoursText: settings.targets.dailyHours === null ? '' : String(settings.targets.dailyHours),\n warningsOverlap: settings.warnings.overlap,\n warningsRunningTimer: settings.warnings.runningTimer,\n assignmentGraceDaysText: String(settings.access.assignmentGraceDays),\n contributed: Object.fromEntries(\n contributedTimeTrackingSettingKeys().map((entry) => [\n entry.id,\n readTimeTrackingSettingValue(settings, entry.id),\n ]),\n ),\n }\n}\n\nexport type SettingsDraftFieldError = 'dailyHours' | 'assignmentGraceDays'\n\nfunction parseDailyHours(text: string): number | null | undefined {\n const trimmed = text.trim()\n if (trimmed.length === 0) return null\n const parsed = Number(trimmed.replace(',', '.'))\n if (!Number.isFinite(parsed) || parsed < 0 || parsed > 24) return undefined\n return parsed\n}\n\nfunction parseGraceDays(text: string): number | undefined {\n const trimmed = text.trim()\n if (trimmed.length === 0) return undefined\n const parsed = Number(trimmed)\n if (!Number.isInteger(parsed) || parsed < 0 || parsed > MAX_ASSIGNMENT_GRACE_DAYS_INPUT) return undefined\n return parsed\n}\n\n/** Which fields currently hold text that cannot be saved. Empty means the draft is valid. */\nexport function settingsDraftErrors(draft: TimeTrackingSettingsDraft): SettingsDraftFieldError[] {\n const errors: SettingsDraftFieldError[] = []\n if (parseDailyHours(draft.dailyHoursText) === undefined) errors.push('dailyHours')\n if (parseGraceDays(draft.assignmentGraceDaysText) === undefined) errors.push('assignmentGraceDays')\n return errors\n}\n\nexport function draftRounding(draft: TimeTrackingSettingsDraft): RoundingSettings {\n return { unitMinutes: draft.roundingUnitMinutes, direction: draft.roundingDirection }\n}\n\n/** The PUT body. Returns null when the draft still holds unsaveable text. */\nexport function toSettingsPayload(draft: TimeTrackingSettingsDraft): TimeTrackingSettings | null {\n const dailyHours = parseDailyHours(draft.dailyHoursText)\n const assignmentGraceDays = parseGraceDays(draft.assignmentGraceDaysText)\n if (dailyHours === undefined || assignmentGraceDays === undefined) return null\n const payload: TimeTrackingSettings = {\n rounding: draftRounding(draft),\n defaults: {\n billable: draft.defaultsBillable,\n chainStartFromPreviousEnd: draft.defaultsChainStartFromPreviousEnd,\n },\n targets: { dailyHours },\n warnings: { overlap: draft.warningsOverlap, runningTimer: draft.warningsRunningTimer },\n access: { assignmentGraceDays },\n }\n for (const entry of contributedTimeTrackingSettingKeys()) {\n const group = (payload[entry.group] ?? {}) as Record<string, unknown>\n group[entry.key] = draft.contributed[entry.id]\n payload[entry.group] = group\n }\n return payload\n}\n\nexport function isSettingsDraftDirty(\n draft: TimeTrackingSettingsDraft,\n baseline: TimeTrackingSettingsDraft,\n): boolean {\n return (\n draft.roundingUnitMinutes !== baseline.roundingUnitMinutes ||\n draft.roundingDirection !== baseline.roundingDirection ||\n draft.defaultsBillable !== baseline.defaultsBillable ||\n draft.defaultsChainStartFromPreviousEnd !== baseline.defaultsChainStartFromPreviousEnd ||\n draft.dailyHoursText.trim() !== baseline.dailyHoursText.trim() ||\n draft.warningsOverlap !== baseline.warningsOverlap ||\n draft.warningsRunningTimer !== baseline.warningsRunningTimer ||\n draft.assignmentGraceDaysText.trim() !== baseline.assignmentGraceDaysText.trim() ||\n contributedTimeTrackingSettingKeys().some(\n (entry) => !Object.is(draft.contributed[entry.id], baseline.contributed[entry.id]),\n )\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,132 @@
1
+ import {
2
+ countWorkingDays,
3
+ eachDayIso,
4
+ isWeekendIso
5
+ } from "./timesheetPeriod.js";
6
+ import { toTimeEntryListRow } from "./timeEntryListData.js";
7
+ import { readRowString } from "./timeEntryDialogState.js";
8
+ function toTimesheetEntry(row, directory) {
9
+ const base = toTimeEntryListRow(row, directory);
10
+ if (!base) return null;
11
+ return { ...base, staffMemberId: readRowString(row, "staff_member_id", "staffMemberId") };
12
+ }
13
+ function buildTimesheetDays(range, entries) {
14
+ const byDate = /* @__PURE__ */ new Map();
15
+ for (const entry of entries) {
16
+ const bucket = byDate.get(entry.date);
17
+ if (bucket) bucket.push(entry);
18
+ else byDate.set(entry.date, [entry]);
19
+ }
20
+ return eachDayIso(range).map((date) => {
21
+ const dayEntries = (byDate.get(date) ?? []).slice().sort(compareEntriesByClock);
22
+ let totalMinutes = 0;
23
+ let billableMinutes = 0;
24
+ for (const entry of dayEntries) {
25
+ const minutes = Number.isFinite(entry.durationMinutes) ? entry.durationMinutes : 0;
26
+ totalMinutes += minutes;
27
+ if (entry.isBillable) billableMinutes += minutes;
28
+ }
29
+ return { date, isWeekend: isWeekendIso(date), entries: dayEntries, totalMinutes, billableMinutes };
30
+ });
31
+ }
32
+ function compareEntriesByClock(left, right) {
33
+ if (left.startText && right.startText) return left.startText.localeCompare(right.startText);
34
+ if (left.startText) return -1;
35
+ if (right.startText) return 1;
36
+ return 0;
37
+ }
38
+ function summarizeTimesheet(days, range, dailyHours) {
39
+ let totalMinutes = 0;
40
+ let billableMinutes = 0;
41
+ for (const day of days) {
42
+ totalMinutes += day.totalMinutes;
43
+ billableMinutes += day.billableMinutes;
44
+ }
45
+ const workingDays = countWorkingDays(range);
46
+ const hasTarget = typeof dailyHours === "number" && Number.isFinite(dailyHours) && dailyHours > 0;
47
+ const targetMinutes = hasTarget ? Math.round(workingDays * dailyHours * 60) : null;
48
+ return {
49
+ totalMinutes,
50
+ billableMinutes,
51
+ targetMinutes,
52
+ deltaMinutes: targetMinutes === null ? null : totalMinutes - targetMinutes,
53
+ workingDays
54
+ };
55
+ }
56
+ function resolveLoadScaleMinutes(days, dailyHours) {
57
+ if (typeof dailyHours === "number" && Number.isFinite(dailyHours) && dailyHours > 0) {
58
+ return Math.round(dailyHours * 60);
59
+ }
60
+ let longest = 0;
61
+ for (const day of days) {
62
+ if (day.totalMinutes > longest) longest = day.totalMinutes;
63
+ }
64
+ return longest > 0 ? longest : null;
65
+ }
66
+ function loadPercent(totalMinutes, scaleMinutes) {
67
+ if (!scaleMinutes || scaleMinutes <= 0) return 0;
68
+ if (totalMinutes <= 0) return 0;
69
+ return Math.min(100, Math.round(totalMinutes / scaleMinutes * 100));
70
+ }
71
+ function pickDefaultExpandedDay(days, dailyHours, todayIsoValue) {
72
+ const past = days.filter((day) => day.date <= todayIsoValue);
73
+ if (past.length === 0) return null;
74
+ const hasTarget = typeof dailyHours === "number" && Number.isFinite(dailyHours) && dailyHours > 0;
75
+ if (hasTarget) {
76
+ const target = Math.round(dailyHours * 60);
77
+ let best = null;
78
+ for (const day of past) {
79
+ if (day.isWeekend) continue;
80
+ const shortfall = target - day.totalMinutes;
81
+ if (shortfall <= 0) continue;
82
+ if (!best || shortfall > best.shortfall || shortfall === best.shortfall && day.date > best.date) {
83
+ best = { date: day.date, shortfall };
84
+ }
85
+ }
86
+ if (best) return best.date;
87
+ }
88
+ for (let index = past.length - 1; index >= 0; index -= 1) {
89
+ if (past[index].entries.length > 0) return past[index].date;
90
+ }
91
+ return null;
92
+ }
93
+ const CLOCK_PATTERN = /^(\d{1,2}):(\d{2})$/;
94
+ function clockToMinutes(value) {
95
+ const match = CLOCK_PATTERN.exec(value);
96
+ if (!match) return null;
97
+ const hours = Number(match[1]);
98
+ const minutes = Number(match[2]);
99
+ if (hours > 23 || minutes > 59) return null;
100
+ return hours * 60 + minutes;
101
+ }
102
+ function suggestNextStartClock(day) {
103
+ if (!day) return null;
104
+ let latest = null;
105
+ for (const entry of day.entries) {
106
+ if (!entry.endText) continue;
107
+ const minutes = clockToMinutes(entry.endText);
108
+ if (minutes === null) continue;
109
+ if (!latest || minutes > latest.minutes) latest = { minutes, text: entry.endText };
110
+ }
111
+ return latest?.text ?? null;
112
+ }
113
+ function indexDaysByDate(days) {
114
+ const index = /* @__PURE__ */ new Map();
115
+ for (const day of days) index.set(day.date, day);
116
+ return index;
117
+ }
118
+ function entryChipLabel(entry, fallback) {
119
+ return entry.projectLabel ?? entry.taskTitle ?? entry.description ?? fallback;
120
+ }
121
+ export {
122
+ buildTimesheetDays,
123
+ entryChipLabel,
124
+ indexDaysByDate,
125
+ loadPercent,
126
+ pickDefaultExpandedDay,
127
+ resolveLoadScaleMinutes,
128
+ suggestNextStartClock,
129
+ summarizeTimesheet,
130
+ toTimesheetEntry
131
+ };
132
+ //# sourceMappingURL=timesheetData.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/time-tracking-ui/timesheetData.ts"],
4
+ "sourcesContent": ["/**\n * The reading half of the timesheet (screens 11 and 12) \u2014 day buckets, load\n * bars, the period footer and the two \"smart\" defaults the mockups ask for.\n *\n * Kept pure and out of the React tree for the same reason as `timesheetPeriod`:\n * every number a consultant will later defend in front of a client should be\n * testable as arithmetic.\n *\n * Three decisions are encoded here rather than in a component:\n *\n * 1. **A load bar has a scale even without a target.** Screen 11 note 6 is\n * explicit that `targets.dailyHours` is a proposal; when a tenant clears it\n * the bars scale to the longest day of the period instead of disappearing,\n * so \"light day vs heavy day\" (US-E3) still reads at a glance.\n * 2. **Weekends do not raise the target but do raise the total** (screen 12\n * note 4). `countWorkingDays` supplies the target; the totals sum every day.\n * 3. **Money is never summed across currencies** \u2014 this module deliberately\n * exposes no money total at all. The timesheet is a time surface; cost lives\n * on the entries list and the report, both of which subtotal per currency.\n */\n\nimport {\n countWorkingDays,\n eachDayIso,\n isWeekendIso,\n type TimesheetDateRange,\n} from './timesheetPeriod'\nimport { toTimeEntryListRow, type TimeEntryDirectory, type TimeEntryListRow } from './timeEntryListData'\nimport { readRowString, type ApiRow } from './timeEntryDialogState'\n\n/**\n * A timesheet row is an entries-list row plus the person who logged it \u2014 a Team\n * Leader filtering to \"everyone\" needs the author on the line (screen 12 note 1),\n * and a Team Member never sees a row that is not theirs anyway.\n */\nexport type TimesheetEntry = TimeEntryListRow & {\n staffMemberId: string | null\n}\n\nexport function toTimesheetEntry(row: ApiRow, directory?: TimeEntryDirectory): TimesheetEntry | null {\n const base = toTimeEntryListRow(row, directory)\n if (!base) return null\n return { ...base, staffMemberId: readRowString(row, 'staff_member_id', 'staffMemberId') }\n}\n\nexport type TimesheetDay = {\n date: string\n isWeekend: boolean\n entries: TimesheetEntry[]\n totalMinutes: number\n billableMinutes: number\n}\n\nexport function buildTimesheetDays(\n range: TimesheetDateRange,\n entries: readonly TimesheetEntry[],\n): TimesheetDay[] {\n const byDate = new Map<string, TimesheetEntry[]>()\n for (const entry of entries) {\n const bucket = byDate.get(entry.date)\n if (bucket) bucket.push(entry)\n else byDate.set(entry.date, [entry])\n }\n return eachDayIso(range).map((date) => {\n const dayEntries = (byDate.get(date) ?? []).slice().sort(compareEntriesByClock)\n let totalMinutes = 0\n let billableMinutes = 0\n for (const entry of dayEntries) {\n const minutes = Number.isFinite(entry.durationMinutes) ? entry.durationMinutes : 0\n totalMinutes += minutes\n if (entry.isBillable) billableMinutes += minutes\n }\n return { date, isWeekend: isWeekendIso(date), entries: dayEntries, totalMinutes, billableMinutes }\n })\n}\n\n/** Entries read top-to-bottom in the order the day was worked; clock-less ones last. */\nfunction compareEntriesByClock(left: TimesheetEntry, right: TimesheetEntry): number {\n if (left.startText && right.startText) return left.startText.localeCompare(right.startText)\n if (left.startText) return -1\n if (right.startText) return 1\n return 0\n}\n\nexport type TimesheetSummary = {\n totalMinutes: number\n billableMinutes: number\n /** `null` when the tenant cleared `targets.dailyHours` \u2014 there is then nothing to be over or under. */\n targetMinutes: number | null\n deltaMinutes: number | null\n workingDays: number\n}\n\nexport function summarizeTimesheet(\n days: readonly TimesheetDay[],\n range: TimesheetDateRange,\n dailyHours: number | null | undefined,\n): TimesheetSummary {\n let totalMinutes = 0\n let billableMinutes = 0\n for (const day of days) {\n totalMinutes += day.totalMinutes\n billableMinutes += day.billableMinutes\n }\n const workingDays = countWorkingDays(range)\n const hasTarget = typeof dailyHours === 'number' && Number.isFinite(dailyHours) && dailyHours > 0\n const targetMinutes = hasTarget ? Math.round(workingDays * dailyHours * 60) : null\n return {\n totalMinutes,\n billableMinutes,\n targetMinutes,\n deltaMinutes: targetMinutes === null ? null : totalMinutes - targetMinutes,\n workingDays,\n }\n}\n\n/**\n * The scale a day's bar is drawn against. With a daily target it is that target,\n * so 8:00 fills the bar; without one it is the longest day in the period, so the\n * bars still rank the days against each other (screen 11 note 6).\n */\nexport function resolveLoadScaleMinutes(\n days: readonly TimesheetDay[],\n dailyHours: number | null | undefined,\n): number | null {\n if (typeof dailyHours === 'number' && Number.isFinite(dailyHours) && dailyHours > 0) {\n return Math.round(dailyHours * 60)\n }\n let longest = 0\n for (const day of days) {\n if (day.totalMinutes > longest) longest = day.totalMinutes\n }\n return longest > 0 ? longest : null\n}\n\n/** 0\u2013100. A day over target pins at 100 \u2014 the bar reads \"full\", the number reads the overage. */\nexport function loadPercent(totalMinutes: number, scaleMinutes: number | null): number {\n if (!scaleMinutes || scaleMinutes <= 0) return 0\n if (totalMinutes <= 0) return 0\n return Math.min(100, Math.round((totalMinutes / scaleMinutes) * 100))\n}\n\n/**\n * Screen 12 note 2 \u2014 \"only the day that deviates from the target is expanded\".\n *\n * Deviation is measured against the daily target on working days that have\n * already happened; a Thursday nobody has worked yet is not a gap, it is the\n * future. The largest shortfall wins, later days breaking ties, so closing out a\n * week always opens on the day that still needs attention. With no target (or no\n * shortfall) the most recent day carrying entries is opened instead, because an\n * all-collapsed list gives the user nothing to act on.\n */\nexport function pickDefaultExpandedDay(\n days: readonly TimesheetDay[],\n dailyHours: number | null | undefined,\n todayIsoValue: string,\n): string | null {\n const past = days.filter((day) => day.date <= todayIsoValue)\n if (past.length === 0) return null\n const hasTarget = typeof dailyHours === 'number' && Number.isFinite(dailyHours) && dailyHours > 0\n if (hasTarget) {\n const target = Math.round(dailyHours * 60)\n let best: { date: string; shortfall: number } | null = null\n for (const day of past) {\n if (day.isWeekend) continue\n const shortfall = target - day.totalMinutes\n if (shortfall <= 0) continue\n if (!best || shortfall > best.shortfall || (shortfall === best.shortfall && day.date > best.date)) {\n best = { date: day.date, shortfall }\n }\n }\n if (best) return best.date\n }\n for (let index = past.length - 1; index >= 0; index -= 1) {\n if (past[index].entries.length > 0) return past[index].date\n }\n return null\n}\n\nconst CLOCK_PATTERN = /^(\\d{1,2}):(\\d{2})$/\n\nfunction clockToMinutes(value: string): number | null {\n const match = CLOCK_PATTERN.exec(value)\n if (!match) return null\n const hours = Number(match[1])\n const minutes = Number(match[2])\n if (hours > 23 || minutes > 59) return null\n return hours * 60 + minutes\n}\n\n/**\n * Screen 12 note 3 \u2014 the quick-add row's start time is prefilled with the end of\n * the previous entry of that day. The latest end wins rather than the last row in\n * document order, so an entry added out of sequence cannot drag the suggestion\n * backwards. Returns `null` for a day whose entries carry no clocks, in which\n * case the field simply opens empty.\n */\nexport function suggestNextStartClock(day: TimesheetDay | null | undefined): string | null {\n if (!day) return null\n let latest: { minutes: number; text: string } | null = null\n for (const entry of day.entries) {\n if (!entry.endText) continue\n const minutes = clockToMinutes(entry.endText)\n if (minutes === null) continue\n if (!latest || minutes > latest.minutes) latest = { minutes, text: entry.endText }\n }\n return latest?.text ?? null\n}\n\nexport type TimesheetDayIndex = ReadonlyMap<string, TimesheetDay>\n\nexport function indexDaysByDate(days: readonly TimesheetDay[]): TimesheetDayIndex {\n const index = new Map<string, TimesheetDay>()\n for (const day of days) index.set(day.date, day)\n return index\n}\n\n/**\n * The chip label inside a calendar cell \u2014 the project when we know it, the task\n * when we do not, and the description as a last resort. A cell that shows a bare\n * dash tells the user nothing, so something always renders.\n */\nexport function entryChipLabel(entry: TimesheetEntry, fallback: string): string {\n return entry.projectLabel ?? entry.taskTitle ?? entry.description ?? fallback\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }