@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
@@ -140,6 +140,41 @@ const searchConfig = {
140
140
  fieldPolicy: {
141
141
  searchable: ["name", "description", "appearance_icon", "appearance_color"]
142
142
  }
143
+ },
144
+ {
145
+ entityId: "staff:staff_time_project",
146
+ enabled: true,
147
+ priority: 7,
148
+ buildSource: async (ctx) => {
149
+ const { t } = await resolveTranslations();
150
+ const record = ctx.record;
151
+ const lines = [];
152
+ appendLine(lines, "Name", record.name);
153
+ appendLine(lines, "Code", record.code);
154
+ appendLine(lines, "Description", record.description);
155
+ appendLine(lines, "Type", record.project_type ?? record.projectType);
156
+ appendLine(lines, "Cost Center", record.cost_center ?? record.costCenter);
157
+ const presenter = {
158
+ title: String(record.name ?? record.id ?? t("staff.search.badge.timeProject", "Project")),
159
+ subtitle: formatSubtitle(record.code, record.project_type ?? record.projectType),
160
+ icon: "clock",
161
+ badge: t("staff.search.badge.timeProject", "Project")
162
+ };
163
+ return buildIndexSource(ctx, presenter, lines);
164
+ },
165
+ formatResult: async (ctx) => {
166
+ const { t } = await resolveTranslations();
167
+ return {
168
+ title: String(ctx.record.name ?? ctx.record.id ?? ""),
169
+ subtitle: formatSubtitle(ctx.record.code, ctx.record.project_type ?? ctx.record.projectType),
170
+ icon: "clock",
171
+ badge: t("staff.search.badge.timeProject", "Project")
172
+ };
173
+ },
174
+ resolveUrl: async (ctx) => `/backend/staff/timesheets/projects/${encodeURIComponent(String(ctx.record.id))}`,
175
+ fieldPolicy: {
176
+ searchable: ["name", "code", "description", "project_type", "cost_center"]
177
+ }
143
178
  }
144
179
  ]
145
180
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/staff/search.ts"],
4
- "sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchResultPresenter,\n SearchIndexSource,\n} from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction appendCustomFieldLines(lines: string[], customFields: Record<string, unknown>) {\n for (const [key, value] of Object.entries(customFields)) {\n if (value === null || value === undefined) continue\n appendLine(lines, key.replace(/^cf:/, ''), value)\n }\n}\n\nfunction formatSubtitle(...parts: Array<unknown>): string | undefined {\n const text = parts\n .map((part) => (part === null || part === undefined ? '' : String(part)))\n .map((part) => part.trim())\n .filter(Boolean)\n if (text.length === 0) return undefined\n return text.join(' \u00B7 ')\n}\n\nfunction buildTeamPresenter(\n t: TranslateFn,\n record: Record<string, unknown>,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const title =\n pickString(record.name, record.display_name, record.displayName, customFields.name, customFields.display_name) ??\n (record.id as string | undefined) ??\n t('staff.search.badge.team', 'Team')\n const description = snippet(record.description ?? customFields.description)\n return {\n title: String(title),\n subtitle: formatSubtitle(description),\n icon: 'users',\n badge: t('staff.search.badge.team', 'Team'),\n }\n}\n\nfunction buildTeamMemberPresenter(\n t: TranslateFn,\n record: Record<string, unknown>,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const title =\n pickString(record.display_name, record.displayName, record.name, customFields.display_name, customFields.name) ??\n (record.id as string | undefined) ??\n t('staff.search.badge.teamMember', 'Employee')\n const description = snippet(record.description ?? customFields.description)\n const tags = Array.isArray(record.tags) ? record.tags.join(', ') : undefined\n return {\n title: String(title),\n subtitle: formatSubtitle(description, tags),\n icon: 'user',\n badge: t('staff.search.badge.teamMember', 'Employee'),\n }\n}\n\nfunction buildTeamRolePresenter(\n t: TranslateFn,\n record: Record<string, unknown>,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const title =\n pickString(record.name, record.display_name, record.displayName, customFields.name, customFields.display_name) ??\n (record.id as string | undefined) ??\n t('staff.search.badge.teamRole', 'Role')\n const description = snippet(record.description ?? customFields.description)\n return {\n title: String(title),\n subtitle: formatSubtitle(description),\n icon: 'shield',\n badge: t('staff.search.badge.teamRole', 'Role'),\n }\n}\n\nfunction buildIndexSource(\n ctx: SearchBuildContext,\n presenter: SearchResultPresenter,\n lines: string[],\n): SearchIndexSource | null {\n appendCustomFieldLines(lines, ctx.customFields)\n if (!lines.length) return null\n return {\n text: lines,\n presenter,\n checksumSource: { record: ctx.record, customFields: ctx.customFields },\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'staff:staff_team',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name ?? record.display_name ?? ctx.customFields.name)\n appendLine(lines, 'Description', record.description ?? ctx.customFields.description)\n appendLine(lines, 'Active', record.is_active ?? record.isActive)\n return buildIndexSource(ctx, buildTeamPresenter(t, record, ctx.customFields), lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildTeamPresenter(t, ctx.record, ctx.customFields)\n },\n resolveUrl: async (ctx) => `/backend/staff/teams/${encodeURIComponent(String(ctx.record.id))}/edit`,\n fieldPolicy: {\n searchable: ['name', 'description'],\n },\n },\n {\n entityId: 'staff:staff_team_member',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.display_name ?? record.displayName ?? ctx.customFields.display_name)\n appendLine(lines, 'Description', record.description ?? ctx.customFields.description)\n appendLine(lines, 'Tags', record.tags)\n appendLine(lines, 'Active', record.is_active ?? record.isActive)\n return buildIndexSource(ctx, buildTeamMemberPresenter(t, record, ctx.customFields), lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildTeamMemberPresenter(t, ctx.record, ctx.customFields)\n },\n resolveUrl: async (ctx) => `/backend/staff/team-members/${encodeURIComponent(String(ctx.record.id))}`,\n fieldPolicy: {\n searchable: ['display_name', 'description', 'tags'],\n },\n },\n {\n entityId: 'staff:staff_team_role',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name ?? record.display_name ?? ctx.customFields.name)\n appendLine(lines, 'Description', record.description ?? ctx.customFields.description)\n appendLine(lines, 'Icon', record.appearance_icon ?? record.appearanceIcon)\n appendLine(lines, 'Color', record.appearance_color ?? record.appearanceColor)\n return buildIndexSource(ctx, buildTeamRolePresenter(t, record, ctx.customFields), lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildTeamRolePresenter(t, ctx.record, ctx.customFields)\n },\n resolveUrl: async (ctx) => `/backend/staff/team-roles/${encodeURIComponent(String(ctx.record.id))}/edit`,\n fieldPolicy: {\n searchable: ['name', 'description', 'appearance_icon', 'appearance_color'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchResultPresenter,\n SearchIndexSource,\n} from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction appendCustomFieldLines(lines: string[], customFields: Record<string, unknown>) {\n for (const [key, value] of Object.entries(customFields)) {\n if (value === null || value === undefined) continue\n appendLine(lines, key.replace(/^cf:/, ''), value)\n }\n}\n\nfunction formatSubtitle(...parts: Array<unknown>): string | undefined {\n const text = parts\n .map((part) => (part === null || part === undefined ? '' : String(part)))\n .map((part) => part.trim())\n .filter(Boolean)\n if (text.length === 0) return undefined\n return text.join(' \u00B7 ')\n}\n\nfunction buildTeamPresenter(\n t: TranslateFn,\n record: Record<string, unknown>,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const title =\n pickString(record.name, record.display_name, record.displayName, customFields.name, customFields.display_name) ??\n (record.id as string | undefined) ??\n t('staff.search.badge.team', 'Team')\n const description = snippet(record.description ?? customFields.description)\n return {\n title: String(title),\n subtitle: formatSubtitle(description),\n icon: 'users',\n badge: t('staff.search.badge.team', 'Team'),\n }\n}\n\nfunction buildTeamMemberPresenter(\n t: TranslateFn,\n record: Record<string, unknown>,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const title =\n pickString(record.display_name, record.displayName, record.name, customFields.display_name, customFields.name) ??\n (record.id as string | undefined) ??\n t('staff.search.badge.teamMember', 'Employee')\n const description = snippet(record.description ?? customFields.description)\n const tags = Array.isArray(record.tags) ? record.tags.join(', ') : undefined\n return {\n title: String(title),\n subtitle: formatSubtitle(description, tags),\n icon: 'user',\n badge: t('staff.search.badge.teamMember', 'Employee'),\n }\n}\n\nfunction buildTeamRolePresenter(\n t: TranslateFn,\n record: Record<string, unknown>,\n customFields: Record<string, unknown>,\n): SearchResultPresenter {\n const title =\n pickString(record.name, record.display_name, record.displayName, customFields.name, customFields.display_name) ??\n (record.id as string | undefined) ??\n t('staff.search.badge.teamRole', 'Role')\n const description = snippet(record.description ?? customFields.description)\n return {\n title: String(title),\n subtitle: formatSubtitle(description),\n icon: 'shield',\n badge: t('staff.search.badge.teamRole', 'Role'),\n }\n}\n\nfunction buildIndexSource(\n ctx: SearchBuildContext,\n presenter: SearchResultPresenter,\n lines: string[],\n): SearchIndexSource | null {\n appendCustomFieldLines(lines, ctx.customFields)\n if (!lines.length) return null\n return {\n text: lines,\n presenter,\n checksumSource: { record: ctx.record, customFields: ctx.customFields },\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'staff:staff_team',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name ?? record.display_name ?? ctx.customFields.name)\n appendLine(lines, 'Description', record.description ?? ctx.customFields.description)\n appendLine(lines, 'Active', record.is_active ?? record.isActive)\n return buildIndexSource(ctx, buildTeamPresenter(t, record, ctx.customFields), lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildTeamPresenter(t, ctx.record, ctx.customFields)\n },\n resolveUrl: async (ctx) => `/backend/staff/teams/${encodeURIComponent(String(ctx.record.id))}/edit`,\n fieldPolicy: {\n searchable: ['name', 'description'],\n },\n },\n {\n entityId: 'staff:staff_team_member',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.display_name ?? record.displayName ?? ctx.customFields.display_name)\n appendLine(lines, 'Description', record.description ?? ctx.customFields.description)\n appendLine(lines, 'Tags', record.tags)\n appendLine(lines, 'Active', record.is_active ?? record.isActive)\n return buildIndexSource(ctx, buildTeamMemberPresenter(t, record, ctx.customFields), lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildTeamMemberPresenter(t, ctx.record, ctx.customFields)\n },\n resolveUrl: async (ctx) => `/backend/staff/team-members/${encodeURIComponent(String(ctx.record.id))}`,\n fieldPolicy: {\n searchable: ['display_name', 'description', 'tags'],\n },\n },\n {\n entityId: 'staff:staff_team_role',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name ?? record.display_name ?? ctx.customFields.name)\n appendLine(lines, 'Description', record.description ?? ctx.customFields.description)\n appendLine(lines, 'Icon', record.appearance_icon ?? record.appearanceIcon)\n appendLine(lines, 'Color', record.appearance_color ?? record.appearanceColor)\n return buildIndexSource(ctx, buildTeamRolePresenter(t, record, ctx.customFields), lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildTeamRolePresenter(t, ctx.record, ctx.customFields)\n },\n resolveUrl: async (ctx) => `/backend/staff/team-roles/${encodeURIComponent(String(ctx.record.id))}/edit`,\n fieldPolicy: {\n searchable: ['name', 'description', 'appearance_icon', 'appearance_color'],\n },\n },\n {\n entityId: 'staff:staff_time_project',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'Code', record.code)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'Type', record.project_type ?? record.projectType)\n appendLine(lines, 'Cost Center', record.cost_center ?? record.costCenter)\n const presenter: SearchResultPresenter = {\n title: String(record.name ?? record.id ?? t('staff.search.badge.timeProject', 'Project')),\n subtitle: formatSubtitle(record.code, record.project_type ?? record.projectType),\n icon: 'clock',\n badge: t('staff.search.badge.timeProject', 'Project'),\n }\n return buildIndexSource(ctx, presenter, lines)\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return {\n title: String(ctx.record.name ?? ctx.record.id ?? ''),\n subtitle: formatSubtitle(ctx.record.code, ctx.record.project_type ?? ctx.record.projectType),\n icon: 'clock',\n badge: t('staff.search.badge.timeProject', 'Project'),\n }\n },\n resolveUrl: async (ctx) => `/backend/staff/timesheets/projects/${encodeURIComponent(String(ctx.record.id))}`,\n fieldPolicy: {\n searchable: ['name', 'code', 'description', 'project_type', 'cost_center'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,19 @@
1
+ import { appendWidgetsToRoles } from "@open-mercato/core/modules/dashboards/lib/role-widgets";
1
2
  import { seedStaffAddressTypes, seedStaffTeamExamples } from "./lib/seeds.js";
3
+ const TIMESHEETS_DASHBOARD_WIDGET_IDS = [
4
+ "staff.timesheets.timeReporting",
5
+ "staff.timesheets.hoursByProject"
6
+ ];
2
7
  const setup = {
3
8
  seedDefaults: async (ctx) => {
4
9
  const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId };
5
10
  await seedStaffAddressTypes(ctx.em, scope);
11
+ await appendWidgetsToRoles(ctx.em, {
12
+ tenantId: ctx.tenantId,
13
+ organizationId: ctx.organizationId,
14
+ roleNames: ["superadmin", "admin", "employee"],
15
+ widgetIds: TIMESHEETS_DASHBOARD_WIDGET_IDS
16
+ });
6
17
  },
7
18
  seedExamples: async (ctx) => {
8
19
  const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId };
@@ -15,7 +26,10 @@ const setup = {
15
26
  "staff.my_availability.view",
16
27
  "staff.my_availability.manage",
17
28
  "staff.my_leave_requests.view",
18
- "staff.my_leave_requests.send"
29
+ "staff.my_leave_requests.send",
30
+ "staff.timesheets.view",
31
+ "staff.timesheets.manage_own",
32
+ "staff.timesheets.projects.view"
19
33
  ]
20
34
  }
21
35
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/staff/setup.ts"],
4
- "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { seedStaffAddressTypes, seedStaffTeamExamples } from './lib/seeds'\n\nexport const setup: ModuleSetupConfig = {\n seedDefaults: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffAddressTypes(ctx.em, scope)\n },\n\n seedExamples: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffTeamExamples(ctx.em, scope)\n },\n\n defaultRoleFeatures: {\n admin: ['staff.*', 'staff.leave_requests.manage'],\n employee: [\n 'staff.leave_requests.send',\n 'staff.my_availability.view',\n 'staff.my_availability.manage',\n 'staff.my_leave_requests.view',\n 'staff.my_leave_requests.send',\n ],\n },\n}\n\nexport default setup\n"],
5
- "mappings": "AACA,SAAS,uBAAuB,6BAA6B;AAEtD,MAAM,QAA2B;AAAA,EACtC,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AAAA,EAC3C;AAAA,EAEA,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AAAA,EAC3C;AAAA,EAEA,qBAAqB;AAAA,IACnB,OAAO,CAAC,WAAW,6BAA6B;AAAA,IAChD,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { appendWidgetsToRoles } from '@open-mercato/core/modules/dashboards/lib/role-widgets'\nimport { seedStaffAddressTypes, seedStaffTeamExamples } from './lib/seeds'\n\nconst TIMESHEETS_DASHBOARD_WIDGET_IDS = [\n 'staff.timesheets.timeReporting',\n 'staff.timesheets.hoursByProject',\n]\n\nexport const setup: ModuleSetupConfig = {\n seedDefaults: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffAddressTypes(ctx.em, scope)\n await appendWidgetsToRoles(ctx.em, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n roleNames: ['superadmin', 'admin', 'employee'],\n widgetIds: TIMESHEETS_DASHBOARD_WIDGET_IDS,\n })\n },\n\n seedExamples: async (ctx) => {\n const scope = { tenantId: ctx.tenantId, organizationId: ctx.organizationId }\n await seedStaffTeamExamples(ctx.em, scope)\n },\n\n defaultRoleFeatures: {\n admin: ['staff.*', 'staff.leave_requests.manage'],\n employee: [\n 'staff.leave_requests.send',\n 'staff.my_availability.view',\n 'staff.my_availability.manage',\n 'staff.my_leave_requests.view',\n 'staff.my_leave_requests.send',\n 'staff.timesheets.view',\n 'staff.timesheets.manage_own',\n 'staff.timesheets.projects.view',\n ],\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AACA,SAAS,4BAA4B;AACrC,SAAS,uBAAuB,6BAA6B;AAE7D,MAAM,kCAAkC;AAAA,EACtC;AAAA,EACA;AACF;AAEO,MAAM,QAA2B;AAAA,EACtC,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AACzC,UAAM,qBAAqB,IAAI,IAAI;AAAA,MACjC,UAAU,IAAI;AAAA,MACd,gBAAgB,IAAI;AAAA,MACpB,WAAW,CAAC,cAAc,SAAS,UAAU;AAAA,MAC7C,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,OAAO,QAAQ;AAC3B,UAAM,QAAQ,EAAE,UAAU,IAAI,UAAU,gBAAgB,IAAI,eAAe;AAC3E,UAAM,sBAAsB,IAAI,IAAI,KAAK;AAAA,EAC3C;AAAA,EAEA,qBAAqB;AAAA,IACnB,OAAO,CAAC,WAAW,6BAA6B;AAAA,IAChD,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,16 @@
1
+ import { isValidDateRangePreset } from "@open-mercato/ui/backend/date-range";
2
+ const DEFAULT_SETTINGS = {
3
+ dateRange: "this_month"
4
+ };
5
+ function hydrateSettings(raw) {
6
+ if (!raw || typeof raw !== "object") return { ...DEFAULT_SETTINGS };
7
+ const obj = raw;
8
+ return {
9
+ dateRange: isValidDateRangePreset(obj.dateRange) ? obj.dateRange : DEFAULT_SETTINGS.dateRange
10
+ };
11
+ }
12
+ export {
13
+ DEFAULT_SETTINGS,
14
+ hydrateSettings
15
+ };
16
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts"],
4
+ "sourcesContent": ["import { type DateRangePreset, isValidDateRangePreset } from '@open-mercato/ui/backend/date-range'\n\nexport type HoursByProjectSettings = {\n dateRange: DateRangePreset\n}\n\nexport const DEFAULT_SETTINGS: HoursByProjectSettings = {\n dateRange: 'this_month',\n}\n\nexport function hydrateSettings(raw: unknown): HoursByProjectSettings {\n if (!raw || typeof raw !== 'object') return { ...DEFAULT_SETTINGS }\n const obj = raw as Record<string, unknown>\n return {\n dateRange: isValidDateRangePreset(obj.dateRange) ? obj.dateRange : DEFAULT_SETTINGS.dateRange,\n }\n}\n"],
5
+ "mappings": "AAAA,SAA+B,8BAA8B;AAMtD,MAAM,mBAA2C;AAAA,EACtD,WAAW;AACb;AAEO,SAAS,gBAAgB,KAAsC;AACpE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,EAAE,GAAG,iBAAiB;AAClE,QAAM,MAAM;AACZ,SAAO;AAAA,IACL,WAAW,uBAAuB,IAAI,SAAS,IAAI,IAAI,YAAY,iBAAiB;AAAA,EACtF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,126 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
5
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
6
+ import {
7
+ DateRangeSelect,
8
+ InlineDateRangeSelect
9
+ } from "@open-mercato/ui/backend/date-range";
10
+ import { DEFAULT_SETTINGS, hydrateSettings } from "./config.js";
11
+ function minutesToHours(minutes) {
12
+ const hours = minutes / 60;
13
+ return hours % 1 === 0 ? String(hours) : hours.toFixed(1);
14
+ }
15
+ async function fetchData(settings) {
16
+ const body = {
17
+ entityType: "staff:staff_time_entries",
18
+ metric: { field: "durationMinutes", aggregate: "sum" },
19
+ groupBy: { field: "timeProjectId", limit: 20, resolveLabels: true },
20
+ dateRange: { field: "date", preset: settings.dateRange }
21
+ };
22
+ const res = await apiCall("/api/dashboards/widgets/data", {
23
+ method: "POST",
24
+ headers: { "Content-Type": "application/json" },
25
+ body: JSON.stringify(body)
26
+ });
27
+ if (!res.ok) {
28
+ const err = res.result?.error;
29
+ throw new Error(typeof err === "string" ? err : "Failed to fetch data");
30
+ }
31
+ return res.result;
32
+ }
33
+ const HoursByProjectWidget = ({
34
+ mode,
35
+ settings = DEFAULT_SETTINGS,
36
+ onSettingsChange,
37
+ refreshToken,
38
+ onRefreshStateChange
39
+ }) => {
40
+ const t = useT();
41
+ const hydrated = React.useMemo(() => hydrateSettings(settings), [settings]);
42
+ const [data, setData] = React.useState([]);
43
+ const [totalMinutes, setTotalMinutes] = React.useState(0);
44
+ const [loading, setLoading] = React.useState(true);
45
+ const [error, setError] = React.useState(null);
46
+ const refresh = React.useCallback(async () => {
47
+ onRefreshStateChange?.(true);
48
+ setLoading(true);
49
+ setError(null);
50
+ try {
51
+ const result = await fetchData(hydrated);
52
+ const sorted = [...result.data].sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
53
+ setData(sorted);
54
+ setTotalMinutes(sorted.reduce((sum, item) => sum + (item.value ?? 0), 0));
55
+ } catch (err) {
56
+ console.error("staff.timesheets.hoursByProject", err);
57
+ setError(t("staff.timesheets.widgets.hoursByProject.error", "Failed to load data"));
58
+ } finally {
59
+ setLoading(false);
60
+ onRefreshStateChange?.(false);
61
+ }
62
+ }, [hydrated, onRefreshStateChange, t]);
63
+ React.useEffect(() => {
64
+ void refresh();
65
+ }, [refresh, refreshToken]);
66
+ if (mode === "settings") {
67
+ return /* @__PURE__ */ jsx("div", { className: "space-y-4 text-sm", children: /* @__PURE__ */ jsx(
68
+ DateRangeSelect,
69
+ {
70
+ id: "hours-by-project-date-range",
71
+ label: t("staff.timesheets.widgets.hoursByProject.settings.dateRange", "Date Range"),
72
+ value: hydrated.dateRange,
73
+ onChange: (dateRange) => onSettingsChange({ ...hydrated, dateRange })
74
+ }
75
+ ) });
76
+ }
77
+ if (loading) {
78
+ return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("staff.timesheets.widgets.hoursByProject.loading", "Loading...") }) });
79
+ }
80
+ if (error) {
81
+ return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }) });
82
+ }
83
+ const maxValue = data.length > 0 ? Math.max(...data.map((d) => d.value ?? 0)) : 0;
84
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
85
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ jsx(
86
+ InlineDateRangeSelect,
87
+ {
88
+ value: hydrated.dateRange,
89
+ onChange: (dateRange) => onSettingsChange({ ...hydrated, dateRange })
90
+ }
91
+ ) }),
92
+ data.length === 0 ? /* @__PURE__ */ jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: t("staff.timesheets.widgets.hoursByProject.empty", "No hours tracked in this period.") }) : /* @__PURE__ */ jsxs("div", { className: "space-y-2.5", children: [
93
+ data.map((item) => {
94
+ const barWidth = maxValue > 0 ? (item.value ?? 0) / maxValue * 100 : 0;
95
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
96
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
97
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: item.groupLabel || item.groupKey }),
98
+ /* @__PURE__ */ jsxs("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: [
99
+ minutesToHours(item.value ?? 0),
100
+ " h"
101
+ ] })
102
+ ] }),
103
+ /* @__PURE__ */ jsx("div", { className: "h-2 w-full rounded-full bg-muted", children: /* @__PURE__ */ jsx(
104
+ "div",
105
+ {
106
+ className: "h-2 rounded-full bg-primary transition-all",
107
+ style: { width: `${barWidth}%` }
108
+ }
109
+ ) })
110
+ ] }, item.groupKey);
111
+ }),
112
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t pt-2 text-sm font-semibold", children: [
113
+ /* @__PURE__ */ jsx("span", { children: t("staff.timesheets.widgets.hoursByProject.total", "Total") }),
114
+ /* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
115
+ minutesToHours(totalMinutes),
116
+ " h"
117
+ ] })
118
+ ] })
119
+ ] })
120
+ ] });
121
+ };
122
+ var widget_client_default = HoursByProjectWidget;
123
+ export {
124
+ widget_client_default as default
125
+ };
126
+ //# sourceMappingURL=widget.client.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { DashboardWidgetComponentProps } from '@open-mercato/shared/modules/dashboard/widgets'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n DateRangeSelect,\n InlineDateRangeSelect,\n type DateRangePreset,\n} from '@open-mercato/ui/backend/date-range'\nimport { DEFAULT_SETTINGS, hydrateSettings, type HoursByProjectSettings } from './config'\n\ntype WidgetDataItem = { groupKey: string; groupLabel?: string; value: number | null }\ntype WidgetDataResponse = {\n value: number | null\n data: WidgetDataItem[]\n metadata: { fetchedAt: string; recordCount: number }\n}\n\nfunction minutesToHours(minutes: number): string {\n const hours = minutes / 60\n return hours % 1 === 0 ? String(hours) : hours.toFixed(1)\n}\n\nasync function fetchData(settings: HoursByProjectSettings): Promise<WidgetDataResponse> {\n const body = {\n entityType: 'staff:staff_time_entries',\n metric: { field: 'durationMinutes', aggregate: 'sum' },\n groupBy: { field: 'timeProjectId', limit: 20, resolveLabels: true },\n dateRange: { field: 'date', preset: settings.dateRange },\n }\n\n const res = await apiCall<WidgetDataResponse>('/api/dashboards/widgets/data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n\n if (!res.ok) {\n const err = (res.result as Record<string, unknown>)?.error\n throw new Error(typeof err === 'string' ? err : 'Failed to fetch data')\n }\n\n return res.result as WidgetDataResponse\n}\n\nconst HoursByProjectWidget: React.FC<DashboardWidgetComponentProps<HoursByProjectSettings>> = ({\n mode,\n settings = DEFAULT_SETTINGS,\n onSettingsChange,\n refreshToken,\n onRefreshStateChange,\n}) => {\n const t = useT()\n const hydrated = React.useMemo(() => hydrateSettings(settings), [settings])\n const [data, setData] = React.useState<WidgetDataItem[]>([])\n const [totalMinutes, setTotalMinutes] = React.useState(0)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n const refresh = React.useCallback(async () => {\n onRefreshStateChange?.(true)\n setLoading(true)\n setError(null)\n try {\n const result = await fetchData(hydrated)\n const sorted = [...result.data].sort((a, b) => (b.value ?? 0) - (a.value ?? 0))\n setData(sorted)\n setTotalMinutes(sorted.reduce((sum, item) => sum + (item.value ?? 0), 0))\n } catch (err) {\n console.error('staff.timesheets.hoursByProject', err)\n setError(t('staff.timesheets.widgets.hoursByProject.error', 'Failed to load data'))\n } finally {\n setLoading(false)\n onRefreshStateChange?.(false)\n }\n }, [hydrated, onRefreshStateChange, t])\n\n React.useEffect(() => {\n void refresh()\n }, [refresh, refreshToken])\n\n if (mode === 'settings') {\n return (\n <div className=\"space-y-4 text-sm\">\n <DateRangeSelect\n id=\"hours-by-project-date-range\"\n label={t('staff.timesheets.widgets.hoursByProject.settings.dateRange', 'Date Range')}\n value={hydrated.dateRange}\n onChange={(dateRange: DateRangePreset) => onSettingsChange({ ...hydrated, dateRange })}\n />\n </div>\n )\n }\n\n if (loading) {\n return (\n <div className=\"flex h-full items-center justify-center py-8\">\n <p className=\"text-sm text-muted-foreground\">{t('staff.timesheets.widgets.hoursByProject.loading', 'Loading...')}</p>\n </div>\n )\n }\n\n if (error) {\n return (\n <div className=\"flex h-full items-center justify-center py-8\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n )\n }\n\n const maxValue = data.length > 0 ? Math.max(...data.map((d) => d.value ?? 0)) : 0\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-end\">\n <InlineDateRangeSelect\n value={hydrated.dateRange}\n onChange={(dateRange) => onSettingsChange({ ...hydrated, dateRange })}\n />\n </div>\n\n {data.length === 0 ? (\n <p className=\"py-4 text-center text-sm text-muted-foreground\">\n {t('staff.timesheets.widgets.hoursByProject.empty', 'No hours tracked in this period.')}\n </p>\n ) : (\n <div className=\"space-y-2.5\">\n {data.map((item) => {\n const barWidth = maxValue > 0 ? ((item.value ?? 0) / maxValue) * 100 : 0\n return (\n <div key={item.groupKey} className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"truncate font-medium\">{item.groupLabel || item.groupKey}</span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">{minutesToHours(item.value ?? 0)} h</span>\n </div>\n <div className=\"h-2 w-full rounded-full bg-muted\">\n <div\n className=\"h-2 rounded-full bg-primary transition-all\"\n style={{ width: `${barWidth}%` }}\n />\n </div>\n </div>\n )\n })}\n\n <div className=\"flex items-center justify-between border-t pt-2 text-sm font-semibold\">\n <span>{t('staff.timesheets.widgets.hoursByProject.total', 'Total')}</span>\n <span className=\"tabular-nums\">{minutesToHours(totalMinutes)} h</span>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default HoursByProjectWidget\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { lazyDashboardWidget } from "@open-mercato/shared/modules/dashboard/widgets";
2
+ import { DEFAULT_SETTINGS, hydrateSettings } from "./config.js";
3
+ const HoursByProjectWidget = lazyDashboardWidget(() => import("./widget.client.js"));
4
+ const widget = {
5
+ metadata: {
6
+ id: "staff.timesheets.hoursByProject",
7
+ title: "Hours by Project",
8
+ description: "Tracked hours grouped by project for a selected period",
9
+ features: ["dashboards.view", "analytics.view", "staff.timesheets.view"],
10
+ defaultSize: "md",
11
+ defaultEnabled: false,
12
+ defaultSettings: DEFAULT_SETTINGS,
13
+ tags: ["analytics", "staff", "timesheets"],
14
+ category: "analytics",
15
+ icon: "clock",
16
+ supportsRefresh: true
17
+ },
18
+ Widget: HoursByProjectWidget,
19
+ hydrateSettings,
20
+ dehydrateSettings: (s) => ({ dateRange: s.dateRange })
21
+ };
22
+ var widget_default = widget;
23
+ export {
24
+ widget_default as default
25
+ };
26
+ //# sourceMappingURL=widget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts"],
4
+ "sourcesContent": ["import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'\nimport { DEFAULT_SETTINGS, hydrateSettings, type HoursByProjectSettings } from './config'\n\nconst HoursByProjectWidget = lazyDashboardWidget(() => import('./widget.client'))\n\nconst widget: DashboardWidgetModule<HoursByProjectSettings> = {\n metadata: {\n id: 'staff.timesheets.hoursByProject',\n title: 'Hours by Project',\n description: 'Tracked hours grouped by project for a selected period',\n features: ['dashboards.view', 'analytics.view', 'staff.timesheets.view'],\n defaultSize: 'md',\n defaultEnabled: false,\n defaultSettings: DEFAULT_SETTINGS,\n tags: ['analytics', 'staff', 'timesheets'],\n category: 'analytics',\n icon: 'clock',\n supportsRefresh: true,\n },\n Widget: HoursByProjectWidget,\n hydrateSettings,\n dehydrateSettings: (s) => ({ dateRange: s.dateRange }),\n}\n\nexport default widget\n"],
5
+ "mappings": "AAAA,SAAS,2BAAuD;AAChE,SAAS,kBAAkB,uBAAoD;AAE/E,MAAM,uBAAuB,oBAAoB,MAAM,OAAO,iBAAiB,CAAC;AAEhF,MAAM,SAAwD;AAAA,EAC5D,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU,CAAC,mBAAmB,kBAAkB,uBAAuB;AAAA,IACvE,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,MAAM,CAAC,aAAa,SAAS,YAAY;AAAA,IACzC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,iBAAiB;AAAA,EACnB;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU;AACtD;AAEA,IAAO,iBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,15 @@
1
+ const DEFAULT_SETTINGS = {
2
+ lastProjectId: null
3
+ };
4
+ function hydrateSettings(raw) {
5
+ if (!raw || typeof raw !== "object") return { ...DEFAULT_SETTINGS };
6
+ const obj = raw;
7
+ return {
8
+ lastProjectId: typeof obj.lastProjectId === "string" ? obj.lastProjectId : null
9
+ };
10
+ }
11
+ export {
12
+ DEFAULT_SETTINGS,
13
+ hydrateSettings
14
+ };
15
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts"],
4
+ "sourcesContent": ["export type TimeReportingSettings = {\n lastProjectId: string | null\n}\n\nexport const DEFAULT_SETTINGS: TimeReportingSettings = {\n lastProjectId: null,\n}\n\nexport function hydrateSettings(raw: unknown): TimeReportingSettings {\n if (!raw || typeof raw !== 'object') return { ...DEFAULT_SETTINGS }\n const obj = raw as Record<string, unknown>\n return {\n lastProjectId: typeof obj.lastProjectId === 'string' ? obj.lastProjectId : null,\n }\n}\n"],
5
+ "mappings": "AAIO,MAAM,mBAA0C;AAAA,EACrD,eAAe;AACjB;AAEO,SAAS,gBAAgB,KAAqC;AACnE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,EAAE,GAAG,iBAAiB;AAClE,QAAM,MAAM;AACZ,SAAO;AAAA,IACL,eAAe,OAAO,IAAI,kBAAkB,WAAW,IAAI,gBAAgB;AAAA,EAC7E;AACF;",
6
+ "names": []
7
+ }