@open-mercato/core 0.6.4-develop.4217.1.c9aa050183 → 0.6.4-develop.4239.1.4a264a5828

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 (408) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/staff_time_entry/index.js +37 -0
  3. package/dist/generated/entities/staff_time_entry/index.js.map +7 -0
  4. package/dist/generated/entities/staff_time_entry_segment/index.js +23 -0
  5. package/dist/generated/entities/staff_time_entry_segment/index.js.map +7 -0
  6. package/dist/generated/entities/staff_time_project/index.js +35 -0
  7. package/dist/generated/entities/staff_time_project/index.js.map +7 -0
  8. package/dist/generated/entities/staff_time_project_member/index.js +29 -0
  9. package/dist/generated/entities/staff_time_project_member/index.js.map +7 -0
  10. package/dist/generated/entities.ids.generated.js +5 -1
  11. package/dist/generated/entities.ids.generated.js.map +2 -2
  12. package/dist/generated/entity-fields-registry.js +64 -0
  13. package/dist/generated/entity-fields-registry.js.map +2 -2
  14. package/dist/helpers/integration/timesheetFixtures.js +50 -0
  15. package/dist/helpers/integration/timesheetFixtures.js.map +7 -0
  16. package/dist/modules/attachments/api/library/[id]/route.js +20 -16
  17. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  18. package/dist/modules/attachments/api/route.js +18 -14
  19. package/dist/modules/attachments/api/route.js.map +2 -2
  20. package/dist/modules/auth/api/roles/acl/route.js +10 -4
  21. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  22. package/dist/modules/auth/api/sidebar/preferences/route.js +27 -20
  23. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  24. package/dist/modules/auth/api/users/acl/route.js +16 -11
  25. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  26. package/dist/modules/auth/commands/users.js +87 -71
  27. package/dist/modules/auth/commands/users.js.map +2 -2
  28. package/dist/modules/auth/services/sidebarPreferencesService.js +39 -30
  29. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  30. package/dist/modules/business_rules/backend/logs/[id]/page.js +24 -5
  31. package/dist/modules/business_rules/backend/logs/[id]/page.js.map +2 -2
  32. package/dist/modules/catalog/api/offers/route.js +15 -5
  33. package/dist/modules/catalog/api/offers/route.js.map +2 -2
  34. package/dist/modules/catalog/commands/categories.js +61 -12
  35. package/dist/modules/catalog/commands/categories.js.map +2 -2
  36. package/dist/modules/catalog/commands/products.js +79 -54
  37. package/dist/modules/catalog/commands/products.js.map +2 -2
  38. package/dist/modules/catalog/commands/variants.js +29 -16
  39. package/dist/modules/catalog/commands/variants.js.map +2 -2
  40. package/dist/modules/currencies/backend/currencies/[id]/page.js +19 -2
  41. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  42. package/dist/modules/currencies/commands/currencies.js +15 -8
  43. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  44. package/dist/modules/customer_accounts/api/admin/users.js +27 -26
  45. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  46. package/dist/modules/customer_accounts/api/password/reset-confirm.js +5 -5
  47. package/dist/modules/customer_accounts/api/password/reset-confirm.js.map +2 -2
  48. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +11 -10
  49. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
  50. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +27 -7
  51. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  52. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +27 -7
  53. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  54. package/dist/modules/customers/backend/customers/people/[id]/page.js +29 -8
  55. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  56. package/dist/modules/customers/commands/addresses.js +35 -21
  57. package/dist/modules/customers/commands/addresses.js.map +2 -2
  58. package/dist/modules/customers/commands/companies.js +163 -162
  59. package/dist/modules/customers/commands/companies.js.map +2 -2
  60. package/dist/modules/customers/commands/deals.js +3 -4
  61. package/dist/modules/customers/commands/deals.js.map +2 -2
  62. package/dist/modules/customers/commands/interactions.js +19 -22
  63. package/dist/modules/customers/commands/interactions.js.map +2 -2
  64. package/dist/modules/customers/commands/people.js +18 -15
  65. package/dist/modules/customers/commands/people.js.map +2 -2
  66. package/dist/modules/customers/commands/personCompanyLinks.js +105 -94
  67. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  68. package/dist/modules/customers/commands/pipeline-stages.js +30 -23
  69. package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
  70. package/dist/modules/customers/commands/pipelines.js +27 -20
  71. package/dist/modules/customers/commands/pipelines.js.map +2 -2
  72. package/dist/modules/customers/commands/tags.js +13 -5
  73. package/dist/modules/customers/commands/tags.js.map +2 -2
  74. package/dist/modules/dashboards/api/users/widgets/route.js +0 -1
  75. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  76. package/dist/modules/dashboards/api/widgets/data/route.js +29 -1
  77. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  78. package/dist/modules/data_sync/lib/sync-engine.js +4 -4
  79. package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
  80. package/dist/modules/data_sync/lib/sync-run-service.js +51 -27
  81. package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
  82. package/dist/modules/directory/commands/organizations.js +192 -158
  83. package/dist/modules/directory/commands/organizations.js.map +3 -3
  84. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +22 -16
  85. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
  86. package/dist/modules/messages/commands/messages.js +77 -75
  87. package/dist/modules/messages/commands/messages.js.map +2 -2
  88. package/dist/modules/messages/commands/shared.js +132 -132
  89. package/dist/modules/messages/commands/shared.js.map +2 -2
  90. package/dist/modules/perspectives/api/[tableId]/route.js +37 -26
  91. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  92. package/dist/modules/progress/acl.js +8 -4
  93. package/dist/modules/progress/acl.js.map +2 -2
  94. package/dist/modules/resources/commands/resources.js +125 -117
  95. package/dist/modules/resources/commands/resources.js.map +2 -2
  96. package/dist/modules/resources/commands/tags.js +7 -3
  97. package/dist/modules/resources/commands/tags.js.map +2 -2
  98. package/dist/modules/sales/api/quotes/send/route.js +12 -11
  99. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  100. package/dist/modules/sales/commands/documents.js +629 -478
  101. package/dist/modules/sales/commands/documents.js.map +2 -2
  102. package/dist/modules/sales/commands/payments.js +146 -146
  103. package/dist/modules/sales/commands/payments.js.map +2 -2
  104. package/dist/modules/sales/commands/returns.js +68 -60
  105. package/dist/modules/sales/commands/returns.js.map +2 -2
  106. package/dist/modules/staff/acl.js +10 -1
  107. package/dist/modules/staff/acl.js.map +2 -2
  108. package/dist/modules/staff/analytics.js +33 -0
  109. package/dist/modules/staff/analytics.js.map +7 -0
  110. package/dist/modules/staff/api/guards.js +31 -0
  111. package/dist/modules/staff/api/guards.js.map +7 -0
  112. package/dist/modules/staff/api/interceptors.js +96 -0
  113. package/dist/modules/staff/api/interceptors.js.map +7 -0
  114. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +170 -0
  115. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +7 -0
  116. package/dist/modules/staff/api/timesheets/my-projects/route.js +103 -0
  117. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +7 -0
  118. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +147 -0
  119. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +7 -0
  120. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +171 -0
  121. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +7 -0
  122. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +180 -0
  123. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +7 -0
  124. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +155 -0
  125. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +7 -0
  126. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +173 -0
  127. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +7 -0
  128. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +260 -0
  129. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +7 -0
  130. package/dist/modules/staff/api/timesheets/time-entries/route.js +188 -0
  131. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +7 -0
  132. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +159 -0
  133. package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +7 -0
  134. package/dist/modules/staff/api/timesheets/time-projects/route.js +230 -0
  135. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +7 -0
  136. package/dist/modules/staff/backend/staff/timesheets/page.js +710 -0
  137. package/dist/modules/staff/backend/staff/timesheets/page.js.map +7 -0
  138. package/dist/modules/staff/backend/staff/timesheets/page.meta.js +22 -0
  139. package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +7 -0
  140. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +125 -0
  141. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +7 -0
  142. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +16 -0
  143. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +7 -0
  144. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +418 -0
  145. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +7 -0
  146. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +16 -0
  147. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +7 -0
  148. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +79 -0
  149. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +7 -0
  150. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +16 -0
  151. package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +7 -0
  152. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +602 -0
  153. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +7 -0
  154. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +25 -0
  155. package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +7 -0
  156. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +123 -0
  157. package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +7 -0
  158. package/dist/modules/staff/cli.js +38 -1
  159. package/dist/modules/staff/cli.js.map +2 -2
  160. package/dist/modules/staff/commands/index.js +2 -0
  161. package/dist/modules/staff/commands/index.js.map +2 -2
  162. package/dist/modules/staff/commands/leave-requests.js +30 -28
  163. package/dist/modules/staff/commands/leave-requests.js.map +3 -3
  164. package/dist/modules/staff/commands/team-members.js +21 -20
  165. package/dist/modules/staff/commands/team-members.js.map +2 -2
  166. package/dist/modules/staff/commands/timesheets-entries.js +409 -0
  167. package/dist/modules/staff/commands/timesheets-entries.js.map +7 -0
  168. package/dist/modules/staff/commands/timesheets-projects.js +618 -0
  169. package/dist/modules/staff/commands/timesheets-projects.js.map +7 -0
  170. package/dist/modules/staff/data/enrichers.js +104 -0
  171. package/dist/modules/staff/data/enrichers.js.map +7 -0
  172. package/dist/modules/staff/data/entities.js +226 -1
  173. package/dist/modules/staff/data/entities.js.map +2 -2
  174. package/dist/modules/staff/data/validators.js +113 -1
  175. package/dist/modules/staff/data/validators.js.map +2 -2
  176. package/dist/modules/staff/events.js +13 -1
  177. package/dist/modules/staff/events.js.map +2 -2
  178. package/dist/modules/staff/lib/crud.js +7 -1
  179. package/dist/modules/staff/lib/crud.js.map +2 -2
  180. package/dist/modules/staff/lib/staffMemberResolver.js +15 -0
  181. package/dist/modules/staff/lib/staffMemberResolver.js.map +7 -0
  182. package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js +60 -0
  183. package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js.map +7 -0
  184. package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js +260 -0
  185. package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js.map +7 -0
  186. package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js +41 -0
  187. package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js.map +7 -0
  188. package/dist/modules/staff/lib/timesheets-projects/initials.js +10 -0
  189. package/dist/modules/staff/lib/timesheets-projects/initials.js.map +7 -0
  190. package/dist/modules/staff/lib/timesheets-projects/kpiMath.js +12 -0
  191. package/dist/modules/staff/lib/timesheets-projects/kpiMath.js.map +7 -0
  192. package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js +55 -0
  193. package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js.map +7 -0
  194. package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js +66 -0
  195. package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js.map +7 -0
  196. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +81 -0
  197. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +7 -0
  198. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js +58 -0
  199. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js.map +7 -0
  200. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js +152 -0
  201. package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js.map +7 -0
  202. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +37 -0
  203. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +7 -0
  204. package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js +57 -0
  205. package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js.map +7 -0
  206. package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js +50 -0
  207. package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js.map +7 -0
  208. package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js +163 -0
  209. package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js.map +7 -0
  210. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +209 -0
  211. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +7 -0
  212. package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js +52 -0
  213. package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js.map +7 -0
  214. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +77 -0
  215. package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +7 -0
  216. package/dist/modules/staff/lib/timesheets-ui/ListView.js +173 -0
  217. package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +7 -0
  218. package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js +32 -0
  219. package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js.map +7 -0
  220. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +270 -0
  221. package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +7 -0
  222. package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js +57 -0
  223. package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js.map +7 -0
  224. package/dist/modules/staff/lib/timesheets-ui/colors.js +43 -0
  225. package/dist/modules/staff/lib/timesheets-ui/colors.js.map +7 -0
  226. package/dist/modules/staff/migrations/Migration20260326135612.js +24 -0
  227. package/dist/modules/staff/migrations/Migration20260326135612.js.map +7 -0
  228. package/dist/modules/staff/migrations/Migration20260413102715.js +23 -0
  229. package/dist/modules/staff/migrations/Migration20260413102715.js.map +7 -0
  230. package/dist/modules/staff/migrations/Migration20260413111602.js +13 -0
  231. package/dist/modules/staff/migrations/Migration20260413111602.js.map +7 -0
  232. package/dist/modules/staff/migrations/Migration20260511112759.js +19 -0
  233. package/dist/modules/staff/migrations/Migration20260511112759.js.map +7 -0
  234. package/dist/modules/staff/search.js +35 -0
  235. package/dist/modules/staff/search.js.map +2 -2
  236. package/dist/modules/staff/setup.js +15 -1
  237. package/dist/modules/staff/setup.js.map +2 -2
  238. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js +16 -0
  239. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js.map +7 -0
  240. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +126 -0
  241. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +7 -0
  242. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js +26 -0
  243. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js.map +7 -0
  244. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js +15 -0
  245. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js.map +7 -0
  246. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +238 -0
  247. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +7 -0
  248. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js +26 -0
  249. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js.map +7 -0
  250. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +145 -0
  251. package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +7 -0
  252. package/dist/modules/staff/widgets/injection-table.js +12 -0
  253. package/dist/modules/staff/widgets/injection-table.js.map +7 -0
  254. package/dist/modules/sync_excel/api/import/route.js +19 -17
  255. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  256. package/dist/modules/translations/commands/translations.js +22 -19
  257. package/dist/modules/translations/commands/translations.js.map +2 -2
  258. package/dist/modules/workflows/backend/events/[id]/page.js +24 -6
  259. package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
  260. package/dist/modules/workflows/backend/instances/[id]/page.js +27 -5
  261. package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
  262. package/dist/modules/workflows/backend/tasks/[id]/page.js +25 -6
  263. package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
  264. package/generated/entities/staff_time_entry/index.ts +17 -0
  265. package/generated/entities/staff_time_entry_segment/index.ts +10 -0
  266. package/generated/entities/staff_time_project/index.ts +16 -0
  267. package/generated/entities/staff_time_project_member/index.ts +13 -0
  268. package/generated/entities.ids.generated.ts +5 -1
  269. package/generated/entity-fields-registry.ts +64 -0
  270. package/package.json +7 -7
  271. package/src/helpers/integration/timesheetFixtures.ts +61 -0
  272. package/src/modules/attachments/api/library/[id]/route.ts +24 -17
  273. package/src/modules/attachments/api/route.ts +20 -14
  274. package/src/modules/auth/api/roles/acl/route.ts +11 -5
  275. package/src/modules/auth/api/sidebar/preferences/route.ts +33 -24
  276. package/src/modules/auth/api/users/acl/route.ts +17 -12
  277. package/src/modules/auth/commands/users.ts +96 -80
  278. package/src/modules/auth/services/sidebarPreferencesService.ts +40 -32
  279. package/src/modules/business_rules/backend/logs/[id]/page.tsx +32 -7
  280. package/src/modules/catalog/api/offers/route.ts +20 -5
  281. package/src/modules/catalog/commands/categories.ts +61 -12
  282. package/src/modules/catalog/commands/products.ts +93 -60
  283. package/src/modules/catalog/commands/variants.ts +29 -16
  284. package/src/modules/currencies/backend/currencies/[id]/page.tsx +21 -2
  285. package/src/modules/currencies/commands/currencies.ts +27 -14
  286. package/src/modules/currencies/i18n/de.json +1 -0
  287. package/src/modules/currencies/i18n/en.json +1 -0
  288. package/src/modules/currencies/i18n/es.json +1 -0
  289. package/src/modules/currencies/i18n/pl.json +1 -0
  290. package/src/modules/customer_accounts/api/admin/users.ts +31 -26
  291. package/src/modules/customer_accounts/api/password/reset-confirm.ts +5 -6
  292. package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +14 -13
  293. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -11
  294. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +34 -11
  295. package/src/modules/customers/backend/customers/people/[id]/page.tsx +35 -11
  296. package/src/modules/customers/commands/addresses.ts +35 -23
  297. package/src/modules/customers/commands/companies.ts +166 -165
  298. package/src/modules/customers/commands/deals.ts +2 -4
  299. package/src/modules/customers/commands/interactions.ts +20 -26
  300. package/src/modules/customers/commands/people.ts +18 -15
  301. package/src/modules/customers/commands/personCompanyLinks.ts +109 -100
  302. package/src/modules/customers/commands/pipeline-stages.ts +31 -27
  303. package/src/modules/customers/commands/pipelines.ts +29 -23
  304. package/src/modules/customers/commands/tags.ts +13 -5
  305. package/src/modules/dashboards/api/users/widgets/route.ts +0 -1
  306. package/src/modules/dashboards/api/widgets/data/route.ts +36 -1
  307. package/src/modules/data_sync/lib/sync-engine.ts +4 -5
  308. package/src/modules/data_sync/lib/sync-run-service.ts +57 -28
  309. package/src/modules/directory/commands/organizations.ts +203 -166
  310. package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +26 -18
  311. package/src/modules/messages/commands/messages.ts +82 -80
  312. package/src/modules/messages/commands/shared.ts +138 -133
  313. package/src/modules/perspectives/api/[tableId]/route.ts +38 -27
  314. package/src/modules/progress/acl.ts +4 -0
  315. package/src/modules/resources/commands/resources.ts +127 -117
  316. package/src/modules/resources/commands/tags.ts +7 -3
  317. package/src/modules/sales/api/quotes/send/route.ts +17 -12
  318. package/src/modules/sales/commands/documents.ts +673 -481
  319. package/src/modules/sales/commands/payments.ts +158 -152
  320. package/src/modules/sales/commands/returns.ts +74 -63
  321. package/src/modules/staff/acl.ts +11 -0
  322. package/src/modules/staff/analytics.ts +30 -0
  323. package/src/modules/staff/api/guards.ts +59 -0
  324. package/src/modules/staff/api/interceptors.ts +122 -0
  325. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +191 -0
  326. package/src/modules/staff/api/timesheets/my-projects/route.ts +115 -0
  327. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +159 -0
  328. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +187 -0
  329. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +191 -0
  330. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +168 -0
  331. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +191 -0
  332. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +292 -0
  333. package/src/modules/staff/api/timesheets/time-entries/route.ts +193 -0
  334. package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +167 -0
  335. package/src/modules/staff/api/timesheets/time-projects/route.ts +244 -0
  336. package/src/modules/staff/backend/staff/timesheets/page.meta.ts +20 -0
  337. package/src/modules/staff/backend/staff/timesheets/page.tsx +899 -0
  338. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +12 -0
  339. package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +141 -0
  340. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +12 -0
  341. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +579 -0
  342. package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +12 -0
  343. package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +90 -0
  344. package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +23 -0
  345. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +765 -0
  346. package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +138 -0
  347. package/src/modules/staff/cli.ts +40 -1
  348. package/src/modules/staff/commands/index.ts +2 -0
  349. package/src/modules/staff/commands/leave-requests.ts +37 -29
  350. package/src/modules/staff/commands/team-members.ts +25 -20
  351. package/src/modules/staff/commands/timesheets-entries.ts +504 -0
  352. package/src/modules/staff/commands/timesheets-projects.ts +699 -0
  353. package/src/modules/staff/data/enrichers.ts +134 -0
  354. package/src/modules/staff/data/entities.ts +198 -0
  355. package/src/modules/staff/data/validators.ts +129 -0
  356. package/src/modules/staff/events.ts +13 -0
  357. package/src/modules/staff/i18n/de.json +209 -1
  358. package/src/modules/staff/i18n/en.json +209 -1
  359. package/src/modules/staff/i18n/es.json +209 -1
  360. package/src/modules/staff/i18n/pl.json +209 -1
  361. package/src/modules/staff/lib/crud.ts +8 -0
  362. package/src/modules/staff/lib/staffMemberResolver.ts +22 -0
  363. package/src/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.ts +89 -0
  364. package/src/modules/staff/lib/timesheets-projects/computeProjectsKpis.ts +311 -0
  365. package/src/modules/staff/lib/timesheets-projects/dateBuckets.ts +37 -0
  366. package/src/modules/staff/lib/timesheets-projects/initials.ts +6 -0
  367. package/src/modules/staff/lib/timesheets-projects/kpiMath.ts +8 -0
  368. package/src/modules/staff/lib/timesheets-projects/listProjectMembersPreview.ts +83 -0
  369. package/src/modules/staff/lib/timesheets-projects-ui/HoursSparkline.tsx +75 -0
  370. package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +110 -0
  371. package/src/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.tsx +73 -0
  372. package/src/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.tsx +185 -0
  373. package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +53 -0
  374. package/src/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.tsx +63 -0
  375. package/src/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.ts +63 -0
  376. package/src/modules/staff/lib/timesheets-ui/AddRowDropdown.tsx +188 -0
  377. package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +229 -0
  378. package/src/modules/staff/lib/timesheets-ui/ColorPicker.tsx +65 -0
  379. package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +99 -0
  380. package/src/modules/staff/lib/timesheets-ui/ListView.tsx +230 -0
  381. package/src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx +40 -0
  382. package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +327 -0
  383. package/src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx +60 -0
  384. package/src/modules/staff/lib/timesheets-ui/colors.ts +58 -0
  385. package/src/modules/staff/migrations/.snapshot-open-mercato.json +1148 -0
  386. package/src/modules/staff/migrations/Migration20260326135612.ts +26 -0
  387. package/src/modules/staff/migrations/Migration20260413102715.ts +25 -0
  388. package/src/modules/staff/migrations/Migration20260413111602.ts +13 -0
  389. package/src/modules/staff/migrations/Migration20260511112759.ts +21 -0
  390. package/src/modules/staff/search.ts +35 -0
  391. package/src/modules/staff/setup.ts +15 -0
  392. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts +17 -0
  393. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +158 -0
  394. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts +25 -0
  395. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts +15 -0
  396. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +297 -0
  397. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.ts +25 -0
  398. package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +161 -0
  399. package/src/modules/staff/widgets/injection-table.ts +10 -0
  400. package/src/modules/sync_excel/api/import/route.ts +23 -18
  401. package/src/modules/translations/commands/translations.ts +49 -41
  402. package/src/modules/workflows/backend/events/[id]/page.tsx +32 -10
  403. package/src/modules/workflows/backend/instances/[id]/page.tsx +33 -9
  404. package/src/modules/workflows/backend/tasks/[id]/page.tsx +33 -10
  405. package/src/modules/workflows/i18n/de.json +1 -0
  406. package/src/modules/workflows/i18n/en.json +1 -0
  407. package/src/modules/workflows/i18n/es.json +1 -0
  408. package/src/modules/workflows/i18n/pl.json +1 -0
@@ -0,0 +1,209 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Button } from "@open-mercato/ui/primitives/button";
5
+ import { IconButton } from "@open-mercato/ui/primitives/icon-button";
6
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
7
+ import { CalendarDays, ChevronLeft, ChevronRight } from "lucide-react";
8
+ function getMonday(date) {
9
+ const result = new Date(date);
10
+ const day = result.getDay();
11
+ const diff = day === 0 ? -6 : 1 - day;
12
+ result.setDate(result.getDate() + diff);
13
+ result.setHours(0, 0, 0, 0);
14
+ return result;
15
+ }
16
+ function getWeekNumber(date) {
17
+ const target = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
18
+ target.setUTCDate(target.getUTCDate() + 4 - (target.getUTCDay() || 7));
19
+ const yearStart = new Date(Date.UTC(target.getUTCFullYear(), 0, 1));
20
+ return Math.ceil(((target.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
21
+ }
22
+ function isSameDay(first, second) {
23
+ return first.getFullYear() === second.getFullYear() && first.getMonth() === second.getMonth() && first.getDate() === second.getDate();
24
+ }
25
+ function isSameWeek(first, second) {
26
+ return isSameDay(getMonday(first), getMonday(second));
27
+ }
28
+ function buildWeeks(year, month) {
29
+ const firstDay = new Date(year, month, 1);
30
+ const start = getMonday(firstDay);
31
+ const weeks = [];
32
+ const current = new Date(start);
33
+ for (let weekIdx = 0; weekIdx < 6; weekIdx++) {
34
+ const week = [];
35
+ for (let dayIdx = 0; dayIdx < 7; dayIdx++) {
36
+ week.push(new Date(current));
37
+ current.setDate(current.getDate() + 1);
38
+ }
39
+ weeks.push(week);
40
+ if (current.getMonth() !== month && weekIdx >= 3) break;
41
+ }
42
+ return weeks;
43
+ }
44
+ function getLocalizedDayHeaders() {
45
+ const baseMonday = new Date(2024, 0, 1);
46
+ return Array.from({ length: 7 }, (_, idx) => {
47
+ const date = new Date(baseMonday);
48
+ date.setDate(date.getDate() + idx);
49
+ return date.toLocaleDateString(void 0, { weekday: "narrow" });
50
+ });
51
+ }
52
+ function CalendarPicker({ selectedWeekStart, onWeekSelect }) {
53
+ const t = useT();
54
+ const [open, setOpen] = React.useState(false);
55
+ const [viewYear, setViewYear] = React.useState(selectedWeekStart.getFullYear());
56
+ const [viewMonth, setViewMonth] = React.useState(selectedWeekStart.getMonth());
57
+ const containerRef = React.useRef(null);
58
+ const dayHeaders = React.useMemo(() => getLocalizedDayHeaders(), []);
59
+ React.useEffect(() => {
60
+ function handleClickOutside(event) {
61
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
62
+ setOpen(false);
63
+ }
64
+ }
65
+ if (open) document.addEventListener("mousedown", handleClickOutside);
66
+ return () => document.removeEventListener("mousedown", handleClickOutside);
67
+ }, [open]);
68
+ React.useEffect(() => {
69
+ setViewYear(selectedWeekStart.getFullYear());
70
+ setViewMonth(selectedWeekStart.getMonth());
71
+ }, [selectedWeekStart]);
72
+ const weeks = React.useMemo(() => buildWeeks(viewYear, viewMonth), [viewYear, viewMonth]);
73
+ const monthLabel = React.useMemo(() => {
74
+ return new Date(viewYear, viewMonth, 1).toLocaleString(void 0, { month: "long", year: "numeric" });
75
+ }, [viewYear, viewMonth]);
76
+ const today = React.useMemo(() => /* @__PURE__ */ new Date(), []);
77
+ const handleWeekClick = React.useCallback((monday) => {
78
+ onWeekSelect(monday);
79
+ setOpen(false);
80
+ }, [onWeekSelect]);
81
+ const goToPrevMonth = React.useCallback(() => {
82
+ setViewMonth((prev) => {
83
+ if (prev === 0) {
84
+ setViewYear((yr) => yr - 1);
85
+ return 11;
86
+ }
87
+ return prev - 1;
88
+ });
89
+ }, []);
90
+ const goToNextMonth = React.useCallback(() => {
91
+ setViewMonth((prev) => {
92
+ if (prev === 11) {
93
+ setViewYear((yr) => yr + 1);
94
+ return 0;
95
+ }
96
+ return prev + 1;
97
+ });
98
+ }, []);
99
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative inline-block", children: [
100
+ /* @__PURE__ */ jsx(
101
+ IconButton,
102
+ {
103
+ variant: "outline",
104
+ size: "sm",
105
+ type: "button",
106
+ onClick: () => setOpen((prev) => !prev),
107
+ "aria-label": t("staff.timesheets.my.calendar.open", "Open calendar"),
108
+ children: /* @__PURE__ */ jsx(CalendarDays, { className: "size-4" })
109
+ }
110
+ ),
111
+ open && /* @__PURE__ */ jsxs("div", { className: "absolute left-0 z-20 mt-1 w-[280px] rounded-lg border bg-popover p-3 shadow-lg", children: [
112
+ /* @__PURE__ */ jsxs("div", { className: "mb-3 flex gap-2 border-b pb-2", children: [
113
+ /* @__PURE__ */ jsx(
114
+ Button,
115
+ {
116
+ type: "button",
117
+ variant: "ghost",
118
+ size: "sm",
119
+ className: "h-auto px-2 py-1 text-xs",
120
+ onClick: () => handleWeekClick(getMonday(/* @__PURE__ */ new Date())),
121
+ children: t("staff.timesheets.my.calendar.thisWeek", "This week")
122
+ }
123
+ ),
124
+ /* @__PURE__ */ jsx(
125
+ Button,
126
+ {
127
+ type: "button",
128
+ variant: "ghost",
129
+ size: "sm",
130
+ className: "h-auto px-2 py-1 text-xs",
131
+ onClick: () => {
132
+ const lastWeek = /* @__PURE__ */ new Date();
133
+ lastWeek.setDate(lastWeek.getDate() - 7);
134
+ handleWeekClick(getMonday(lastWeek));
135
+ },
136
+ children: t("staff.timesheets.my.calendar.lastWeek", "Last week")
137
+ }
138
+ )
139
+ ] }),
140
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
141
+ /* @__PURE__ */ jsx(
142
+ IconButton,
143
+ {
144
+ variant: "ghost",
145
+ size: "xs",
146
+ type: "button",
147
+ onClick: goToPrevMonth,
148
+ "aria-label": t("staff.timesheets.my.calendar.prevMonth", "Previous month"),
149
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3.5" })
150
+ }
151
+ ),
152
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: monthLabel }),
153
+ /* @__PURE__ */ jsx(
154
+ IconButton,
155
+ {
156
+ variant: "ghost",
157
+ size: "xs",
158
+ type: "button",
159
+ onClick: goToNextMonth,
160
+ "aria-label": t("staff.timesheets.my.calendar.nextMonth", "Next month"),
161
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5" })
162
+ }
163
+ )
164
+ ] }),
165
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[32px_repeat(7,1fr)] gap-0 mb-1", children: [
166
+ /* @__PURE__ */ jsx("div", {}),
167
+ dayHeaders.map((day, idx) => /* @__PURE__ */ jsx("div", { className: "text-center text-[11px] font-medium text-muted-foreground py-1", children: day }, idx))
168
+ ] }),
169
+ weeks.map((week) => {
170
+ const monday = week[0];
171
+ const weekNum = getWeekNumber(monday);
172
+ const isSelected = isSameWeek(monday, selectedWeekStart);
173
+ return /* @__PURE__ */ jsxs(
174
+ Button,
175
+ {
176
+ type: "button",
177
+ variant: "ghost",
178
+ className: `grid grid-cols-[32px_repeat(7,1fr)] gap-0 w-full h-auto rounded-md px-0 py-0 hover:bg-muted
179
+ ${isSelected ? "bg-primary text-primary-foreground hover:bg-primary/90" : ""}`,
180
+ onClick: () => handleWeekClick(monday),
181
+ children: [
182
+ /* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium py-1.5 text-center ${isSelected ? "text-primary-foreground/70" : "text-muted-foreground"}`, children: weekNum }),
183
+ week.map((date) => {
184
+ const inMonth = date.getMonth() === viewMonth;
185
+ const isTodayDate = isSameDay(date, today);
186
+ return /* @__PURE__ */ jsx(
187
+ "span",
188
+ {
189
+ className: `text-xs py-1.5 text-center
190
+ ${!inMonth && !isSelected ? "text-muted-foreground/40" : ""}
191
+ ${isTodayDate && !isSelected ? "font-bold text-primary" : ""}
192
+ ${isTodayDate && isSelected ? "font-bold underline" : ""}`,
193
+ children: date.getDate()
194
+ },
195
+ date.toISOString()
196
+ );
197
+ })
198
+ ]
199
+ },
200
+ monday.toISOString()
201
+ );
202
+ })
203
+ ] })
204
+ ] });
205
+ }
206
+ export {
207
+ CalendarPicker
208
+ };
209
+ //# sourceMappingURL=CalendarPicker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CalendarDays, ChevronLeft, ChevronRight } from 'lucide-react'\n\ntype CalendarPickerProps = {\n selectedWeekStart: Date\n onWeekSelect: (weekStart: Date) => void\n}\n\nfunction getMonday(date: Date): Date {\n const result = new Date(date)\n const day = result.getDay()\n const diff = day === 0 ? -6 : 1 - day\n result.setDate(result.getDate() + diff)\n result.setHours(0, 0, 0, 0)\n return result\n}\n\nfunction getWeekNumber(date: Date): number {\n const target = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))\n target.setUTCDate(target.getUTCDate() + 4 - (target.getUTCDay() || 7))\n const yearStart = new Date(Date.UTC(target.getUTCFullYear(), 0, 1))\n return Math.ceil(((target.getTime() - yearStart.getTime()) / 86400000 + 1) / 7)\n}\n\nfunction isSameDay(first: Date, second: Date): boolean {\n return first.getFullYear() === second.getFullYear() && first.getMonth() === second.getMonth() && first.getDate() === second.getDate()\n}\n\nfunction isSameWeek(first: Date, second: Date): boolean {\n return isSameDay(getMonday(first), getMonday(second))\n}\n\nfunction buildWeeks(year: number, month: number): Date[][] {\n const firstDay = new Date(year, month, 1)\n const start = getMonday(firstDay)\n const weeks: Date[][] = []\n const current = new Date(start)\n\n for (let weekIdx = 0; weekIdx < 6; weekIdx++) {\n const week: Date[] = []\n for (let dayIdx = 0; dayIdx < 7; dayIdx++) {\n week.push(new Date(current))\n current.setDate(current.getDate() + 1)\n }\n weeks.push(week)\n if (current.getMonth() !== month && weekIdx >= 3) break\n }\n return weeks\n}\n\nfunction getLocalizedDayHeaders(): string[] {\n const baseMonday = new Date(2024, 0, 1) // Known Monday\n return Array.from({ length: 7 }, (_, idx) => {\n const date = new Date(baseMonday)\n date.setDate(date.getDate() + idx)\n return date.toLocaleDateString(undefined, { weekday: 'narrow' })\n })\n}\n\nexport function CalendarPicker({ selectedWeekStart, onWeekSelect }: CalendarPickerProps) {\n const t = useT()\n const [open, setOpen] = React.useState(false)\n const [viewYear, setViewYear] = React.useState(selectedWeekStart.getFullYear())\n const [viewMonth, setViewMonth] = React.useState(selectedWeekStart.getMonth())\n const containerRef = React.useRef<HTMLDivElement>(null)\n\n const dayHeaders = React.useMemo(() => getLocalizedDayHeaders(), [])\n\n React.useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (containerRef.current && !containerRef.current.contains(event.target as Node)) {\n setOpen(false)\n }\n }\n if (open) document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }, [open])\n\n React.useEffect(() => {\n setViewYear(selectedWeekStart.getFullYear())\n setViewMonth(selectedWeekStart.getMonth())\n }, [selectedWeekStart])\n\n const weeks = React.useMemo(() => buildWeeks(viewYear, viewMonth), [viewYear, viewMonth])\n\n const monthLabel = React.useMemo(() => {\n return new Date(viewYear, viewMonth, 1).toLocaleString(undefined, { month: 'long', year: 'numeric' })\n }, [viewYear, viewMonth])\n\n const today = React.useMemo(() => new Date(), [])\n\n const handleWeekClick = React.useCallback((monday: Date) => {\n onWeekSelect(monday)\n setOpen(false)\n }, [onWeekSelect])\n\n const goToPrevMonth = React.useCallback(() => {\n setViewMonth((prev) => {\n if (prev === 0) { setViewYear((yr) => yr - 1); return 11 }\n return prev - 1\n })\n }, [])\n\n const goToNextMonth = React.useCallback(() => {\n setViewMonth((prev) => {\n if (prev === 11) { setViewYear((yr) => yr + 1); return 0 }\n return prev + 1\n })\n }, [])\n\n return (\n <div ref={containerRef} className=\"relative inline-block\">\n <IconButton\n variant=\"outline\"\n size=\"sm\"\n type=\"button\"\n onClick={() => setOpen((prev) => !prev)}\n aria-label={t('staff.timesheets.my.calendar.open', 'Open calendar')}\n >\n <CalendarDays className=\"size-4\" />\n </IconButton>\n\n {open && (\n <div className=\"absolute left-0 z-20 mt-1 w-[280px] rounded-lg border bg-popover p-3 shadow-lg\">\n {/* Quick links */}\n <div className=\"mb-3 flex gap-2 border-b pb-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto px-2 py-1 text-xs\"\n onClick={() => handleWeekClick(getMonday(new Date()))}\n >\n {t('staff.timesheets.my.calendar.thisWeek', 'This week')}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto px-2 py-1 text-xs\"\n onClick={() => {\n const lastWeek = new Date()\n lastWeek.setDate(lastWeek.getDate() - 7)\n handleWeekClick(getMonday(lastWeek))\n }}\n >\n {t('staff.timesheets.my.calendar.lastWeek', 'Last week')}\n </Button>\n </div>\n\n {/* Month navigation */}\n <div className=\"mb-2 flex items-center justify-between\">\n <IconButton\n variant=\"ghost\"\n size=\"xs\"\n type=\"button\"\n onClick={goToPrevMonth}\n aria-label={t('staff.timesheets.my.calendar.prevMonth', 'Previous month')}\n >\n <ChevronLeft className=\"size-3.5\" />\n </IconButton>\n <span className=\"text-sm font-medium\">{monthLabel}</span>\n <IconButton\n variant=\"ghost\"\n size=\"xs\"\n type=\"button\"\n onClick={goToNextMonth}\n aria-label={t('staff.timesheets.my.calendar.nextMonth', 'Next month')}\n >\n <ChevronRight className=\"size-3.5\" />\n </IconButton>\n </div>\n\n {/* Day headers */}\n <div className=\"grid grid-cols-[32px_repeat(7,1fr)] gap-0 mb-1\">\n <div />\n {dayHeaders.map((day, idx) => (\n <div key={idx} className=\"text-center text-[11px] font-medium text-muted-foreground py-1\">\n {day}\n </div>\n ))}\n </div>\n\n {/* Week rows */}\n {weeks.map((week) => {\n const monday = week[0]\n const weekNum = getWeekNumber(monday)\n const isSelected = isSameWeek(monday, selectedWeekStart)\n\n return (\n <Button\n key={monday.toISOString()}\n type=\"button\"\n variant=\"ghost\"\n className={`grid grid-cols-[32px_repeat(7,1fr)] gap-0 w-full h-auto rounded-md px-0 py-0 hover:bg-muted\n ${isSelected ? 'bg-primary text-primary-foreground hover:bg-primary/90' : ''}`}\n onClick={() => handleWeekClick(monday)}\n >\n <span className={`text-[10px] font-medium py-1.5 text-center ${isSelected ? 'text-primary-foreground/70' : 'text-muted-foreground'}`}>\n {weekNum}\n </span>\n {week.map((date) => {\n const inMonth = date.getMonth() === viewMonth\n const isTodayDate = isSameDay(date, today)\n return (\n <span\n key={date.toISOString()}\n className={`text-xs py-1.5 text-center\n ${!inMonth && !isSelected ? 'text-muted-foreground/40' : ''}\n ${isTodayDate && !isSelected ? 'font-bold text-primary' : ''}\n ${isTodayDate && isSelected ? 'font-bold underline' : ''}`}\n >\n {date.getDate()}\n </span>\n )\n })}\n </Button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Check } from "lucide-react";
4
+ import { PROJECT_COLORS } from "./colors.js";
5
+ function ColorPicker({
6
+ value,
7
+ onChange,
8
+ allowReset = true,
9
+ resetLabel = "Auto",
10
+ id,
11
+ disabled = false
12
+ }) {
13
+ return /* @__PURE__ */ jsxs("div", { id, className: "flex flex-wrap items-center gap-2", role: "radiogroup", children: [
14
+ PROJECT_COLORS.map((color) => {
15
+ const selected = value === color.key;
16
+ return /* @__PURE__ */ jsx(
17
+ "button",
18
+ {
19
+ type: "button",
20
+ role: "radio",
21
+ "aria-checked": selected,
22
+ "aria-label": color.key,
23
+ title: color.key,
24
+ disabled,
25
+ onClick: () => onChange(color.key),
26
+ className: `inline-flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-full transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${selected ? "ring-2 ring-offset-1 ring-ring" : ""}`,
27
+ style: { backgroundColor: color.hex },
28
+ children: selected ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-white", strokeWidth: 3 }) : null
29
+ },
30
+ color.key
31
+ );
32
+ }),
33
+ allowReset ? /* @__PURE__ */ jsx(
34
+ "button",
35
+ {
36
+ type: "button",
37
+ role: "radio",
38
+ "aria-checked": value == null,
39
+ "aria-label": resetLabel,
40
+ title: resetLabel,
41
+ disabled,
42
+ onClick: () => onChange(null),
43
+ className: `inline-flex h-6 items-center cursor-pointer rounded-full border border-dashed border-muted-foreground/50 bg-transparent px-2 text-[11px] text-muted-foreground transition-colors hover:bg-muted focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${value == null ? "ring-2 ring-offset-1 ring-ring" : ""}`,
44
+ children: resetLabel
45
+ }
46
+ ) : null
47
+ ] });
48
+ }
49
+ export {
50
+ ColorPicker
51
+ };
52
+ //# sourceMappingURL=ColorPicker.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/timesheets-ui/ColorPicker.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Check } from 'lucide-react'\nimport { PROJECT_COLORS } from './colors'\n\nexport type ColorPickerProps = {\n value: string | null | undefined\n onChange: (value: string | null) => void\n allowReset?: boolean\n resetLabel?: string\n id?: string\n disabled?: boolean\n}\n\nexport function ColorPicker({\n value,\n onChange,\n allowReset = true,\n resetLabel = 'Auto',\n id,\n disabled = false,\n}: ColorPickerProps) {\n return (\n <div id={id} className=\"flex flex-wrap items-center gap-2\" role=\"radiogroup\">\n {PROJECT_COLORS.map((color) => {\n const selected = value === color.key\n return (\n <button\n key={color.key}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n aria-label={color.key}\n title={color.key}\n disabled={disabled}\n onClick={() => onChange(color.key)}\n className={`inline-flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-full transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${\n selected ? 'ring-2 ring-offset-1 ring-ring' : ''\n }`}\n style={{ backgroundColor: color.hex }}\n >\n {selected ? <Check className=\"h-3.5 w-3.5 text-white\" strokeWidth={3} /> : null}\n </button>\n )\n })}\n {allowReset ? (\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={value == null}\n aria-label={resetLabel}\n title={resetLabel}\n disabled={disabled}\n onClick={() => onChange(null)}\n className={`inline-flex h-6 items-center cursor-pointer rounded-full border border-dashed border-muted-foreground/50 bg-transparent px-2 text-[11px] text-muted-foreground transition-colors hover:bg-muted focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${\n value == null ? 'ring-2 ring-offset-1 ring-ring' : ''\n }`}\n >\n {resetLabel}\n </button>\n ) : null}\n </div>\n )\n}\n"],
5
+ "mappings": ";AAwBI,SAkBoB,KAlBpB;AArBJ,SAAS,aAAa;AACtB,SAAS,sBAAsB;AAWxB,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,aAAa;AAAA,EACb;AAAA,EACA,WAAW;AACb,GAAqB;AACnB,SACE,qBAAC,SAAI,IAAQ,WAAU,qCAAoC,MAAK,cAC7D;AAAA,mBAAe,IAAI,CAAC,UAAU;AAC7B,YAAM,WAAW,UAAU,MAAM;AACjC,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,gBAAc;AAAA,UACd,cAAY,MAAM;AAAA,UAClB,OAAO,MAAM;AAAA,UACb;AAAA,UACA,SAAS,MAAM,SAAS,MAAM,GAAG;AAAA,UACjC,WAAW,iPACT,WAAW,mCAAmC,EAChD;AAAA,UACA,OAAO,EAAE,iBAAiB,MAAM,IAAI;AAAA,UAEnC,qBAAW,oBAAC,SAAM,WAAU,0BAAyB,aAAa,GAAG,IAAK;AAAA;AAAA,QAbtE,MAAM;AAAA,MAcb;AAAA,IAEJ,CAAC;AAAA,IACA,aACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,gBAAc,SAAS;AAAA,QACvB,cAAY;AAAA,QACZ,OAAO;AAAA,QACP;AAAA,QACA,SAAS,MAAM,SAAS,IAAI;AAAA,QAC5B,WAAW,uTACT,SAAS,OAAO,mCAAmC,EACrD;AAAA,QAEC;AAAA;AAAA,IACH,IACE;AAAA,KACN;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@open-mercato/ui/primitives/dialog";
5
+ import { Button } from "@open-mercato/ui/primitives/button";
6
+ import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
7
+ import { createCrud } from "@open-mercato/ui/backend/utils/crud";
8
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
9
+ import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
10
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
11
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
12
+ import { E } from "../../../../generated/entities.ids.generated.js";
13
+ import {
14
+ buildProjectPayload,
15
+ createProjectFormFields,
16
+ createProjectFormGroups,
17
+ createProjectFormSchema
18
+ } from "../../backend/staff/timesheets/projects/projectFormConfig.js";
19
+ function CreateProjectDialog({ open, onOpenChange, onProjectCreated }) {
20
+ const t = useT();
21
+ const formSchema = React.useMemo(() => createProjectFormSchema(), []);
22
+ const fields = React.useMemo(() => createProjectFormFields(t), [t]);
23
+ const groups = React.useMemo(() => createProjectFormGroups(t), [t]);
24
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
25
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: t("staff.timesheets.projects.form.createTitle", "Create project") }) }),
26
+ /* @__PURE__ */ jsx(
27
+ CrudForm,
28
+ {
29
+ embedded: true,
30
+ fields,
31
+ groups,
32
+ schema: formSchema,
33
+ initialValues: {},
34
+ entityIds: [E.staff.staff_time_project],
35
+ submitLabel: t("staff.timesheets.projects.form.actions.create", "Create"),
36
+ extraActions: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: t("staff.timesheets.projects.form.actions.cancel", "Cancel") }),
37
+ onSubmit: async (values) => {
38
+ const payload = buildProjectPayload(values);
39
+ const { result: created } = await createCrud(
40
+ "staff/timesheets/time-projects",
41
+ payload,
42
+ { errorMessage: t("staff.timesheets.projects.errors.save", "Failed to save project.") }
43
+ );
44
+ const newId = created?.id;
45
+ if (!newId) {
46
+ throw createCrudFormError(
47
+ t("staff.timesheets.projects.errors.save", "Failed to save project.")
48
+ );
49
+ }
50
+ try {
51
+ const selfRes = await apiCall("/api/staff/team-members/self");
52
+ const staffMemberId = selfRes.result?.member?.id;
53
+ if (staffMemberId) {
54
+ await createCrud("staff/timesheets/time-projects/" + newId + "/employees", {
55
+ staffMemberId,
56
+ assignedStartDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
57
+ status: "active"
58
+ }, { errorMessage: "" });
59
+ }
60
+ } catch {
61
+ }
62
+ onProjectCreated({
63
+ id: newId,
64
+ name: created?.name ?? values.name.trim(),
65
+ code: created?.code ?? values.code?.trim() ?? null
66
+ });
67
+ flash(t("staff.timesheets.projects.messages.saved", "Project saved."), "success");
68
+ onOpenChange(false);
69
+ }
70
+ }
71
+ )
72
+ ] }) });
73
+ }
74
+ export {
75
+ CreateProjectDialog
76
+ };
77
+ //# sourceMappingURL=CreateProjectDialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { createCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n buildProjectPayload,\n createProjectFormFields,\n createProjectFormGroups,\n createProjectFormSchema,\n type ProjectFormValues,\n} from '../../backend/staff/timesheets/projects/projectFormConfig'\n\ntype CreateProjectDialogProps = {\n open: boolean\n onOpenChange: (open: boolean) => void\n onProjectCreated: (project: { id: string; name: string; code: string | null }) => void\n}\n\nexport function CreateProjectDialog({ open, onOpenChange, onProjectCreated }: CreateProjectDialogProps) {\n const t = useT()\n\n const formSchema = React.useMemo(() => createProjectFormSchema(), [])\n const fields = React.useMemo(() => createProjectFormFields(t), [t])\n const groups = React.useMemo(() => createProjectFormGroups(t), [t])\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>\n {t('staff.timesheets.projects.form.createTitle', 'Create project')}\n </DialogTitle>\n </DialogHeader>\n <CrudForm<ProjectFormValues>\n embedded\n fields={fields}\n groups={groups}\n schema={formSchema}\n initialValues={{}}\n entityIds={[E.staff.staff_time_project]}\n submitLabel={t('staff.timesheets.projects.form.actions.create', 'Create')}\n extraActions={(\n <Button type=\"button\" variant=\"ghost\" onClick={() => onOpenChange(false)}>\n {t('staff.timesheets.projects.form.actions.cancel', 'Cancel')}\n </Button>\n )}\n onSubmit={async (values) => {\n const payload = buildProjectPayload(values)\n\n const { result: created } = await createCrud<{ id?: string; name?: string; code?: string | null }>(\n 'staff/timesheets/time-projects',\n payload,\n { errorMessage: t('staff.timesheets.projects.errors.save', 'Failed to save project.') },\n )\n\n const newId = created?.id\n if (!newId) {\n throw createCrudFormError(\n t('staff.timesheets.projects.errors.save', 'Failed to save project.'),\n )\n }\n\n // Auto-assign creator to the project (best-effort)\n try {\n const selfRes = await apiCall<{ member?: { id?: string } | null }>('/api/staff/team-members/self')\n const staffMemberId = selfRes.result?.member?.id\n if (staffMemberId) {\n await createCrud('staff/timesheets/time-projects/' + newId + '/employees', {\n staffMemberId,\n assignedStartDate: new Date().toISOString().slice(0, 10),\n status: 'active',\n }, { errorMessage: '' })\n }\n } catch {\n // non-critical \u2014 project created, self-assignment is best-effort\n }\n\n onProjectCreated({\n id: newId,\n name: created?.name ?? values.name.trim(),\n code: created?.code ?? values.code?.trim() ?? null,\n })\n\n flash(t('staff.timesheets.projects.messages.saved', 'Project saved.'), 'success')\n onOpenChange(false)\n }}\n />\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": ";AAmCM,SAEI,KAFJ;AAjCN,YAAY,WAAW;AACvB,SAAS,QAAQ,eAAe,cAAc,mBAAmB;AACjE,SAAS,cAAc;AACvB,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB,SAAS,2BAA2B;AACpC,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAQA,SAAS,oBAAoB,EAAE,MAAM,cAAc,iBAAiB,GAA6B;AACtG,QAAM,IAAI,KAAK;AAEf,QAAM,aAAa,MAAM,QAAQ,MAAM,wBAAwB,GAAG,CAAC,CAAC;AACpE,QAAM,SAAS,MAAM,QAAQ,MAAM,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC;AAClE,QAAM,SAAS,MAAM,QAAQ,MAAM,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC;AAElE,SACE,oBAAC,UAAO,MAAY,cAClB,+BAAC,iBAAc,WAAU,eACvB;AAAA,wBAAC,gBACC,8BAAC,eACE,YAAE,8CAA8C,gBAAgB,GACnE,GACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,eAAe,CAAC;AAAA,QAChB,WAAW,CAAC,EAAE,MAAM,kBAAkB;AAAA,QACtC,aAAa,EAAE,iDAAiD,QAAQ;AAAA,QACxE,cACE,oBAAC,UAAO,MAAK,UAAS,SAAQ,SAAQ,SAAS,MAAM,aAAa,KAAK,GACpE,YAAE,iDAAiD,QAAQ,GAC9D;AAAA,QAEF,UAAU,OAAO,WAAW;AAC1B,gBAAM,UAAU,oBAAoB,MAAM;AAE1C,gBAAM,EAAE,QAAQ,QAAQ,IAAI,MAAM;AAAA,YAChC;AAAA,YACA;AAAA,YACA,EAAE,cAAc,EAAE,yCAAyC,yBAAyB,EAAE;AAAA,UACxF;AAEA,gBAAM,QAAQ,SAAS;AACvB,cAAI,CAAC,OAAO;AACV,kBAAM;AAAA,cACJ,EAAE,yCAAyC,yBAAyB;AAAA,YACtE;AAAA,UACF;AAGA,cAAI;AACF,kBAAM,UAAU,MAAM,QAA6C,8BAA8B;AACjG,kBAAM,gBAAgB,QAAQ,QAAQ,QAAQ;AAC9C,gBAAI,eAAe;AACjB,oBAAM,WAAW,oCAAoC,QAAQ,cAAc;AAAA,gBACzE;AAAA,gBACA,oBAAmB,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,gBACvD,QAAQ;AAAA,cACV,GAAG,EAAE,cAAc,GAAG,CAAC;AAAA,YACzB;AAAA,UACF,QAAQ;AAAA,UAER;AAEA,2BAAiB;AAAA,YACf,IAAI;AAAA,YACJ,MAAM,SAAS,QAAQ,OAAO,KAAK,KAAK;AAAA,YACxC,MAAM,SAAS,QAAQ,OAAO,MAAM,KAAK,KAAK;AAAA,UAChD,CAAC;AAED,gBAAM,EAAE,4CAA4C,gBAAgB,GAAG,SAAS;AAChF,uBAAa,KAAK;AAAA,QACpB;AAAA;AAAA,IACF;AAAA,KACF,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,173 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
5
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
6
+ import { ProjectColorDot } from "./ProjectColorDot.js";
7
+ function getLocalDateStr(date) {
8
+ const year = date.getFullYear();
9
+ const month = String(date.getMonth() + 1).padStart(2, "0");
10
+ const day = String(date.getDate()).padStart(2, "0");
11
+ return `${year}-${month}-${day}`;
12
+ }
13
+ function formatDayLabel(dateStr, translate) {
14
+ const today = /* @__PURE__ */ new Date();
15
+ const todayStr = getLocalDateStr(today);
16
+ const yesterday = new Date(today);
17
+ yesterday.setDate(yesterday.getDate() - 1);
18
+ const yesterdayStr = getLocalDateStr(yesterday);
19
+ if (dateStr === todayStr) return translate("staff.timesheets.my.list.today", "Today");
20
+ if (dateStr === yesterdayStr) return translate("staff.timesheets.my.list.yesterday", "Yesterday");
21
+ const date = /* @__PURE__ */ new Date(dateStr + "T00:00:00");
22
+ const dayName = date.toLocaleDateString(void 0, { weekday: "short" });
23
+ const day = date.getDate();
24
+ const month = date.toLocaleDateString(void 0, { month: "short" });
25
+ return `${dayName}, ${day} ${month}`;
26
+ }
27
+ function formatDuration(minutes) {
28
+ if (minutes < 60) return `${minutes}m`;
29
+ const hours = Math.floor(minutes / 60);
30
+ const remainingMinutes = minutes % 60;
31
+ if (remainingMinutes === 0) return `${hours}h`;
32
+ return `${hours}h ${remainingMinutes}m`;
33
+ }
34
+ function formatTimeRange(startedAt, endedAt) {
35
+ const start = new Date(startedAt);
36
+ const end = new Date(endedAt);
37
+ const format = (date) => date.toLocaleTimeString(void 0, {
38
+ hour: "numeric",
39
+ minute: "2-digit",
40
+ hour12: true
41
+ });
42
+ return `${format(start)} - ${format(end)}`;
43
+ }
44
+ function InlineDescription({
45
+ entryId,
46
+ initialValue,
47
+ placeholder,
48
+ onSaved
49
+ }) {
50
+ const [editing, setEditing] = React.useState(false);
51
+ const [value, setValue] = React.useState(initialValue ?? "");
52
+ const [saving, setSaving] = React.useState(false);
53
+ const inputRef = React.useRef(null);
54
+ React.useEffect(() => {
55
+ if (editing && inputRef.current) inputRef.current.focus();
56
+ }, [editing]);
57
+ const save = React.useCallback(async () => {
58
+ const trimmed = value.trim();
59
+ if (trimmed === (initialValue ?? "")) {
60
+ setEditing(false);
61
+ return;
62
+ }
63
+ setSaving(true);
64
+ try {
65
+ await apiCall(`/api/staff/timesheets/time-entries`, {
66
+ method: "PUT",
67
+ headers: { "Content-Type": "application/json" },
68
+ body: JSON.stringify({ id: entryId, notes: trimmed || null })
69
+ });
70
+ onSaved?.();
71
+ } catch {
72
+ } finally {
73
+ setSaving(false);
74
+ setEditing(false);
75
+ }
76
+ }, [entryId, value, initialValue, onSaved]);
77
+ if (!editing) {
78
+ return /* @__PURE__ */ jsx(
79
+ "button",
80
+ {
81
+ type: "button",
82
+ onClick: () => setEditing(true),
83
+ className: `text-sm text-left cursor-pointer hover:underline ${initialValue ? "" : "text-muted-foreground italic"}`,
84
+ children: initialValue || placeholder
85
+ }
86
+ );
87
+ }
88
+ return /* @__PURE__ */ jsx(
89
+ "input",
90
+ {
91
+ ref: inputRef,
92
+ type: "text",
93
+ value,
94
+ disabled: saving,
95
+ onChange: (e) => setValue(e.target.value),
96
+ onBlur: () => {
97
+ void save();
98
+ },
99
+ onKeyDown: (e) => {
100
+ if (e.key === "Enter") {
101
+ void save();
102
+ }
103
+ if (e.key === "Escape") {
104
+ setValue(initialValue ?? "");
105
+ setEditing(false);
106
+ }
107
+ },
108
+ placeholder,
109
+ className: "text-sm w-full bg-transparent border-b border-primary/40 outline-none py-0.5 placeholder:text-muted-foreground/50"
110
+ }
111
+ );
112
+ }
113
+ function ListView({ entries, onEntryUpdated }) {
114
+ const t = useT();
115
+ if (entries.length === 0) {
116
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12 text-sm text-muted-foreground", children: t("staff.timesheets.my.list.noEntries", "No entries for this period.") });
117
+ }
118
+ const grouped = /* @__PURE__ */ new Map();
119
+ for (const entry of entries) {
120
+ const existing = grouped.get(entry.date);
121
+ if (existing) {
122
+ existing.push(entry);
123
+ } else {
124
+ grouped.set(entry.date, [entry]);
125
+ }
126
+ }
127
+ const sortedDays = [...grouped.keys()].sort((a, b) => b.localeCompare(a));
128
+ return /* @__PURE__ */ jsx("div", { children: sortedDays.map((dateStr) => {
129
+ const dayEntries = grouped.get(dateStr);
130
+ const dailyTotal = dayEntries.reduce(
131
+ (sum, entry) => sum + entry.durationMinutes,
132
+ 0
133
+ );
134
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border mb-4", children: [
135
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center p-4 border-b bg-muted/30 font-medium text-sm", children: [
136
+ /* @__PURE__ */ jsx("span", { children: formatDayLabel(dateStr, t) }),
137
+ /* @__PURE__ */ jsx("span", { className: "font-mono tabular-nums", children: formatDuration(dailyTotal) })
138
+ ] }),
139
+ dayEntries.map((entry) => /* @__PURE__ */ jsxs(
140
+ "div",
141
+ {
142
+ className: "flex items-center justify-between p-3 border-b last:border-0 hover:bg-muted/20",
143
+ children: [
144
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 min-w-0 flex-1 mr-4", children: [
145
+ /* @__PURE__ */ jsx(
146
+ InlineDescription,
147
+ {
148
+ entryId: entry.id,
149
+ initialValue: entry.notes,
150
+ placeholder: t("staff.timesheets.my.list.addDescription", "Add description"),
151
+ onSaved: onEntryUpdated
152
+ }
153
+ ),
154
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-muted-foreground", children: [
155
+ /* @__PURE__ */ jsx(ProjectColorDot, { colorKey: entry.projectColor, projectName: entry.projectName, size: "xs" }),
156
+ entry.projectName
157
+ ] })
158
+ ] }),
159
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end gap-1 shrink-0", children: [
160
+ entry.source === "timer" && entry.startedAt && entry.endedAt ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: formatTimeRange(entry.startedAt, entry.endedAt) }) : null,
161
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-mono tabular-nums", children: formatDuration(entry.durationMinutes) })
162
+ ] })
163
+ ]
164
+ },
165
+ entry.id
166
+ ))
167
+ ] }, dateStr);
168
+ }) });
169
+ }
170
+ export {
171
+ ListView
172
+ };
173
+ //# sourceMappingURL=ListView.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/staff/lib/timesheets-ui/ListView.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { ProjectColorDot } from './ProjectColorDot'\n\ntype TimeEntry = {\n id: string\n date: string\n durationMinutes: number\n projectId: string\n projectName: string\n projectCode: string | null\n projectColor: string | null\n notes: string | null\n source: string\n startedAt: string | null\n endedAt: string | null\n}\n\ntype ListViewProps = {\n entries: TimeEntry[]\n onEntryUpdated?: () => void\n}\n\nfunction getLocalDateStr(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\nfunction formatDayLabel(dateStr: string, translate: TranslateFn): string {\n const today = new Date()\n const todayStr = getLocalDateStr(today)\n\n const yesterday = new Date(today)\n yesterday.setDate(yesterday.getDate() - 1)\n const yesterdayStr = getLocalDateStr(yesterday)\n\n if (dateStr === todayStr) return translate('staff.timesheets.my.list.today', 'Today')\n if (dateStr === yesterdayStr) return translate('staff.timesheets.my.list.yesterday', 'Yesterday')\n\n const date = new Date(dateStr + 'T00:00:00')\n const dayName = date.toLocaleDateString(undefined, { weekday: 'short' })\n const day = date.getDate()\n const month = date.toLocaleDateString(undefined, { month: 'short' })\n\n return `${dayName}, ${day} ${month}`\n}\n\nfunction formatDuration(minutes: number): string {\n if (minutes < 60) return `${minutes}m`\n\n const hours = Math.floor(minutes / 60)\n const remainingMinutes = minutes % 60\n\n if (remainingMinutes === 0) return `${hours}h`\n return `${hours}h ${remainingMinutes}m`\n}\n\nfunction formatTimeRange(startedAt: string, endedAt: string): string {\n const start = new Date(startedAt)\n const end = new Date(endedAt)\n\n const format = (date: Date) =>\n date.toLocaleTimeString(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n\n return `${format(start)} - ${format(end)}`\n}\n\nfunction InlineDescription({\n entryId,\n initialValue,\n placeholder,\n onSaved,\n}: {\n entryId: string\n initialValue: string | null\n placeholder: string\n onSaved?: () => void\n}) {\n const [editing, setEditing] = React.useState(false)\n const [value, setValue] = React.useState(initialValue ?? '')\n const [saving, setSaving] = React.useState(false)\n const inputRef = React.useRef<HTMLInputElement>(null)\n\n React.useEffect(() => {\n if (editing && inputRef.current) inputRef.current.focus()\n }, [editing])\n\n const save = React.useCallback(async () => {\n const trimmed = value.trim()\n if (trimmed === (initialValue ?? '')) {\n setEditing(false)\n return\n }\n setSaving(true)\n try {\n await apiCall(`/api/staff/timesheets/time-entries`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: entryId, notes: trimmed || null }),\n })\n onSaved?.()\n } catch {\n // silent\n } finally {\n setSaving(false)\n setEditing(false)\n }\n }, [entryId, value, initialValue, onSaved])\n\n if (!editing) {\n return (\n <button\n type=\"button\"\n onClick={() => setEditing(true)}\n className={`text-sm text-left cursor-pointer hover:underline ${\n initialValue ? '' : 'text-muted-foreground italic'\n }`}\n >\n {initialValue || placeholder}\n </button>\n )\n }\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n disabled={saving}\n onChange={(e) => setValue(e.target.value)}\n onBlur={() => { void save() }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') { void save() }\n if (e.key === 'Escape') { setValue(initialValue ?? ''); setEditing(false) }\n }}\n placeholder={placeholder}\n className=\"text-sm w-full bg-transparent border-b border-primary/40 outline-none py-0.5 placeholder:text-muted-foreground/50\"\n />\n )\n}\n\nexport function ListView({ entries, onEntryUpdated }: ListViewProps) {\n const t = useT()\n\n if (entries.length === 0) {\n return (\n <div className=\"flex items-center justify-center py-12 text-sm text-muted-foreground\">\n {t('staff.timesheets.my.list.noEntries', 'No entries for this period.')}\n </div>\n )\n }\n\n const grouped = new Map<string, TimeEntry[]>()\n for (const entry of entries) {\n const existing = grouped.get(entry.date)\n if (existing) {\n existing.push(entry)\n } else {\n grouped.set(entry.date, [entry])\n }\n }\n\n const sortedDays = [...grouped.keys()].sort((a, b) => b.localeCompare(a))\n\n return (\n <div>\n {sortedDays.map((dateStr) => {\n const dayEntries = grouped.get(dateStr)!\n const dailyTotal = dayEntries.reduce(\n (sum, entry) => sum + entry.durationMinutes,\n 0,\n )\n\n return (\n <div key={dateStr} className=\"rounded-lg border mb-4\">\n <div className=\"flex justify-between items-center p-4 border-b bg-muted/30 font-medium text-sm\">\n <span>{formatDayLabel(dateStr, t)}</span>\n <span className=\"font-mono tabular-nums\">\n {formatDuration(dailyTotal)}\n </span>\n </div>\n\n {dayEntries.map((entry) => (\n <div\n key={entry.id}\n className=\"flex items-center justify-between p-3 border-b last:border-0 hover:bg-muted/20\"\n >\n <div className=\"flex flex-col gap-1 min-w-0 flex-1 mr-4\">\n <InlineDescription\n entryId={entry.id}\n initialValue={entry.notes}\n placeholder={t('staff.timesheets.my.list.addDescription', 'Add description')}\n onSaved={onEntryUpdated}\n />\n <span className=\"inline-flex items-center gap-1 text-xs font-medium text-muted-foreground\">\n <ProjectColorDot colorKey={entry.projectColor} projectName={entry.projectName} size=\"xs\" />\n {entry.projectName}\n </span>\n </div>\n\n <div className=\"flex flex-col items-end gap-1 shrink-0\">\n {entry.source === 'timer' &&\n entry.startedAt &&\n entry.endedAt ? (\n <span className=\"text-xs text-muted-foreground\">\n {formatTimeRange(entry.startedAt, entry.endedAt)}\n </span>\n ) : null}\n <span className=\"text-sm font-mono tabular-nums\">\n {formatDuration(entry.durationMinutes)}\n </span>\n </div>\n </div>\n ))}\n </div>\n )\n })}\n </div>\n )\n}\n"],
5
+ "mappings": ";AAyHM,cAgEM,YAhEN;AAvHN,YAAY,WAAW;AACvB,SAAS,YAAY;AAErB,SAAS,eAAe;AACxB,SAAS,uBAAuB;AAqBhC,SAAS,gBAAgB,MAAoB;AAC3C,QAAM,OAAO,KAAK,YAAY;AAC9B,QAAM,QAAQ,OAAO,KAAK,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACzD,QAAM,MAAM,OAAO,KAAK,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAClD,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG;AAChC;AAEA,SAAS,eAAe,SAAiB,WAAgC;AACvE,QAAM,QAAQ,oBAAI,KAAK;AACvB,QAAM,WAAW,gBAAgB,KAAK;AAEtC,QAAM,YAAY,IAAI,KAAK,KAAK;AAChC,YAAU,QAAQ,UAAU,QAAQ,IAAI,CAAC;AACzC,QAAM,eAAe,gBAAgB,SAAS;AAE9C,MAAI,YAAY,SAAU,QAAO,UAAU,kCAAkC,OAAO;AACpF,MAAI,YAAY,aAAc,QAAO,UAAU,sCAAsC,WAAW;AAEhG,QAAM,OAAO,oBAAI,KAAK,UAAU,WAAW;AAC3C,QAAM,UAAU,KAAK,mBAAmB,QAAW,EAAE,SAAS,QAAQ,CAAC;AACvE,QAAM,MAAM,KAAK,QAAQ;AACzB,QAAM,QAAQ,KAAK,mBAAmB,QAAW,EAAE,OAAO,QAAQ,CAAC;AAEnE,SAAO,GAAG,OAAO,KAAK,GAAG,IAAI,KAAK;AACpC;AAEA,SAAS,eAAe,SAAyB;AAC/C,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AAEnC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,mBAAmB,UAAU;AAEnC,MAAI,qBAAqB,EAAG,QAAO,GAAG,KAAK;AAC3C,SAAO,GAAG,KAAK,KAAK,gBAAgB;AACtC;AAEA,SAAS,gBAAgB,WAAmB,SAAyB;AACnE,QAAM,QAAQ,IAAI,KAAK,SAAS;AAChC,QAAM,MAAM,IAAI,KAAK,OAAO;AAE5B,QAAM,SAAS,CAAC,SACd,KAAK,mBAAmB,QAAW;AAAA,IACjC,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAEH,SAAO,GAAG,OAAO,KAAK,CAAC,MAAM,OAAO,GAAG,CAAC;AAC1C;AAEA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,gBAAgB,EAAE;AAC3D,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,KAAK;AAChD,QAAM,WAAW,MAAM,OAAyB,IAAI;AAEpD,QAAM,UAAU,MAAM;AACpB,QAAI,WAAW,SAAS,QAAS,UAAS,QAAQ,MAAM;AAAA,EAC1D,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,OAAO,MAAM,YAAY,YAAY;AACzC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,aAAa,gBAAgB,KAAK;AACpC,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,cAAU,IAAI;AACd,QAAI;AACF,YAAM,QAAQ,sCAAsC;AAAA,QAClD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,SAAS,OAAO,WAAW,KAAK,CAAC;AAAA,MAC9D,CAAC;AACD,gBAAU;AAAA,IACZ,QAAQ;AAAA,IAER,UAAE;AACA,gBAAU,KAAK;AACf,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,SAAS,OAAO,cAAc,OAAO,CAAC;AAE1C,MAAI,CAAC,SAAS;AACZ,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM,WAAW,IAAI;AAAA,QAC9B,WAAW,oDACT,eAAe,KAAK,8BACtB;AAAA,QAEC,0BAAgB;AAAA;AAAA,IACnB;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAK;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,MACxC,QAAQ,MAAM;AAAE,aAAK,KAAK;AAAA,MAAE;AAAA,MAC5B,WAAW,CAAC,MAAM;AAChB,YAAI,EAAE,QAAQ,SAAS;AAAE,eAAK,KAAK;AAAA,QAAE;AACrC,YAAI,EAAE,QAAQ,UAAU;AAAE,mBAAS,gBAAgB,EAAE;AAAG,qBAAW,KAAK;AAAA,QAAE;AAAA,MAC5E;AAAA,MACA;AAAA,MACA,WAAU;AAAA;AAAA,EACZ;AAEJ;AAEO,SAAS,SAAS,EAAE,SAAS,eAAe,GAAkB;AACnE,QAAM,IAAI,KAAK;AAEf,MAAI,QAAQ,WAAW,GAAG;AACxB,WACE,oBAAC,SAAI,WAAU,wEACZ,YAAE,sCAAsC,6BAA6B,GACxE;AAAA,EAEJ;AAEA,QAAM,UAAU,oBAAI,IAAyB;AAC7C,aAAW,SAAS,SAAS;AAC3B,UAAM,WAAW,QAAQ,IAAI,MAAM,IAAI;AACvC,QAAI,UAAU;AACZ,eAAS,KAAK,KAAK;AAAA,IACrB,OAAO;AACL,cAAQ,IAAI,MAAM,MAAM,CAAC,KAAK,CAAC;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,GAAG,QAAQ,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAExE,SACE,oBAAC,SACE,qBAAW,IAAI,CAAC,YAAY;AAC3B,UAAM,aAAa,QAAQ,IAAI,OAAO;AACtC,UAAM,aAAa,WAAW;AAAA,MAC5B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AAEA,WACE,qBAAC,SAAkB,WAAU,0BAC3B;AAAA,2BAAC,SAAI,WAAU,kFACb;AAAA,4BAAC,UAAM,yBAAe,SAAS,CAAC,GAAE;AAAA,QAClC,oBAAC,UAAK,WAAU,0BACb,yBAAe,UAAU,GAC5B;AAAA,SACF;AAAA,MAEC,WAAW,IAAI,CAAC,UACf;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA,iCAAC,SAAI,WAAU,2CACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,MAAM;AAAA,kBACf,cAAc,MAAM;AAAA,kBACpB,aAAa,EAAE,2CAA2C,iBAAiB;AAAA,kBAC3E,SAAS;AAAA;AAAA,cACX;AAAA,cACA,qBAAC,UAAK,WAAU,4EACd;AAAA,oCAAC,mBAAgB,UAAU,MAAM,cAAc,aAAa,MAAM,aAAa,MAAK,MAAK;AAAA,gBACxF,MAAM;AAAA,iBACT;AAAA,eACF;AAAA,YAEA,qBAAC,SAAI,WAAU,0CACZ;AAAA,oBAAM,WAAW,WAClB,MAAM,aACN,MAAM,UACJ,oBAAC,UAAK,WAAU,iCACb,0BAAgB,MAAM,WAAW,MAAM,OAAO,GACjD,IACE;AAAA,cACJ,oBAAC,UAAK,WAAU,kCACb,yBAAe,MAAM,eAAe,GACvC;AAAA,eACF;AAAA;AAAA;AAAA,QA3BK,MAAM;AAAA,MA4Bb,CACD;AAAA,SAvCO,OAwCV;AAAA,EAEJ,CAAC,GACH;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { resolveProjectColorHex } from "./colors.js";
4
+ const SIZE_CLASS = {
5
+ xs: "h-2 w-2",
6
+ sm: "h-2.5 w-2.5",
7
+ md: "h-3 w-3"
8
+ };
9
+ function ProjectColorDot({
10
+ colorKey,
11
+ projectName,
12
+ size = "sm",
13
+ className,
14
+ title
15
+ }) {
16
+ const hex = resolveProjectColorHex(colorKey, projectName);
17
+ const base = "inline-block shrink-0 rounded-full";
18
+ const classes = [base, SIZE_CLASS[size], className].filter(Boolean).join(" ");
19
+ return /* @__PURE__ */ jsx(
20
+ "span",
21
+ {
22
+ "aria-hidden": "true",
23
+ title,
24
+ className: classes,
25
+ style: { backgroundColor: hex }
26
+ }
27
+ );
28
+ }
29
+ export {
30
+ ProjectColorDot
31
+ };
32
+ //# sourceMappingURL=ProjectColorDot.js.map