@open-mercato/core 0.10.1-develop.7717.1.2befe9c634 → 0.10.1-develop.7721.1.b5c4a00a68

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 (384) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/staff_support_routing_rule/index.js +21 -0
  3. package/dist/generated/entities/staff_support_routing_rule/index.js.map +7 -0
  4. package/dist/generated/entities/staff_support_ticket/index.js +37 -0
  5. package/dist/generated/entities/staff_support_ticket/index.js.map +7 -0
  6. package/dist/generated/entities/staff_time_project/index.js +2 -0
  7. package/dist/generated/entities/staff_time_project/index.js.map +2 -2
  8. package/dist/generated/entities/staff_time_project_member/index.js +2 -0
  9. package/dist/generated/entities/staff_time_project_member/index.js.map +2 -2
  10. package/dist/generated/entities/staff_time_task/index.js +4 -0
  11. package/dist/generated/entities/staff_time_task/index.js.map +2 -2
  12. package/dist/generated/entities/staff_time_task_comment/index.js +9 -1
  13. package/dist/generated/entities/staff_time_task_comment/index.js.map +2 -2
  14. package/dist/generated/entities.ids.generated.js +2 -0
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +38 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/helpers/integration/auth.js +1 -0
  19. package/dist/helpers/integration/auth.js.map +2 -2
  20. package/dist/helpers/integration/communicationChannelsFixtures.js +20 -0
  21. package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
  22. package/dist/modules/catalog/api/bulk-delete/route.js +12 -2
  23. package/dist/modules/catalog/api/bulk-delete/route.js.map +2 -2
  24. package/dist/modules/communication_channels/api/post/test-seed/route.js +17 -3
  25. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
  26. package/dist/modules/communication_channels/lib/test-seed.js +38 -5
  27. package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
  28. package/dist/modules/messages/commands/messages.js +2 -3
  29. package/dist/modules/messages/commands/messages.js.map +2 -2
  30. package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js +2 -2
  31. package/dist/modules/portal/frontend/[orgSlug]/portal/dashboard/page.js.map +2 -2
  32. package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js +299 -0
  33. package/dist/modules/staff/api/portal/support-tickets/[id]/attachments/route.js.map +7 -0
  34. package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js +91 -0
  35. package/dist/modules/staff/api/portal/support-tickets/[id]/messages/route.js.map +7 -0
  36. package/dist/modules/staff/api/portal/support-tickets/[id]/route.js +146 -0
  37. package/dist/modules/staff/api/portal/support-tickets/[id]/route.js.map +7 -0
  38. package/dist/modules/staff/api/portal/support-tickets/options/route.js +60 -0
  39. package/dist/modules/staff/api/portal/support-tickets/options/route.js.map +7 -0
  40. package/dist/modules/staff/api/portal/support-tickets/route.js +220 -0
  41. package/dist/modules/staff/api/portal/support-tickets/route.js.map +7 -0
  42. package/dist/modules/staff/api/timesheets/settings/route.js +7 -1
  43. package/dist/modules/staff/api/timesheets/settings/route.js.map +2 -2
  44. package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js +122 -0
  45. package/dist/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.js.map +7 -0
  46. package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js +180 -0
  47. package/dist/modules/staff/api/timesheets/support-routing-rules/preview/route.js.map +7 -0
  48. package/dist/modules/staff/api/timesheets/support-routing-rules/route.js +147 -0
  49. package/dist/modules/staff/api/timesheets/support-routing-rules/route.js.map +7 -0
  50. package/dist/modules/staff/api/timesheets/support-tickets/options/route.js +133 -0
  51. package/dist/modules/staff/api/timesheets/support-tickets/options/route.js.map +7 -0
  52. package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js +33 -0
  53. package/dist/modules/staff/api/timesheets/tasks/[id]/claim/route.js.map +7 -0
  54. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +25 -7
  55. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +2 -2
  56. package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js +32 -0
  57. package/dist/modules/staff/api/timesheets/tasks/[id]/release/route.js.map +7 -0
  58. package/dist/modules/staff/api/timesheets/tasks/route.js +94 -47
  59. package/dist/modules/staff/api/timesheets/tasks/route.js.map +2 -2
  60. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +3 -0
  61. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +2 -2
  62. package/dist/modules/staff/api/timesheets/time-projects/route.js +3 -0
  63. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  64. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +1 -0
  65. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +2 -2
  66. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +54 -4
  67. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
  68. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js +21 -5
  69. package/dist/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.js.map +2 -2
  70. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js +319 -254
  71. package/dist/modules/staff/backend/staff/time-tracking/settings/page.js.map +2 -2
  72. package/dist/modules/staff/backend/staff/time-tracking/support/page.js +363 -0
  73. package/dist/modules/staff/backend/staff/time-tracking/support/page.js.map +7 -0
  74. package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js +18 -0
  75. package/dist/modules/staff/backend/staff/time-tracking/support/page.meta.js.map +7 -0
  76. package/dist/modules/staff/cli.js +27 -0
  77. package/dist/modules/staff/cli.js.map +2 -2
  78. package/dist/modules/staff/commands/index.js +3 -0
  79. package/dist/modules/staff/commands/index.js.map +2 -2
  80. package/dist/modules/staff/commands/shared.js +10 -1
  81. package/dist/modules/staff/commands/shared.js.map +2 -2
  82. package/dist/modules/staff/commands/support-routing-rules.js +505 -0
  83. package/dist/modules/staff/commands/support-routing-rules.js.map +7 -0
  84. package/dist/modules/staff/commands/support-tickets.js +513 -0
  85. package/dist/modules/staff/commands/support-tickets.js.map +7 -0
  86. package/dist/modules/staff/commands/timesheets-projects.js +72 -14
  87. package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
  88. package/dist/modules/staff/commands/timesheets-task-assignment.js +270 -0
  89. package/dist/modules/staff/commands/timesheets-task-assignment.js.map +7 -0
  90. package/dist/modules/staff/commands/timesheets-task-comments.js +58 -12
  91. package/dist/modules/staff/commands/timesheets-task-comments.js.map +2 -2
  92. package/dist/modules/staff/commands/timesheets-tasks.js +91 -9
  93. package/dist/modules/staff/commands/timesheets-tasks.js.map +3 -3
  94. package/dist/modules/staff/data/enrichers.js +141 -0
  95. package/dist/modules/staff/data/enrichers.js.map +2 -2
  96. package/dist/modules/staff/data/entities.js +143 -2
  97. package/dist/modules/staff/data/entities.js.map +2 -2
  98. package/dist/modules/staff/data/extensions.js +8 -0
  99. package/dist/modules/staff/data/extensions.js.map +2 -2
  100. package/dist/modules/staff/data/validators.js +34 -5
  101. package/dist/modules/staff/data/validators.js.map +2 -2
  102. package/dist/modules/staff/encryption.js +6 -0
  103. package/dist/modules/staff/encryption.js.map +2 -2
  104. package/dist/modules/staff/events.js +25 -0
  105. package/dist/modules/staff/events.js.map +2 -2
  106. package/dist/modules/staff/events.payloads.js +54 -0
  107. package/dist/modules/staff/events.payloads.js.map +2 -2
  108. package/dist/modules/staff/extension-points.js +1 -0
  109. package/dist/modules/staff/extension-points.js.map +2 -2
  110. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js +468 -0
  111. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.js.map +7 -0
  112. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js +12 -0
  113. package/dist/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.js.map +7 -0
  114. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js +316 -0
  115. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.js.map +7 -0
  116. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js +12 -0
  117. package/dist/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.js.map +7 -0
  118. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js +190 -0
  119. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.js.map +7 -0
  120. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js +19 -0
  121. package/dist/modules/staff/frontend/[orgSlug]/portal/support/page.meta.js.map +7 -0
  122. package/dist/modules/staff/index.js +1 -1
  123. package/dist/modules/staff/index.js.map +2 -2
  124. package/dist/modules/staff/lib/crud.js +2 -0
  125. package/dist/modules/staff/lib/crud.js.map +2 -2
  126. package/dist/modules/staff/lib/support/attachments.js +36 -0
  127. package/dist/modules/staff/lib/support/attachments.js.map +7 -0
  128. package/dist/modules/staff/lib/support/dictionaries.js +87 -0
  129. package/dist/modules/staff/lib/support/dictionaries.js.map +7 -0
  130. package/dist/modules/staff/lib/support/notifications.js +111 -0
  131. package/dist/modules/staff/lib/support/notifications.js.map +7 -0
  132. package/dist/modules/staff/lib/support/portalAttachments.js +100 -0
  133. package/dist/modules/staff/lib/support/portalAttachments.js.map +7 -0
  134. package/dist/modules/staff/lib/support/portalBroadcast.js +117 -0
  135. package/dist/modules/staff/lib/support/portalBroadcast.js.map +7 -0
  136. package/dist/modules/staff/lib/support/portalRoute.js +99 -0
  137. package/dist/modules/staff/lib/support/portalRoute.js.map +7 -0
  138. package/dist/modules/staff/lib/support/portalStatus.js +12 -0
  139. package/dist/modules/staff/lib/support/portalStatus.js.map +7 -0
  140. package/dist/modules/staff/lib/support/portalTickets.js +148 -0
  141. package/dist/modules/staff/lib/support/portalTickets.js.map +7 -0
  142. package/dist/modules/staff/lib/support/routing.js +81 -0
  143. package/dist/modules/staff/lib/support/routing.js.map +7 -0
  144. package/dist/modules/staff/lib/support/routingRuleDraft.js +25 -0
  145. package/dist/modules/staff/lib/support/routingRuleDraft.js.map +7 -0
  146. package/dist/modules/staff/lib/support/seedDefaults.js +114 -0
  147. package/dist/modules/staff/lib/support/seedDefaults.js.map +7 -0
  148. package/dist/modules/staff/lib/support/supportActivity.js +26 -0
  149. package/dist/modules/staff/lib/support/supportActivity.js.map +7 -0
  150. package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js +23 -0
  151. package/dist/modules/staff/lib/support-ui/PortalSupportNotLinked.js.map +7 -0
  152. package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js +112 -0
  153. package/dist/modules/staff/lib/support-ui/portalAttachmentValidation.js.map +7 -0
  154. package/dist/modules/staff/lib/support-ui/portalPendingUploads.js +45 -0
  155. package/dist/modules/staff/lib/support-ui/portalPendingUploads.js.map +7 -0
  156. package/dist/modules/staff/lib/support-ui/portalSupport.js +51 -0
  157. package/dist/modules/staff/lib/support-ui/portalSupport.js.map +7 -0
  158. package/dist/modules/staff/lib/time-tracking/access.js +3 -39
  159. package/dist/modules/staff/lib/time-tracking/access.js.map +2 -2
  160. package/dist/modules/staff/lib/time-tracking/listProjectAccess.js +54 -0
  161. package/dist/modules/staff/lib/time-tracking/listProjectAccess.js.map +7 -0
  162. package/dist/modules/staff/lib/time-tracking/portalRecipients.js +92 -2
  163. package/dist/modules/staff/lib/time-tracking/portalRecipients.js.map +2 -2
  164. package/dist/modules/staff/lib/time-tracking/projectAssignment.js +112 -0
  165. package/dist/modules/staff/lib/time-tracking/projectAssignment.js.map +7 -0
  166. package/dist/modules/staff/lib/time-tracking/settingKeys.js +14 -0
  167. package/dist/modules/staff/lib/time-tracking/settingKeys.js.map +2 -2
  168. package/dist/modules/staff/lib/time-tracking/settings.js +28 -1
  169. package/dist/modules/staff/lib/time-tracking/settings.js.map +2 -2
  170. package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js +143 -0
  171. package/dist/modules/staff/lib/time-tracking/taskAssignmentRoute.js.map +7 -0
  172. package/dist/modules/staff/lib/time-tracking/workRecipients.js +92 -0
  173. package/dist/modules/staff/lib/time-tracking/workRecipients.js.map +7 -0
  174. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js +32 -3
  175. package/dist/modules/staff/lib/time-tracking-ui/BoardFilterChips.js.map +2 -2
  176. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js +29 -0
  177. package/dist/modules/staff/lib/time-tracking-ui/KanbanBoard.js.map +2 -2
  178. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js +4 -0
  179. package/dist/modules/staff/lib/time-tracking-ui/KanbanCard.js.map +2 -2
  180. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js +141 -1
  181. package/dist/modules/staff/lib/time-tracking-ui/ProjectFormSections.js.map +2 -2
  182. package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js +153 -0
  183. package/dist/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.js.map +7 -0
  184. package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js +67 -0
  185. package/dist/modules/staff/lib/time-tracking-ui/SupportRequestPanel.js.map +7 -0
  186. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js +3 -1
  187. package/dist/modules/staff/lib/time-tracking-ui/TaskBoardScreen.js.map +2 -2
  188. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js +80 -17
  189. package/dist/modules/staff/lib/time-tracking-ui/TaskCommentThread.js.map +2 -2
  190. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js +230 -41
  191. package/dist/modules/staff/lib/time-tracking-ui/TaskDrawer.js.map +2 -2
  192. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js +21 -1
  193. package/dist/modules/staff/lib/time-tracking-ui/boardDirectory.js.map +2 -2
  194. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js +16 -4
  195. package/dist/modules/staff/lib/time-tracking-ui/boardFilters.js.map +2 -2
  196. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js +3 -1
  197. package/dist/modules/staff/lib/time-tracking-ui/kanbanBoardData.js.map +2 -2
  198. package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js +68 -0
  199. package/dist/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.js.map +7 -0
  200. package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js +7 -0
  201. package/dist/modules/staff/lib/time-tracking-ui/settingsTabs.js.map +7 -0
  202. package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js +50 -0
  203. package/dist/modules/staff/lib/time-tracking-ui/supportTicketData.js.map +7 -0
  204. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js +13 -1
  205. package/dist/modules/staff/lib/time-tracking-ui/taskDrawerData.js.map +2 -2
  206. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js +36 -2
  207. package/dist/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.js.map +2 -2
  208. package/dist/modules/staff/migrations/Migration20261009180543_staff.js +42 -0
  209. package/dist/modules/staff/migrations/Migration20261009180543_staff.js.map +7 -0
  210. package/dist/modules/staff/notifications.js +92 -0
  211. package/dist/modules/staff/notifications.js.map +2 -2
  212. package/dist/modules/staff/setup.js +6 -2
  213. package/dist/modules/staff/setup.js.map +2 -2
  214. package/dist/modules/staff/subscribers/support-portal-comment-created.js +26 -0
  215. package/dist/modules/staff/subscribers/support-portal-comment-created.js.map +7 -0
  216. package/dist/modules/staff/subscribers/support-portal-comment-deleted.js +26 -0
  217. package/dist/modules/staff/subscribers/support-portal-comment-deleted.js.map +7 -0
  218. package/dist/modules/staff/subscribers/support-portal-comment-updated.js +26 -0
  219. package/dist/modules/staff/subscribers/support-portal-comment-updated.js.map +7 -0
  220. package/dist/modules/staff/subscribers/support-portal-status-column-updated.js +24 -0
  221. package/dist/modules/staff/subscribers/support-portal-status-column-updated.js.map +7 -0
  222. package/dist/modules/staff/subscribers/support-portal-task-status-changed.js +25 -0
  223. package/dist/modules/staff/subscribers/support-portal-task-status-changed.js.map +7 -0
  224. package/dist/modules/staff/subscribers/support-portal-task-updated.js +25 -0
  225. package/dist/modules/staff/subscribers/support-portal-task-updated.js.map +7 -0
  226. package/dist/modules/staff/subscribers/support-ticket-created-notification.js +25 -0
  227. package/dist/modules/staff/subscribers/support-ticket-created-notification.js.map +7 -0
  228. package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js +25 -0
  229. package/dist/modules/staff/subscribers/support-ticket-customer-replied-notification.js.map +7 -0
  230. package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js +26 -0
  231. package/dist/modules/staff/subscribers/support-ticket-unnotified-clear.js.map +7 -0
  232. package/dist/modules/staff/subscribers/time-task-assignee-notification.js +83 -0
  233. package/dist/modules/staff/subscribers/time-task-assignee-notification.js.map +7 -0
  234. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js +112 -0
  235. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.client.js.map +7 -0
  236. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js +17 -0
  237. package/dist/modules/staff/widgets/injection/portal-support-tickets/widget.js.map +7 -0
  238. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js +870 -0
  239. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.js.map +7 -0
  240. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js +17 -0
  241. package/dist/modules/staff/widgets/injection/time-tracking-settings-support/widget.js.map +7 -0
  242. package/dist/modules/staff/widgets/injection-table.js +16 -1
  243. package/dist/modules/staff/widgets/injection-table.js.map +2 -2
  244. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +4 -18
  245. package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
  246. package/dist/modules/wms/components/backend/WmsLotDetailPage.js +4 -18
  247. package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
  248. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +4 -18
  249. package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
  250. package/dist/modules/wms/lib/inventoryCsvExport.js +19 -0
  251. package/dist/modules/wms/lib/inventoryCsvExport.js.map +7 -0
  252. package/generated/entities/staff_support_routing_rule/index.ts +9 -0
  253. package/generated/entities/staff_support_ticket/index.ts +17 -0
  254. package/generated/entities/staff_time_project/index.ts +1 -0
  255. package/generated/entities/staff_time_project_member/index.ts +1 -0
  256. package/generated/entities/staff_time_task/index.ts +2 -0
  257. package/generated/entities/staff_time_task_comment/index.ts +4 -0
  258. package/generated/entities.ids.generated.ts +2 -0
  259. package/generated/entity-fields-registry.ts +38 -0
  260. package/package.json +8 -8
  261. package/src/helpers/integration/auth.ts +1 -1
  262. package/src/helpers/integration/communicationChannelsFixtures.ts +60 -2
  263. package/src/modules/catalog/api/bulk-delete/route.ts +12 -2
  264. package/src/modules/communication_channels/api/post/test-seed/route.ts +29 -12
  265. package/src/modules/communication_channels/lib/test-seed.ts +49 -10
  266. package/src/modules/messages/commands/messages.ts +8 -10
  267. package/src/modules/portal/frontend/[orgSlug]/portal/dashboard/page.tsx +2 -2
  268. package/src/modules/staff/AGENTS.md +22 -6
  269. package/src/modules/staff/api/portal/support-tickets/[id]/attachments/route.ts +327 -0
  270. package/src/modules/staff/api/portal/support-tickets/[id]/messages/route.ts +94 -0
  271. package/src/modules/staff/api/portal/support-tickets/[id]/route.ts +160 -0
  272. package/src/modules/staff/api/portal/support-tickets/options/route.ts +60 -0
  273. package/src/modules/staff/api/portal/support-tickets/route.ts +253 -0
  274. package/src/modules/staff/api/timesheets/settings/route.ts +7 -1
  275. package/src/modules/staff/api/timesheets/support-routing-rules/fallback-project/route.ts +131 -0
  276. package/src/modules/staff/api/timesheets/support-routing-rules/preview/route.ts +248 -0
  277. package/src/modules/staff/api/timesheets/support-routing-rules/route.ts +150 -0
  278. package/src/modules/staff/api/timesheets/support-tickets/options/route.ts +181 -0
  279. package/src/modules/staff/api/timesheets/tasks/[id]/claim/route.ts +31 -0
  280. package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +25 -7
  281. package/src/modules/staff/api/timesheets/tasks/[id]/release/route.ts +30 -0
  282. package/src/modules/staff/api/timesheets/tasks/route.ts +119 -67
  283. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +3 -0
  284. package/src/modules/staff/api/timesheets/time-projects/route.ts +3 -0
  285. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +1 -0
  286. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +67 -2
  287. package/src/modules/staff/backend/staff/time-tracking/projects/projectFormConfig.ts +22 -3
  288. package/src/modules/staff/backend/staff/time-tracking/settings/page.tsx +405 -308
  289. package/src/modules/staff/backend/staff/time-tracking/support/page.meta.ts +14 -0
  290. package/src/modules/staff/backend/staff/time-tracking/support/page.tsx +428 -0
  291. package/src/modules/staff/cli.ts +28 -0
  292. package/src/modules/staff/commands/index.ts +3 -0
  293. package/src/modules/staff/commands/shared.ts +22 -1
  294. package/src/modules/staff/commands/support-routing-rules.ts +595 -0
  295. package/src/modules/staff/commands/support-tickets.ts +580 -0
  296. package/src/modules/staff/commands/timesheets-projects.ts +84 -13
  297. package/src/modules/staff/commands/timesheets-task-assignment.ts +319 -0
  298. package/src/modules/staff/commands/timesheets-task-comments.ts +70 -15
  299. package/src/modules/staff/commands/timesheets-tasks.ts +106 -15
  300. package/src/modules/staff/data/enrichers.ts +203 -0
  301. package/src/modules/staff/data/entities.ts +133 -2
  302. package/src/modules/staff/data/extensions.ts +9 -1
  303. package/src/modules/staff/data/validators.ts +36 -0
  304. package/src/modules/staff/encryption.ts +6 -0
  305. package/src/modules/staff/events.payloads.ts +87 -1
  306. package/src/modules/staff/events.ts +26 -0
  307. package/src/modules/staff/extension-points.ts +1 -0
  308. package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.meta.ts +10 -0
  309. package/src/modules/staff/frontend/[orgSlug]/portal/support/[id]/page.tsx +553 -0
  310. package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.meta.ts +10 -0
  311. package/src/modules/staff/frontend/[orgSlug]/portal/support/new/page.tsx +346 -0
  312. package/src/modules/staff/frontend/[orgSlug]/portal/support/page.meta.ts +17 -0
  313. package/src/modules/staff/frontend/[orgSlug]/portal/support/page.tsx +253 -0
  314. package/src/modules/staff/i18n/de.json +291 -0
  315. package/src/modules/staff/i18n/en.json +291 -0
  316. package/src/modules/staff/i18n/es.json +291 -0
  317. package/src/modules/staff/i18n/ko.json +291 -0
  318. package/src/modules/staff/i18n/pl.json +291 -0
  319. package/src/modules/staff/index.ts +1 -1
  320. package/src/modules/staff/lib/crud.ts +2 -1
  321. package/src/modules/staff/lib/support/attachments.ts +43 -0
  322. package/src/modules/staff/lib/support/dictionaries.ts +120 -0
  323. package/src/modules/staff/lib/support/notifications.ts +138 -0
  324. package/src/modules/staff/lib/support/portalAttachments.ts +140 -0
  325. package/src/modules/staff/lib/support/portalBroadcast.ts +161 -0
  326. package/src/modules/staff/lib/support/portalRoute.ts +108 -0
  327. package/src/modules/staff/lib/support/portalStatus.ts +15 -0
  328. package/src/modules/staff/lib/support/portalTickets.ts +233 -0
  329. package/src/modules/staff/lib/support/routing.ts +117 -0
  330. package/src/modules/staff/lib/support/routingRuleDraft.ts +45 -0
  331. package/src/modules/staff/lib/support/seedDefaults.ts +151 -0
  332. package/src/modules/staff/lib/support/supportActivity.ts +39 -0
  333. package/src/modules/staff/lib/support-ui/PortalSupportNotLinked.tsx +20 -0
  334. package/src/modules/staff/lib/support-ui/portalAttachmentValidation.ts +125 -0
  335. package/src/modules/staff/lib/support-ui/portalPendingUploads.ts +49 -0
  336. package/src/modules/staff/lib/support-ui/portalSupport.ts +116 -0
  337. package/src/modules/staff/lib/time-tracking/access.ts +2 -62
  338. package/src/modules/staff/lib/time-tracking/listProjectAccess.ts +78 -0
  339. package/src/modules/staff/lib/time-tracking/portalRecipients.ts +173 -5
  340. package/src/modules/staff/lib/time-tracking/projectAssignment.ts +172 -0
  341. package/src/modules/staff/lib/time-tracking/settingKeys.ts +11 -0
  342. package/src/modules/staff/lib/time-tracking/settings.ts +46 -1
  343. package/src/modules/staff/lib/time-tracking/taskAssignmentRoute.ts +165 -0
  344. package/src/modules/staff/lib/time-tracking/workRecipients.ts +183 -0
  345. package/src/modules/staff/lib/time-tracking-ui/BoardFilterChips.tsx +36 -1
  346. package/src/modules/staff/lib/time-tracking-ui/KanbanBoard.tsx +30 -0
  347. package/src/modules/staff/lib/time-tracking-ui/KanbanCard.tsx +9 -0
  348. package/src/modules/staff/lib/time-tracking-ui/ProjectFormSections.tsx +185 -6
  349. package/src/modules/staff/lib/time-tracking-ui/SupportAttachmentsSection.tsx +188 -0
  350. package/src/modules/staff/lib/time-tracking-ui/SupportRequestPanel.tsx +102 -0
  351. package/src/modules/staff/lib/time-tracking-ui/TaskBoardScreen.tsx +2 -0
  352. package/src/modules/staff/lib/time-tracking-ui/TaskCommentThread.tsx +105 -22
  353. package/src/modules/staff/lib/time-tracking-ui/TaskDrawer.tsx +278 -43
  354. package/src/modules/staff/lib/time-tracking-ui/boardDirectory.ts +21 -0
  355. package/src/modules/staff/lib/time-tracking-ui/boardFilters.ts +16 -2
  356. package/src/modules/staff/lib/time-tracking-ui/kanbanBoardData.ts +4 -0
  357. package/src/modules/staff/lib/time-tracking-ui/projectDefaultAssignee.ts +117 -0
  358. package/src/modules/staff/lib/time-tracking-ui/settingsTabs.ts +17 -0
  359. package/src/modules/staff/lib/time-tracking-ui/supportTicketData.ts +71 -0
  360. package/src/modules/staff/lib/time-tracking-ui/taskDrawerData.ts +15 -0
  361. package/src/modules/staff/lib/time-tracking-ui/timeTrackingSettingsForm.ts +48 -1
  362. package/src/modules/staff/migrations/.snapshot-open-mercato.json +714 -0
  363. package/src/modules/staff/migrations/Migration20261009180543_staff.ts +50 -0
  364. package/src/modules/staff/notifications.ts +92 -0
  365. package/src/modules/staff/setup.ts +6 -2
  366. package/src/modules/staff/subscribers/support-portal-comment-created.ts +35 -0
  367. package/src/modules/staff/subscribers/support-portal-comment-deleted.ts +35 -0
  368. package/src/modules/staff/subscribers/support-portal-comment-updated.ts +35 -0
  369. package/src/modules/staff/subscribers/support-portal-status-column-updated.ts +36 -0
  370. package/src/modules/staff/subscribers/support-portal-task-status-changed.ts +34 -0
  371. package/src/modules/staff/subscribers/support-portal-task-updated.ts +34 -0
  372. package/src/modules/staff/subscribers/support-ticket-created-notification.ts +27 -0
  373. package/src/modules/staff/subscribers/support-ticket-customer-replied-notification.ts +27 -0
  374. package/src/modules/staff/subscribers/support-ticket-unnotified-clear.ts +29 -0
  375. package/src/modules/staff/subscribers/time-task-assignee-notification.ts +102 -0
  376. package/src/modules/staff/widgets/injection/portal-support-tickets/widget.client.tsx +151 -0
  377. package/src/modules/staff/widgets/injection/portal-support-tickets/widget.ts +16 -0
  378. package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.client.tsx +1058 -0
  379. package/src/modules/staff/widgets/injection/time-tracking-settings-support/widget.ts +17 -0
  380. package/src/modules/staff/widgets/injection-table.ts +15 -0
  381. package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +4 -20
  382. package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +4 -20
  383. package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +4 -19
  384. package/src/modules/wms/lib/inventoryCsvExport.ts +18 -0
@@ -0,0 +1,117 @@
1
+ import { resolveAssignmentState } from './projectTeamAssignment'
2
+
3
+ export const DEFAULT_ASSIGNEE_PAGE_SIZE = 100
4
+ export const DEFAULT_ASSIGNEE_MAX_PAGES = 20
5
+
6
+ export type ProjectMemberRow = {
7
+ id?: unknown
8
+ staffMemberId?: unknown
9
+ staff_member_id?: unknown
10
+ status?: unknown
11
+ assigned_start_date?: unknown
12
+ assignedStartDate?: unknown
13
+ assigned_end_date?: unknown
14
+ assignedEndDate?: unknown
15
+ }
16
+
17
+ export type ProjectMembershipPage = {
18
+ items: ProjectMemberRow[]
19
+ totalPages: number | null
20
+ }
21
+
22
+ export type ProjectMembershipCollection = {
23
+ rows: ProjectMemberRow[]
24
+ truncated: boolean
25
+ }
26
+
27
+ export type DefaultAssigneeCandidate = {
28
+ staffMemberId: string
29
+ active: boolean
30
+ }
31
+
32
+ function readString(value: unknown): string | null {
33
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null
34
+ }
35
+
36
+ export function readMembershipStaffMemberId(row: ProjectMemberRow): string | null {
37
+ return readString(row.staffMemberId) ?? readString(row.staff_member_id)
38
+ }
39
+
40
+ /**
41
+ * Whether a membership can still receive a portal ticket as the default assignee —
42
+ * the browser twin of `resolveUsableDefaultAssignee`: an `active` membership inside
43
+ * its assignment window plus the tenant's grace days.
44
+ */
45
+ export function isUsableDefaultAssigneeMembership(row: ProjectMemberRow, graceDays: number, now: Date = new Date()): boolean {
46
+ if (readString(row.status) !== 'active') return false
47
+ const startDate = readString(row.assignedStartDate) ?? readString(row.assigned_start_date)
48
+ const endDate = readString(row.assignedEndDate) ?? readString(row.assigned_end_date)
49
+ return resolveAssignmentState({ startDate, endDate }, graceDays, now) === 'active'
50
+ }
51
+
52
+ export type ProjectMembershipPageResponse = {
53
+ ok: boolean
54
+ result?: { items?: unknown; totalPages?: unknown } | null
55
+ }
56
+
57
+ /**
58
+ * Reads one employees page, refusing anything but a successful response with a
59
+ * row list: an error page carries no rows and no total, and reading it as an empty
60
+ * last page would mark every member beyond it as gone.
61
+ */
62
+ export function readProjectMembershipPage(response: ProjectMembershipPageResponse): ProjectMembershipPage {
63
+ if (!response.ok) throw new Error('[internal] project membership page request failed')
64
+ const items = response.result?.items
65
+ if (!Array.isArray(items)) throw new Error('[internal] project membership page has no rows')
66
+ const totalPages = typeof response.result?.totalPages === 'number' ? response.result.totalPages : null
67
+ const rows = items.filter((item): item is ProjectMemberRow => typeof item === 'object' && item !== null)
68
+ return { items: rows, totalPages }
69
+ }
70
+
71
+ export async function collectProjectMemberships(
72
+ fetchPage: (page: number) => Promise<ProjectMembershipPage>,
73
+ options: { pageSize?: number; maxPages?: number } = {},
74
+ ): Promise<ProjectMembershipCollection> {
75
+ const pageSize = options.pageSize ?? DEFAULT_ASSIGNEE_PAGE_SIZE
76
+ const maxPages = options.maxPages ?? DEFAULT_ASSIGNEE_MAX_PAGES
77
+ const rows: ProjectMemberRow[] = []
78
+ for (let page = 1; page <= maxPages; page += 1) {
79
+ const result = await fetchPage(page)
80
+ rows.push(...result.items)
81
+ const lastPage = result.totalPages !== null ? page >= result.totalPages : result.items.length < pageSize
82
+ if (lastPage || result.items.length === 0) return { rows, truncated: false }
83
+ }
84
+ return { rows, truncated: true }
85
+ }
86
+
87
+ export function classifyDefaultAssigneeCandidates(
88
+ rows: ProjectMemberRow[],
89
+ graceDays: number,
90
+ now: Date = new Date(),
91
+ ): DefaultAssigneeCandidate[] {
92
+ const byMember = new Map<string, boolean>()
93
+ for (const row of rows) {
94
+ const staffMemberId = readMembershipStaffMemberId(row)
95
+ if (!staffMemberId) continue
96
+ const active = isUsableDefaultAssigneeMembership(row, graceDays, now)
97
+ byMember.set(staffMemberId, (byMember.get(staffMemberId) ?? false) || active)
98
+ }
99
+ return Array.from(byMember, ([staffMemberId, active]) => ({ staffMemberId, active }))
100
+ }
101
+
102
+ export function chunkIds(ids: string[], size: number = DEFAULT_ASSIGNEE_PAGE_SIZE): string[][] {
103
+ const batches: string[][] = []
104
+ for (let index = 0; index < ids.length; index += size) batches.push(ids.slice(index, index + size))
105
+ return batches
106
+ }
107
+
108
+ export function resolveSelectedDefaultAssignee(
109
+ candidates: DefaultAssigneeCandidate[],
110
+ value: string | null,
111
+ truncated: boolean,
112
+ ): { candidate: DefaultAssigneeCandidate | null; unusable: boolean } {
113
+ if (!value) return { candidate: null, unusable: false }
114
+ const candidate = candidates.find((entry) => entry.staffMemberId === value) ?? null
115
+ if (candidate) return { candidate, unusable: !candidate.active }
116
+ return { candidate: null, unusable: !truncated }
117
+ }
@@ -0,0 +1,17 @@
1
+ import type { TimeTrackingSettings } from '../time-tracking/settings'
2
+
3
+ export const TIME_TRACKING_SETTINGS_GENERAL_TAB = 'general'
4
+ export const TIME_TRACKING_SETTINGS_TAB_PARAM = 'tab'
5
+
6
+ /**
7
+ * Context of the `staff.time_tracking.settings:tabs` spot. A tab owns its saves and does
8
+ * not sit under the page's Save bar. When it writes the settings record itself it builds
9
+ * the body from `settings` (the last saved record, never the page's unsaved draft) and
10
+ * hands the response to `onSettingsSaved`, which rebases the page draft onto it.
11
+ */
12
+ export type TimeTrackingSettingsTabContext = {
13
+ moduleId: string
14
+ canManage: boolean
15
+ settings: TimeTrackingSettings
16
+ onSettingsSaved: (settings: TimeTrackingSettings) => void
17
+ }
@@ -0,0 +1,71 @@
1
+ import type { StatusBadgeVariant } from '@open-mercato/ui/primitives/status-badge'
2
+ import type { BoardApiRow } from './kanbanBoardData'
3
+
4
+ export type SupportPortalStatus = 'received' | 'in_progress' | 'resolved'
5
+
6
+ export type SupportTicketView = {
7
+ id: string
8
+ supportReference: string
9
+ categoryValue: string
10
+ categoryLabel: string
11
+ routedVia: 'category' | 'fallback'
12
+ portalStatus: SupportPortalStatus
13
+ customerName: string | null
14
+ customerKind: string | null
15
+ reporterName: string | null
16
+ reportedByCustomerUserId: string | null
17
+ unnotifiedAt: string | null
18
+ requestSubject: string | null
19
+ requestBody: string | null
20
+ }
21
+
22
+ export const SUPPORT_PORTAL_STATUS_VARIANT: Record<SupportPortalStatus, StatusBadgeVariant> = {
23
+ received: 'info',
24
+ in_progress: 'warning',
25
+ resolved: 'success',
26
+ }
27
+
28
+ function isRecord(value: unknown): value is Record<string, unknown> {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
30
+ }
31
+
32
+ function readText(source: Record<string, unknown> | null | undefined, key: string): string | null {
33
+ const value = source?.[key]
34
+ return typeof value === 'string' && value.length > 0 ? value : null
35
+ }
36
+
37
+ function readPortalStatus(value: unknown): SupportPortalStatus {
38
+ return value === 'resolved' || value === 'in_progress' ? value : 'received'
39
+ }
40
+
41
+ /** Reads the `_staffSupport.ticket` enrichment off a tasks API row. Internal tasks answer `null`. */
42
+ export function readSupportTicket(row: BoardApiRow | null | undefined): SupportTicketView | null {
43
+ if (!row) return null
44
+ const enrichment = (row as Record<string, unknown>)._staffSupport
45
+ if (!isRecord(enrichment)) return null
46
+ const ticket = enrichment.ticket
47
+ if (!isRecord(ticket)) return null
48
+ const id = readText(ticket, 'id')
49
+ const supportReference = readText(ticket, 'supportReference')
50
+ if (!id || !supportReference) return null
51
+ const category = isRecord(ticket.category) ? ticket.category : null
52
+ const customer = isRecord(ticket.customerSnapshot) ? ticket.customerSnapshot : null
53
+ const request = isRecord(ticket.customerRequest) ? ticket.customerRequest : null
54
+ return {
55
+ id,
56
+ supportReference,
57
+ categoryValue: readText(category, 'value') ?? '',
58
+ categoryLabel: readText(category, 'label') ?? readText(category, 'value') ?? '',
59
+ routedVia: ticket.routedVia === 'category' ? 'category' : 'fallback',
60
+ portalStatus: readPortalStatus(ticket.portalStatus),
61
+ customerName: readText(customer, 'displayName'),
62
+ customerKind: readText(customer, 'kind'),
63
+ reporterName: readText(customer, 'reporterDisplayName'),
64
+ reportedByCustomerUserId: readText(ticket, 'reportedByCustomerUserId'),
65
+ unnotifiedAt: readText(ticket, 'unnotifiedAt'),
66
+ requestSubject: readText(request, 'subject'),
67
+ requestBody: typeof request?.body === 'string' ? (request.body as string) : null,
68
+ }
69
+ }
70
+
71
+ export const SUPPORT_ACTIVITY_EVENT = 'staff.support_ticket.activity_recorded'
@@ -15,6 +15,8 @@
15
15
  import { formatDuration } from '../time-tracking/duration'
16
16
  import { readNumber, readString, type BoardApiRow, type BoardStatus } from './kanbanBoardData'
17
17
 
18
+ export const TASK_DRAWER_QUERY_ROOT = ['staff', 'time-tracking', 'task-drawer'] as const
19
+
18
20
  export type DrawerComment = {
19
21
  id: string
20
22
  body: string
@@ -22,6 +24,9 @@ export type DrawerComment = {
22
24
  authorName: string | null
23
25
  authorEmail: string | null
24
26
  createdAt: string | null
27
+ visibility: 'internal' | 'customer'
28
+ authorKind: 'staff' | 'customer'
29
+ updatedAt: string | null
25
30
  }
26
31
 
27
32
  export type DrawerEntry = {
@@ -57,6 +62,9 @@ export function toDrawerComment(row: BoardApiRow): DrawerComment | null {
57
62
  authorName: readString(row, 'authorName', 'author_name'),
58
63
  authorEmail: readString(row, 'authorEmail', 'author_email'),
59
64
  createdAt: readString(row, 'createdAt', 'created_at'),
65
+ visibility: readString(row, 'visibility') === 'customer' ? 'customer' : 'internal',
66
+ authorKind: readString(row, 'authorKind', 'author_kind') === 'customer' ? 'customer' : 'staff',
67
+ updatedAt: readString(row, 'updatedAt', 'updated_at'),
60
68
  }
61
69
  }
62
70
 
@@ -192,3 +200,10 @@ export function buildEntryClocks({ date, startClock, endClock, minutes }: EntryC
192
200
  endedAt: `${date}T${minutesToClock(resolvedEnd)}`,
193
201
  }
194
202
  }
203
+
204
+ export const TASK_ASSIGNMENT_CHANGED_EVENT = 'staff.timesheets.time_task.assignee_changed'
205
+
206
+ export function isAssignmentEventForTask(payload: unknown, taskId: string): boolean {
207
+ if (!taskId || typeof payload !== 'object' || payload === null) return false
208
+ return (payload as { id?: unknown }).id === taskId
209
+ }
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { formatDuration } from '../time-tracking/duration'
18
18
  import { roundMinutes, type RoundingSettings, type RoundingUnitMinutes } from '../time-tracking/rounding'
19
- import { contributedTimeTrackingSettingKeys } from '../time-tracking/settingKeys'
19
+ import { DEFAULT_SUPPORT_REFERENCE_PREFIX, contributedTimeTrackingSettingKeys } from '../time-tracking/settingKeys'
20
20
  import { readTimeTrackingSettingValue, type TimeTrackingSettings } from '../time-tracking/settings'
21
21
 
22
22
  export const ROUNDING_UNIT_OPTIONS: readonly RoundingUnitMinutes[] = [0, 5, 10, 15]
@@ -65,6 +65,8 @@ export type TimeTrackingSettingsDraft = {
65
65
  warningsOverlap: boolean
66
66
  warningsRunningTimer: boolean
67
67
  assignmentGraceDaysText: string
68
+ /** Edited on the Support settings tab; carried through so this page's Save never resets it. */
69
+ supportReferencePrefix: string
68
70
  /**
69
71
  * EP-42 — every contributed setting key, by its `<group>.<key>` id, carried through
70
72
  * the draft untouched so the page's own Save round-trips a contribution it knows
@@ -86,6 +88,7 @@ export function toSettingsDraft(settings: TimeTrackingSettings): TimeTrackingSet
86
88
  warningsOverlap: settings.warnings.overlap,
87
89
  warningsRunningTimer: settings.warnings.runningTimer,
88
90
  assignmentGraceDaysText: String(settings.access.assignmentGraceDays),
91
+ supportReferencePrefix: settings.support?.referencePrefix ?? DEFAULT_SUPPORT_REFERENCE_PREFIX,
89
92
  contributed: Object.fromEntries(
90
93
  contributedTimeTrackingSettingKeys().map((entry) => [
91
94
  entry.id,
@@ -139,6 +142,7 @@ export function toSettingsPayload(draft: TimeTrackingSettingsDraft): TimeTrackin
139
142
  targets: { dailyHours },
140
143
  warnings: { overlap: draft.warningsOverlap, runningTimer: draft.warningsRunningTimer },
141
144
  access: { assignmentGraceDays },
145
+ support: { referencePrefix: draft.supportReferencePrefix },
142
146
  }
143
147
  for (const entry of contributedTimeTrackingSettingKeys()) {
144
148
  const group = (payload[entry.group] ?? {}) as Record<string, unknown>
@@ -148,6 +152,49 @@ export function toSettingsPayload(draft: TimeTrackingSettingsDraft): TimeTrackin
148
152
  return payload
149
153
  }
150
154
 
155
+ /**
156
+ * A settings tab that saves the record itself moves the stored baseline under the
157
+ * page's draft. Rebase the draft onto the new record: a field the user has not touched
158
+ * takes the saved value, an edited field keeps the edit, so the page's Save neither
159
+ * reverts the tab's write nor drops pending changes.
160
+ */
161
+ export function rebaseSettingsDraft(
162
+ draft: TimeTrackingSettingsDraft,
163
+ previousBaseline: TimeTrackingSettingsDraft,
164
+ nextBaseline: TimeTrackingSettingsDraft,
165
+ ): TimeTrackingSettingsDraft {
166
+ const pick = <TValue>(current: TValue, previous: TValue, next: TValue): TValue =>
167
+ Object.is(current, previous) ? next : current
168
+ const contributed: Record<string, unknown> = { ...nextBaseline.contributed }
169
+ for (const [id, value] of Object.entries(draft.contributed)) {
170
+ contributed[id] = pick(value, previousBaseline.contributed[id], nextBaseline.contributed[id])
171
+ }
172
+ return {
173
+ roundingUnitMinutes: pick(draft.roundingUnitMinutes, previousBaseline.roundingUnitMinutes, nextBaseline.roundingUnitMinutes),
174
+ roundingDirection: pick(draft.roundingDirection, previousBaseline.roundingDirection, nextBaseline.roundingDirection),
175
+ defaultsBillable: pick(draft.defaultsBillable, previousBaseline.defaultsBillable, nextBaseline.defaultsBillable),
176
+ defaultsChainStartFromPreviousEnd: pick(
177
+ draft.defaultsChainStartFromPreviousEnd,
178
+ previousBaseline.defaultsChainStartFromPreviousEnd,
179
+ nextBaseline.defaultsChainStartFromPreviousEnd,
180
+ ),
181
+ dailyHoursText: pick(draft.dailyHoursText, previousBaseline.dailyHoursText, nextBaseline.dailyHoursText),
182
+ warningsOverlap: pick(draft.warningsOverlap, previousBaseline.warningsOverlap, nextBaseline.warningsOverlap),
183
+ warningsRunningTimer: pick(draft.warningsRunningTimer, previousBaseline.warningsRunningTimer, nextBaseline.warningsRunningTimer),
184
+ assignmentGraceDaysText: pick(
185
+ draft.assignmentGraceDaysText,
186
+ previousBaseline.assignmentGraceDaysText,
187
+ nextBaseline.assignmentGraceDaysText,
188
+ ),
189
+ supportReferencePrefix: pick(
190
+ draft.supportReferencePrefix,
191
+ previousBaseline.supportReferencePrefix,
192
+ nextBaseline.supportReferencePrefix,
193
+ ),
194
+ contributed,
195
+ }
196
+ }
197
+
151
198
  export function isSettingsDraftDirty(
152
199
  draft: TimeTrackingSettingsDraft,
153
200
  baseline: TimeTrackingSettingsDraft,