@hed-hog/operations 0.0.329 → 0.0.331

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 (290) hide show
  1. package/README.md +5 -5
  2. package/dist/controllers/operations-collaborators.controller.d.ts +7 -216
  3. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
  4. package/dist/controllers/operations-contracts.controller.d.ts +6 -6
  5. package/dist/controllers/operations-projects.controller.d.ts +25 -0
  6. package/dist/controllers/operations-projects.controller.d.ts.map +1 -1
  7. package/dist/controllers/operations-projects.controller.js +48 -0
  8. package/dist/controllers/operations-projects.controller.js.map +1 -1
  9. package/dist/controllers/operations-reports.controller.d.ts +1 -1
  10. package/dist/controllers/operations-tasks.controller.d.ts +30 -5
  11. package/dist/controllers/operations-tasks.controller.d.ts.map +1 -1
  12. package/dist/controllers/operations-tasks.controller.js +43 -32
  13. package/dist/controllers/operations-tasks.controller.js.map +1 -1
  14. package/dist/controllers/operations-timesheets.controller.d.ts +9 -9
  15. package/dist/dashboard/components/DashboardLayout.d.ts +30 -0
  16. package/dist/dashboard/components/DashboardLayout.d.ts.map +1 -0
  17. package/dist/dashboard/components/DashboardLayout.js +87 -0
  18. package/dist/dashboard/components/DashboardLayout.js.map +1 -0
  19. package/dist/dashboard/components/widget-registry.d.ts +23 -0
  20. package/dist/dashboard/components/widget-registry.d.ts.map +1 -0
  21. package/dist/dashboard/components/widget-registry.js +245 -0
  22. package/dist/dashboard/components/widget-registry.js.map +1 -0
  23. package/dist/dashboard/hooks/useDashboardData.d.ts +20 -0
  24. package/dist/dashboard/hooks/useDashboardData.d.ts.map +1 -0
  25. package/dist/dashboard/hooks/useDashboardData.js +24 -0
  26. package/dist/dashboard/hooks/useDashboardData.js.map +1 -0
  27. package/dist/dashboard/types/widgets.types.d.ts +233 -0
  28. package/dist/dashboard/types/widgets.types.d.ts.map +1 -0
  29. package/dist/dashboard/types/widgets.types.js +6 -0
  30. package/dist/dashboard/types/widgets.types.js.map +1 -0
  31. package/dist/dashboard/widgets/CapacityDistribution.d.ts +23 -0
  32. package/dist/dashboard/widgets/CapacityDistribution.d.ts.map +1 -0
  33. package/dist/dashboard/widgets/CapacityDistribution.js +11 -0
  34. package/dist/dashboard/widgets/CapacityDistribution.js.map +1 -0
  35. package/dist/dashboard/widgets/EffortByProject.d.ts +22 -0
  36. package/dist/dashboard/widgets/EffortByProject.d.ts.map +1 -0
  37. package/dist/dashboard/widgets/EffortByProject.js +11 -0
  38. package/dist/dashboard/widgets/EffortByProject.js.map +1 -0
  39. package/dist/dashboard/widgets/HeadcountByArea.d.ts +24 -0
  40. package/dist/dashboard/widgets/HeadcountByArea.d.ts.map +1 -0
  41. package/dist/dashboard/widgets/HeadcountByArea.js +11 -0
  42. package/dist/dashboard/widgets/HeadcountByArea.js.map +1 -0
  43. package/dist/dashboard/widgets/ManagedProjectsStatus.d.ts +18 -0
  44. package/dist/dashboard/widgets/ManagedProjectsStatus.d.ts.map +1 -0
  45. package/dist/dashboard/widgets/ManagedProjectsStatus.js +12 -0
  46. package/dist/dashboard/widgets/ManagedProjectsStatus.js.map +1 -0
  47. package/dist/dashboard/widgets/MyHoursPeriodKpi.d.ts +22 -0
  48. package/dist/dashboard/widgets/MyHoursPeriodKpi.d.ts.map +1 -0
  49. package/dist/dashboard/widgets/MyHoursPeriodKpi.js +12 -0
  50. package/dist/dashboard/widgets/MyHoursPeriodKpi.js.map +1 -0
  51. package/dist/dashboard/widgets/MyOpenRequestsKpi.d.ts +19 -0
  52. package/dist/dashboard/widgets/MyOpenRequestsKpi.d.ts.map +1 -0
  53. package/dist/dashboard/widgets/MyOpenRequestsKpi.js +17 -0
  54. package/dist/dashboard/widgets/MyOpenRequestsKpi.js.map +1 -0
  55. package/dist/dashboard/widgets/MyPendingRequestsList.d.ts +23 -0
  56. package/dist/dashboard/widgets/MyPendingRequestsList.d.ts.map +1 -0
  57. package/dist/dashboard/widgets/MyPendingRequestsList.js +14 -0
  58. package/dist/dashboard/widgets/MyPendingRequestsList.js.map +1 -0
  59. package/dist/dashboard/widgets/MyProjectAllocationsKpi.d.ts +22 -0
  60. package/dist/dashboard/widgets/MyProjectAllocationsKpi.d.ts.map +1 -0
  61. package/dist/dashboard/widgets/MyProjectAllocationsKpi.js +11 -0
  62. package/dist/dashboard/widgets/MyProjectAllocationsKpi.js.map +1 -0
  63. package/dist/dashboard/widgets/MyQuickActions.d.ts +23 -0
  64. package/dist/dashboard/widgets/MyQuickActions.d.ts.map +1 -0
  65. package/dist/dashboard/widgets/MyQuickActions.js +18 -0
  66. package/dist/dashboard/widgets/MyQuickActions.js.map +1 -0
  67. package/dist/dashboard/widgets/MyRelevantDeadlines.d.ts +23 -0
  68. package/dist/dashboard/widgets/MyRelevantDeadlines.d.ts.map +1 -0
  69. package/dist/dashboard/widgets/MyRelevantDeadlines.js +22 -0
  70. package/dist/dashboard/widgets/MyRelevantDeadlines.js.map +1 -0
  71. package/dist/dashboard/widgets/MyTimesheetStatusKpi.d.ts +17 -0
  72. package/dist/dashboard/widgets/MyTimesheetStatusKpi.d.ts.map +1 -0
  73. package/dist/dashboard/widgets/MyTimesheetStatusKpi.js +11 -0
  74. package/dist/dashboard/widgets/MyTimesheetStatusKpi.js.map +1 -0
  75. package/dist/dashboard/widgets/MyWeeklyJourney.d.ts +21 -0
  76. package/dist/dashboard/widgets/MyWeeklyJourney.d.ts.map +1 -0
  77. package/dist/dashboard/widgets/MyWeeklyJourney.js +19 -0
  78. package/dist/dashboard/widgets/MyWeeklyJourney.js.map +1 -0
  79. package/dist/dashboard/widgets/PortfolioCostsKpi.d.ts +19 -0
  80. package/dist/dashboard/widgets/PortfolioCostsKpi.d.ts.map +1 -0
  81. package/dist/dashboard/widgets/PortfolioCostsKpi.js +12 -0
  82. package/dist/dashboard/widgets/PortfolioCostsKpi.js.map +1 -0
  83. package/dist/dashboard/widgets/PortfolioEffortKpi.d.ts +18 -0
  84. package/dist/dashboard/widgets/PortfolioEffortKpi.d.ts.map +1 -0
  85. package/dist/dashboard/widgets/PortfolioEffortKpi.js +8 -0
  86. package/dist/dashboard/widgets/PortfolioEffortKpi.js.map +1 -0
  87. package/dist/dashboard/widgets/PortfolioProjectsKpi.d.ts +22 -0
  88. package/dist/dashboard/widgets/PortfolioProjectsKpi.d.ts.map +1 -0
  89. package/dist/dashboard/widgets/PortfolioProjectsKpi.js +56 -0
  90. package/dist/dashboard/widgets/PortfolioProjectsKpi.js.map +1 -0
  91. package/dist/dashboard/widgets/PortfolioRiskKpi.d.ts +19 -0
  92. package/dist/dashboard/widgets/PortfolioRiskKpi.d.ts.map +1 -0
  93. package/dist/dashboard/widgets/PortfolioRiskKpi.js +11 -0
  94. package/dist/dashboard/widgets/PortfolioRiskKpi.js.map +1 -0
  95. package/dist/dashboard/widgets/ProjectStatusOverview.d.ts +19 -0
  96. package/dist/dashboard/widgets/ProjectStatusOverview.d.ts.map +1 -0
  97. package/dist/dashboard/widgets/ProjectStatusOverview.js +18 -0
  98. package/dist/dashboard/widgets/ProjectStatusOverview.js.map +1 -0
  99. package/dist/dashboard/widgets/StrategicDeadlines.d.ts +24 -0
  100. package/dist/dashboard/widgets/StrategicDeadlines.d.ts.map +1 -0
  101. package/dist/dashboard/widgets/StrategicDeadlines.js +22 -0
  102. package/dist/dashboard/widgets/StrategicDeadlines.js.map +1 -0
  103. package/dist/dashboard/widgets/TeamApprovalQueue.d.ts +24 -0
  104. package/dist/dashboard/widgets/TeamApprovalQueue.d.ts.map +1 -0
  105. package/dist/dashboard/widgets/TeamApprovalQueue.js +12 -0
  106. package/dist/dashboard/widgets/TeamApprovalQueue.js.map +1 -0
  107. package/dist/dashboard/widgets/TeamCapacityKpi.d.ts +18 -0
  108. package/dist/dashboard/widgets/TeamCapacityKpi.d.ts.map +1 -0
  109. package/dist/dashboard/widgets/TeamCapacityKpi.js +19 -0
  110. package/dist/dashboard/widgets/TeamCapacityKpi.js.map +1 -0
  111. package/dist/dashboard/widgets/TeamHeadcountKpi.d.ts +22 -0
  112. package/dist/dashboard/widgets/TeamHeadcountKpi.d.ts.map +1 -0
  113. package/dist/dashboard/widgets/TeamHeadcountKpi.js +56 -0
  114. package/dist/dashboard/widgets/TeamHeadcountKpi.js.map +1 -0
  115. package/dist/dashboard/widgets/TeamHoursKpi.d.ts +19 -0
  116. package/dist/dashboard/widgets/TeamHoursKpi.d.ts.map +1 -0
  117. package/dist/dashboard/widgets/TeamHoursKpi.js +13 -0
  118. package/dist/dashboard/widgets/TeamHoursKpi.js.map +1 -0
  119. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.d.ts +20 -0
  120. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.d.ts.map +1 -0
  121. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.js +11 -0
  122. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.js.map +1 -0
  123. package/dist/dashboard/widgets/TeamUtilizationOverview.d.ts +18 -0
  124. package/dist/dashboard/widgets/TeamUtilizationOverview.d.ts.map +1 -0
  125. package/dist/dashboard/widgets/TeamUtilizationOverview.js +17 -0
  126. package/dist/dashboard/widgets/TeamUtilizationOverview.js.map +1 -0
  127. package/dist/dashboard/widgets/TeamWorkloadAlerts.d.ts +24 -0
  128. package/dist/dashboard/widgets/TeamWorkloadAlerts.d.ts.map +1 -0
  129. package/dist/dashboard/widgets/TeamWorkloadAlerts.js +19 -0
  130. package/dist/dashboard/widgets/TeamWorkloadAlerts.js.map +1 -0
  131. package/dist/dashboard/widgets/index.d.ts +24 -0
  132. package/dist/dashboard/widgets/index.d.ts.map +1 -0
  133. package/dist/dashboard/widgets/index.js +54 -0
  134. package/dist/dashboard/widgets/index.js.map +1 -0
  135. package/dist/dto/create-collaborator.dto.d.ts +0 -1
  136. package/dist/dto/create-collaborator.dto.d.ts.map +1 -1
  137. package/dist/dto/create-collaborator.dto.js +0 -6
  138. package/dist/dto/create-collaborator.dto.js.map +1 -1
  139. package/dist/index.d.ts +2 -0
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +2 -0
  142. package/dist/index.js.map +1 -1
  143. package/dist/operations.controller.d.ts +42 -0
  144. package/dist/operations.controller.d.ts.map +1 -1
  145. package/dist/operations.service.d.ts +178 -264
  146. package/dist/operations.service.d.ts.map +1 -1
  147. package/dist/operations.service.js +2170 -1340
  148. package/dist/operations.service.js.map +1 -1
  149. package/dist/operations.service.spec.js +345 -174
  150. package/dist/operations.service.spec.js.map +1 -1
  151. package/hedhog/data/dashboard_component.yaml +66 -0
  152. package/hedhog/data/dashboard_component_role.yaml +8 -8
  153. package/hedhog/data/dashboard_item.yaml +25 -25
  154. package/hedhog/data/dashboard_role.yaml +1 -1
  155. package/hedhog/data/menu.yaml +6 -16
  156. package/hedhog/data/role.yaml +1 -1
  157. package/hedhog/data/route.yaml +116 -55
  158. package/hedhog/frontend/app/_components/async-options-combobox.tsx.ejs +15 -9
  159. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +39 -99
  160. package/hedhog/frontend/app/_components/collaborator-picker.tsx.ejs +158 -0
  161. package/hedhog/frontend/app/_components/my-project-summary-screen.tsx.ejs +314 -116
  162. package/hedhog/frontend/app/_components/project-assignments-tab.tsx.ejs +434 -449
  163. package/hedhog/frontend/app/_components/project-costs-section.tsx.ejs +51 -81
  164. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +328 -423
  165. package/hedhog/frontend/app/_components/project-file-attachments.tsx.ejs +371 -0
  166. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +446 -377
  167. package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +803 -581
  168. package/hedhog/frontend/app/_components/task-file-attachments.tsx.ejs +14 -9
  169. package/hedhog/frontend/app/_components/task-form-fields.tsx.ejs +406 -0
  170. package/hedhog/frontend/app/_components/task-form-sheet.tsx.ejs +629 -784
  171. package/hedhog/frontend/app/_components/task-info-display.tsx.ejs +137 -0
  172. package/hedhog/frontend/app/_components/timesheet-entry-create-sheet.tsx.ejs +306 -0
  173. package/hedhog/frontend/app/_lib/api.ts.ejs +480 -476
  174. package/hedhog/frontend/app/_lib/hooks/use-values-visibility.ts.ejs +61 -0
  175. package/hedhog/frontend/app/_lib/types.ts.ejs +66 -5
  176. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +0 -2
  177. package/hedhog/frontend/app/_lib/utils/task-ui.ts.ejs +43 -0
  178. package/hedhog/frontend/app/approvals/page.tsx.ejs +11 -2
  179. package/hedhog/frontend/app/collaborator-types/page.tsx.ejs +6 -1
  180. package/hedhog/frontend/app/collaborators/page.tsx.ejs +127 -42
  181. package/hedhog/frontend/app/contracts/page.tsx.ejs +29 -8
  182. package/hedhog/frontend/app/dashboard/widgets/CapacityDistribution.tsx.ejs +84 -0
  183. package/hedhog/frontend/app/dashboard/widgets/EffortByProject.tsx.ejs +85 -0
  184. package/hedhog/frontend/app/dashboard/widgets/HeadcountByArea.tsx.ejs +101 -0
  185. package/hedhog/frontend/app/dashboard/widgets/ManagedProjectsStatus.tsx.ejs +113 -0
  186. package/hedhog/frontend/app/dashboard/widgets/MyHoursPeriodKpi.tsx.ejs +87 -0
  187. package/hedhog/frontend/app/dashboard/widgets/MyOpenRequestsKpi.tsx.ejs +97 -0
  188. package/hedhog/frontend/app/dashboard/widgets/MyPendingRequestsList.tsx.ejs +99 -0
  189. package/hedhog/frontend/app/dashboard/widgets/MyProjectAllocationsKpi.tsx.ejs +78 -0
  190. package/hedhog/frontend/app/dashboard/widgets/MyQuickActions.tsx.ejs +130 -0
  191. package/hedhog/frontend/app/dashboard/widgets/MyRelevantDeadlines.tsx.ejs +144 -0
  192. package/hedhog/frontend/app/dashboard/widgets/MyTimesheetStatusKpi.tsx.ejs +78 -0
  193. package/hedhog/frontend/app/dashboard/widgets/MyWeeklyJourney.tsx.ejs +99 -0
  194. package/hedhog/frontend/app/dashboard/widgets/PortfolioCostsKpi.tsx.ejs +112 -0
  195. package/hedhog/frontend/app/dashboard/widgets/PortfolioEffortKpi.tsx.ejs +93 -0
  196. package/hedhog/frontend/app/dashboard/widgets/PortfolioProjectsKpi.tsx.ejs +96 -0
  197. package/hedhog/frontend/app/dashboard/widgets/PortfolioRiskKpi.tsx.ejs +115 -0
  198. package/hedhog/frontend/app/dashboard/widgets/ProjectStatusOverview.tsx.ejs +120 -0
  199. package/hedhog/frontend/app/dashboard/widgets/StrategicDeadlines.tsx.ejs +146 -0
  200. package/hedhog/frontend/app/dashboard/widgets/TeamApprovalQueue.tsx.ejs +108 -0
  201. package/hedhog/frontend/app/dashboard/widgets/TeamCapacityKpi.tsx.ejs +97 -0
  202. package/hedhog/frontend/app/dashboard/widgets/TeamHeadcountKpi.tsx.ejs +100 -0
  203. package/hedhog/frontend/app/dashboard/widgets/TeamHoursKpi.tsx.ejs +104 -0
  204. package/hedhog/frontend/app/dashboard/widgets/TeamPendingApprovalsKpi.tsx.ejs +110 -0
  205. package/hedhog/frontend/app/dashboard/widgets/TeamUtilizationOverview.tsx.ejs +115 -0
  206. package/hedhog/frontend/app/dashboard/widgets/TeamWorkloadAlerts.tsx.ejs +117 -0
  207. package/hedhog/frontend/app/dashboard/widgets/index.ts.ejs +26 -0
  208. package/hedhog/frontend/app/departments/page.tsx.ejs +6 -1
  209. package/hedhog/frontend/app/my-projects/page.tsx.ejs +59 -16
  210. package/hedhog/frontend/app/my-tasks/page.tsx.ejs +329 -106
  211. package/hedhog/frontend/app/project-cost-categories/page.tsx.ejs +58 -52
  212. package/hedhog/frontend/app/project-cost-types/page.tsx.ejs +58 -51
  213. package/hedhog/frontend/app/projects/page.tsx.ejs +436 -35
  214. package/hedhog/frontend/app/reports/collaborators/page.tsx.ejs +65 -52
  215. package/hedhog/frontend/app/reports/projects/page.tsx.ejs +80 -82
  216. package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +13 -2
  217. package/hedhog/frontend/app/time-off/page.tsx.ejs +6 -1
  218. package/hedhog/frontend/app/timesheets/page.tsx.ejs +10 -4
  219. package/hedhog/frontend/messages/en.json +460 -61
  220. package/hedhog/frontend/messages/operations/en.json +61 -52
  221. package/hedhog/frontend/messages/operations/pt.json +59 -43
  222. package/hedhog/frontend/messages/pt.json +460 -61
  223. package/hedhog/frontend/widgets/capacity-distribution.tsx.ejs +17 -0
  224. package/hedhog/frontend/widgets/effort-by-project.tsx.ejs +17 -0
  225. package/hedhog/frontend/widgets/headcount-by-area.tsx.ejs +17 -0
  226. package/hedhog/frontend/widgets/index.ts.ejs +25 -0
  227. package/hedhog/frontend/widgets/managed-projects-status.tsx.ejs +17 -0
  228. package/hedhog/frontend/widgets/my-hours-period-kpi.tsx.ejs +17 -0
  229. package/hedhog/frontend/widgets/my-open-requests-kpi.tsx.ejs +17 -0
  230. package/hedhog/frontend/widgets/my-pending-requests-list.tsx.ejs +17 -0
  231. package/hedhog/frontend/widgets/my-project-allocations-kpi.tsx.ejs +17 -0
  232. package/hedhog/frontend/widgets/my-quick-actions.tsx.ejs +17 -0
  233. package/hedhog/frontend/widgets/my-relevant-deadlines.tsx.ejs +17 -0
  234. package/hedhog/frontend/widgets/my-timesheet-status-kpi.tsx.ejs +17 -0
  235. package/hedhog/frontend/widgets/my-weekly-journey.tsx.ejs +17 -0
  236. package/hedhog/frontend/widgets/portfolio-costs-kpi.tsx.ejs +17 -0
  237. package/hedhog/frontend/widgets/portfolio-effort-kpi.tsx.ejs +17 -0
  238. package/hedhog/frontend/widgets/portfolio-projects-kpi.tsx.ejs +17 -0
  239. package/hedhog/frontend/widgets/portfolio-risk-kpi.tsx.ejs +17 -0
  240. package/hedhog/frontend/widgets/project-status-overview.tsx.ejs +17 -0
  241. package/hedhog/frontend/widgets/shared-operations-widget.tsx.ejs +170 -0
  242. package/hedhog/frontend/widgets/strategic-deadlines.tsx.ejs +17 -0
  243. package/hedhog/frontend/widgets/team-approval-queue.tsx.ejs +17 -0
  244. package/hedhog/frontend/widgets/team-capacity-kpi.tsx.ejs +17 -0
  245. package/hedhog/frontend/widgets/team-headcount-kpi.tsx.ejs +17 -0
  246. package/hedhog/frontend/widgets/team-hours-kpi.tsx.ejs +17 -0
  247. package/hedhog/frontend/widgets/team-pending-approvals-kpi.tsx.ejs +17 -0
  248. package/hedhog/frontend/widgets/team-utilization-overview.tsx.ejs +17 -0
  249. package/hedhog/frontend/widgets/team-workload-alerts.tsx.ejs +17 -0
  250. package/hedhog/table/operations_collaborator.yaml +8 -13
  251. package/hedhog/table/operations_project.yaml +1 -1
  252. package/hedhog/table/operations_project_file.yaml +23 -0
  253. package/hedhog/table/operations_task.yaml +76 -69
  254. package/hedhog/table/operations_task_activity.yaml +51 -0
  255. package/package.json +7 -6
  256. package/src/controllers/operations-projects.controller.ts +41 -8
  257. package/src/controllers/operations-tasks.controller.ts +156 -166
  258. package/src/dashboard/README.md +214 -0
  259. package/src/dashboard/components/DashboardLayout.tsx +131 -0
  260. package/src/dashboard/components/widget-registry.ts +255 -0
  261. package/src/dashboard/hooks/useDashboardData.ts +29 -0
  262. package/src/dashboard/types/widgets.types.ts +237 -0
  263. package/src/dashboard/widgets/CapacityDistribution.tsx +56 -0
  264. package/src/dashboard/widgets/EffortByProject.tsx +51 -0
  265. package/src/dashboard/widgets/HeadcountByArea.tsx +57 -0
  266. package/src/dashboard/widgets/ManagedProjectsStatus.tsx +53 -0
  267. package/src/dashboard/widgets/MyHoursPeriodKpi.tsx +87 -0
  268. package/src/dashboard/widgets/MyOpenRequestsKpi.tsx +51 -0
  269. package/src/dashboard/widgets/MyPendingRequestsList.tsx +63 -0
  270. package/src/dashboard/widgets/MyProjectAllocationsKpi.tsx +57 -0
  271. package/src/dashboard/widgets/MyQuickActions.tsx +62 -0
  272. package/src/dashboard/widgets/MyRelevantDeadlines.tsx +84 -0
  273. package/src/dashboard/widgets/MyTimesheetStatusKpi.tsx +65 -0
  274. package/src/dashboard/widgets/MyWeeklyJourney.tsx +57 -0
  275. package/src/dashboard/widgets/PortfolioCostsKpi.tsx +48 -0
  276. package/src/dashboard/widgets/PortfolioEffortKpi.tsx +41 -0
  277. package/src/dashboard/widgets/PortfolioRiskKpi.tsx +50 -0
  278. package/src/dashboard/widgets/ProjectStatusOverview.tsx +52 -0
  279. package/src/dashboard/widgets/StrategicDeadlines.tsx +93 -0
  280. package/src/dashboard/widgets/TeamApprovalQueue.tsx +70 -0
  281. package/src/dashboard/widgets/TeamCapacityKpi.tsx +50 -0
  282. package/src/dashboard/widgets/TeamHoursKpi.tsx +51 -0
  283. package/src/dashboard/widgets/TeamPendingApprovalsKpi.tsx +53 -0
  284. package/src/dashboard/widgets/TeamUtilizationOverview.tsx +62 -0
  285. package/src/dashboard/widgets/TeamWorkloadAlerts.tsx +81 -0
  286. package/src/dashboard/widgets/index.ts +26 -0
  287. package/src/dto/create-collaborator.dto.ts +4 -11
  288. package/src/index.ts +3 -0
  289. package/src/operations.service.spec.ts +988 -764
  290. package/src/operations.service.ts +4300 -2538
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useState } from 'react';
4
+
5
+ /**
6
+ * Global sessionStorage key shared across all Operations screens.
7
+ * Changing this constant will reset everyone's saved preference.
8
+ */
9
+ export const OPERATIONS_VALUES_VISIBILITY_KEY = 'operations-values-visible';
10
+
11
+ /**
12
+ * Convenience helper — returns the masked placeholder string.
13
+ * Use wherever a monetary value should be hidden.
14
+ */
15
+ export const MASKED_VALUE = '••••••';
16
+
17
+ /**
18
+ * useValuesVisibility — toggles monetary-value visibility for Operations screens.
19
+ *
20
+ * State is stored in sessionStorage under OPERATIONS_VALUES_VISIBILITY_KEY so it
21
+ * persists across page navigations within the same browser tab but resets when the
22
+ * tab is closed (privacy-first default).
23
+ *
24
+ * Default: hidden (false).
25
+ *
26
+ * Usage:
27
+ * const { valuesVisible, toggleValuesVisible } = useValuesVisibility();
28
+ *
29
+ * // In JSX (eye button):
30
+ * <Button size="icon" variant="ghost" onClick={toggleValuesVisible}>
31
+ * {valuesVisible ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
32
+ * </Button>
33
+ *
34
+ * // Masking a value:
35
+ * value={valuesVisible ? formatCurrency(amount, ...) : MASKED_VALUE}
36
+ */
37
+ export function useValuesVisibility() {
38
+ const [valuesVisible, setValuesVisible] = useState<boolean>(() => {
39
+ try {
40
+ return (
41
+ sessionStorage.getItem(OPERATIONS_VALUES_VISIBILITY_KEY) === 'true'
42
+ );
43
+ } catch {
44
+ return false;
45
+ }
46
+ });
47
+
48
+ const toggleValuesVisible = useCallback(() => {
49
+ setValuesVisible((prev) => {
50
+ const next = !prev;
51
+ try {
52
+ sessionStorage.setItem(OPERATIONS_VALUES_VISIBILITY_KEY, String(next));
53
+ } catch {
54
+ // ignore — storage may be unavailable (e.g. private browsing restrictions)
55
+ }
56
+ return next;
57
+ });
58
+ }, []);
59
+
60
+ return { valuesVisible, toggleValuesVisible };
61
+ }
@@ -20,6 +20,19 @@ export type OperationsTaskComment = {
20
20
  updatedAt: string | null;
21
21
  };
22
22
 
23
+ export type OperationsTaskActivity = {
24
+ id: number;
25
+ taskId: number;
26
+ actorCollaboratorId: number | null;
27
+ actorName: string | null;
28
+ actorUserPhotoId: number | null;
29
+ actorPersonAvatarId: number | null;
30
+ action: string | null;
31
+ fromStatus: string;
32
+ toStatus: string;
33
+ createdAt: string;
34
+ };
35
+
23
36
  export type OperationsDashboard = {
24
37
  actor: {
25
38
  roleScope: 'self' | 'team' | 'full';
@@ -36,6 +49,48 @@ export type OperationsDashboard = {
36
49
  scheduleAdjustmentRequests: number;
37
50
  pendingApprovals: number;
38
51
  };
52
+ windowDays: number;
53
+ taskSummary: {
54
+ total: number;
55
+ backlog: number;
56
+ inProgress: number;
57
+ completed: number;
58
+ };
59
+ avgTaskCompletionHours: number;
60
+ completedTasksInWindow: number;
61
+ hoursInExecution: number;
62
+ timesheetHeatmap: Array<{
63
+ workDate: string;
64
+ weekday: number;
65
+ hours: number;
66
+ }>;
67
+ activeProjects: Array<{
68
+ id: number;
69
+ name: string;
70
+ code?: string | null;
71
+ taskBacklog: number;
72
+ taskInProgress: number;
73
+ taskCompleted: number;
74
+ }>;
75
+ recentTaskActivities: Array<{
76
+ taskId: number;
77
+ taskName: string;
78
+ taskStatus: string;
79
+ taskPriority?: string | null;
80
+ taskDueDate?: string | null;
81
+ taskEstimateHours?: number | null;
82
+ taskTags?: string | null;
83
+ taskAssigneeCollaboratorId?: number | null;
84
+ taskAssigneeName?: string | null;
85
+ projectId: number;
86
+ projectName: string;
87
+ projectCode?: string | null;
88
+ projectAssignmentId?: number | null;
89
+ action?: string | null;
90
+ fromStatus: string;
91
+ toStatus: string;
92
+ createdAt: string;
93
+ }>;
39
94
  recentTimesheets: Array<{
40
95
  id: number;
41
96
  collaboratorName: string;
@@ -260,6 +315,7 @@ export type OperationsCollaborator = {
260
315
  supervisorName?: string | null;
261
316
  contractId?: number | null;
262
317
  contractStatus?: string | null;
318
+ hasUser?: boolean | null;
263
319
  activeAssignments?: number;
264
320
  pendingApprovals?: number;
265
321
  pendingTimeOffRequests?: number;
@@ -354,18 +410,21 @@ export type OperationsTaskOption = {
354
410
  description?: string | null;
355
411
  status: string;
356
412
  priority?: string | null;
413
+ assigneeCollaboratorId?: number | null;
357
414
  projectId: number;
358
415
  projectAssignmentId: number | null;
359
416
  projectName: string;
360
- projectCode?: string | null;
361
- dueDate?: string | null;
362
- estimateHours?: number | null;
363
- tags?: string | null;
364
- assigneeName?: string | null;
417
+ projectCode?: string | null;
418
+ dueDate?: string | null;
419
+ estimateHours?: number | null;
420
+ tags?: string | null;
421
+ assigneeName?: string | null;
365
422
  assigneeUserPhotoId?: number | null;
366
423
  assigneePersonAvatarId?: number | null;
367
424
  commentCount?: number | null;
368
425
  fileCount?: number | null;
426
+ doingStartedAt?: string | null;
427
+ totalDoingMinutes?: number | null;
369
428
  createdAt?: string | null;
370
429
  deletedAt?: string | null;
371
430
  };
@@ -659,6 +718,8 @@ export type OperationsMyProjectSummary = {
659
718
  assigneeUserPhotoId: number | null;
660
719
  assigneePersonAvatarId: number | null;
661
720
  projectAssignmentId: number | null;
721
+ doingStartedAt?: string | null;
722
+ totalDoingMinutes?: number | null;
662
723
  createdAt: string;
663
724
  }>;
664
725
  };
@@ -222,8 +222,6 @@ export function getStatusBadgeClass(value?: string | null) {
222
222
  case 'inactive':
223
223
  case 'on_leave':
224
224
  return 'bg-slate-100 text-slate-800';
225
- case 'at_risk':
226
- return 'bg-orange-100 text-orange-900';
227
225
  default:
228
226
  return 'bg-sky-100 text-sky-800';
229
227
  }
@@ -0,0 +1,43 @@
1
+ export function getTaskPriorityLabel(value?: string | null) {
2
+ const labels: Record<string, string> = {
3
+ low: 'Baixa',
4
+ medium: 'Média',
5
+ high: 'Alta',
6
+ };
7
+ return labels[value ?? ''] ?? String(value ?? '');
8
+ }
9
+
10
+ export function getInitials(value?: string | null) {
11
+ const parts = String(value ?? '')
12
+ .trim()
13
+ .split(/\s+/)
14
+ .filter(Boolean)
15
+ .slice(0, 2);
16
+ if (!parts.length) return '??';
17
+ return parts.map((part) => part[0]?.toUpperCase() ?? '').join('');
18
+ }
19
+
20
+ export function getElapsedDoingMinutes(
21
+ task?: {
22
+ status?: string | null;
23
+ doingStartedAt?: string | null;
24
+ totalDoingMinutes?: number | null;
25
+ } | null,
26
+ tick = 0
27
+ ) {
28
+ void tick;
29
+ const base = Number(task?.totalDoingMinutes ?? 0);
30
+ if (!task || task.status !== 'doing' || !task.doingStartedAt) return base;
31
+ const startedAt = new Date(task.doingStartedAt).getTime();
32
+ if (Number.isNaN(startedAt)) return base;
33
+ return base + Math.max(Math.floor((Date.now() - startedAt) / 60000), 0);
34
+ }
35
+
36
+ export function formatDurationMinutes(minutes?: number | null) {
37
+ const total = Math.max(Number(minutes ?? 0), 0);
38
+ const hours = Math.floor(total / 60);
39
+ const remainingMinutes = total % 60;
40
+ if (hours <= 0) return `${remainingMinutes}min`;
41
+ if (remainingMinutes <= 0) return `${hours}h`;
42
+ return `${hours}h ${remainingMinutes}min`;
43
+ }
@@ -57,6 +57,7 @@ import {
57
57
  import { OperationsHeader } from '../_components/operations-header';
58
58
  import { StatusBadge } from '../_components/status-badge';
59
59
  import { fetchOperations } from '../_lib/api';
60
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
60
61
  import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
61
62
  import type { OperationsApproval, PaginatedResponse } from '../_lib/types';
62
63
  import {
@@ -146,10 +147,12 @@ function SchedulePanel({
146
147
  days,
147
148
  locale,
148
149
  emptyLabel,
150
+ dayOffLabel,
149
151
  }: {
150
152
  days: ScheduleDay[];
151
153
  locale: string;
152
154
  emptyLabel: string;
155
+ dayOffLabel: string;
153
156
  }) {
154
157
  const lines = groupScheduleLines(days, locale);
155
158
  if (!lines.length)
@@ -167,7 +170,7 @@ function SchedulePanel({
167
170
  {line.dayLabel}
168
171
  </span>
169
172
  {line.isOff ? (
170
- <span className="text-muted-foreground">Folga</span>
173
+ <span className="text-muted-foreground">{dayOffLabel}</span>
171
174
  ) : (
172
175
  <span className="text-foreground">
173
176
  {line.time}
@@ -230,7 +233,11 @@ export default function OperationsApprovalsPage() {
230
233
  () => new Date().getMonth() + 1
231
234
  );
232
235
  const [page, setPage] = useState(1);
233
- const [pageSize, setPageSize] = useState(12);
236
+ const [pageSize, setPageSize] = usePersistedPageSize({
237
+ storageKey: 'pagination:operations-approvals:pageSize',
238
+ defaultValue: 12,
239
+ allowedValues: [12, 24, 48],
240
+ });
234
241
  const [viewMode, setViewMode] = useState<'table' | 'cards' | 'calendar'>(
235
242
  () => {
236
243
  if (typeof window === 'undefined') return 'table';
@@ -1176,6 +1183,7 @@ export default function OperationsApprovalsPage() {
1176
1183
  days={selectedApproval.currentSchedule ?? []}
1177
1184
  locale={currentLocaleCode}
1178
1185
  emptyLabel={commonT('labels.notAssigned')}
1186
+ dayOffLabel={commonT('labels.dayOff')}
1179
1187
  />
1180
1188
  </div>
1181
1189
  </div>
@@ -1188,6 +1196,7 @@ export default function OperationsApprovalsPage() {
1188
1196
  days={selectedApproval.days ?? []}
1189
1197
  locale={currentLocaleCode}
1190
1198
  emptyLabel={commonT('labels.notAssigned')}
1199
+ dayOffLabel={commonT('labels.dayOff')}
1191
1200
  />
1192
1201
  </div>
1193
1202
  </div>
@@ -55,6 +55,7 @@ import { useEffect, useMemo, useState } from 'react';
55
55
  import { OperationsHeader } from '../_components/operations-header';
56
56
  import { StatusBadge } from '../_components/status-badge';
57
57
  import { fetchOperations, mutateOperations } from '../_lib/api';
58
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
58
59
  import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
59
60
  import type {
60
61
  OperationsCollaboratorType,
@@ -195,7 +196,11 @@ export default function OperationsCollaboratorTypesPage() {
195
196
  'all' | 'active' | 'inactive'
196
197
  >('all');
197
198
  const [page, setPage] = useState(1);
198
- const [pageSize, setPageSize] = useState(100);
199
+ const [pageSize, setPageSize] = usePersistedPageSize({
200
+ storageKey: 'pagination:operations-collaborator-types:pageSize',
201
+ defaultValue: 100,
202
+ allowedValues: [25, 50, 100, 200],
203
+ });
199
204
  const [viewMode, setViewMode] = useState<'table' | 'cards'>(() => {
200
205
  if (typeof window === 'undefined') return 'table';
201
206
  const saved = window.localStorage.getItem(
@@ -35,6 +35,8 @@ import {
35
35
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
36
36
  import {
37
37
  CalendarDays,
38
+ Eye,
39
+ EyeOff,
38
40
  FileText,
39
41
  Info,
40
42
  LayoutGrid,
@@ -45,6 +47,7 @@ import {
45
47
  UserCheck,
46
48
  UserRound,
47
49
  Users,
50
+ UserX,
48
51
  Wallet,
49
52
  } from 'lucide-react';
50
53
  import { useTranslations } from 'next-intl';
@@ -55,7 +58,12 @@ import { CollaboratorFormScreen } from '../_components/collaborator-form-screen'
55
58
  import { OperationsHeader } from '../_components/operations-header';
56
59
  import { StatusBadge } from '../_components/status-badge';
57
60
  import { fetchOperations, mutateOperations } from '../_lib/api';
61
+ import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
58
62
  import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
63
+ import {
64
+ MASKED_VALUE,
65
+ useValuesVisibility,
66
+ } from '../_lib/hooks/use-values-visibility';
59
67
  import type {
60
68
  OperationsCollaborator,
61
69
  OperationsCollaboratorStats,
@@ -115,7 +123,11 @@ export default function OperationsCollaboratorsPage() {
115
123
  const [statusFilter, setStatusFilter] = useState('all');
116
124
  const [typeFilter, setTypeFilter] = useState('all');
117
125
  const [page, setPage] = useState(1);
118
- const [pageSize, setPageSize] = useState(12);
126
+ const [pageSize, setPageSize] = usePersistedPageSize({
127
+ storageKey: 'pagination:operations-collaborators:pageSize',
128
+ defaultValue: 12,
129
+ allowedValues: [12, 24, 48],
130
+ });
119
131
  const [viewMode, setViewMode] = useState<CollaboratorViewMode>(() => {
120
132
  if (typeof window === 'undefined') {
121
133
  return 'table';
@@ -128,6 +140,7 @@ export default function OperationsCollaboratorsPage() {
128
140
  return savedViewMode === 'cards' ? 'cards' : 'table';
129
141
  });
130
142
  const [isCreateSheetOpen, setIsCreateSheetOpen] = useState(false);
143
+ const { valuesVisible, toggleValuesVisible } = useValuesVisibility();
131
144
 
132
145
  const editParam = searchParams.get('edit');
133
146
  const editingCollaboratorId =
@@ -345,11 +358,13 @@ export default function OperationsCollaboratorsPage() {
345
358
  t('cards.totalSalaryDescription'),
346
359
  t('cards.totalSalaryTooltip')
347
360
  ),
348
- value: formatCurrency(
349
- collaboratorStats?.totalSalary ?? 0,
350
- getSettingValue,
351
- currentLocaleCode
352
- ),
361
+ value: valuesVisible
362
+ ? formatCurrency(
363
+ collaboratorStats?.totalSalary ?? 0,
364
+ getSettingValue,
365
+ currentLocaleCode
366
+ )
367
+ : MASKED_VALUE,
353
368
  icon: Wallet,
354
369
  accentClassName: 'from-emerald-500/20 via-green-500/10 to-transparent',
355
370
  iconContainerClassName:
@@ -362,11 +377,13 @@ export default function OperationsCollaboratorsPage() {
362
377
  t('cards.totalCostsDescription'),
363
378
  t('cards.totalCostsTooltip')
364
379
  ),
365
- value: formatCurrency(
366
- collaboratorStats?.totalCosts ?? 0,
367
- getSettingValue,
368
- currentLocaleCode
369
- ),
380
+ value: valuesVisible
381
+ ? formatCurrency(
382
+ collaboratorStats?.totalCosts ?? 0,
383
+ getSettingValue,
384
+ currentLocaleCode
385
+ )
386
+ : MASKED_VALUE,
370
387
  icon: TrendingUp,
371
388
  accentClassName: 'from-amber-500/20 via-yellow-500/10 to-transparent',
372
389
  iconContainerClassName:
@@ -379,11 +396,13 @@ export default function OperationsCollaboratorsPage() {
379
396
  t('cards.avgSalaryPlusCostsDescription'),
380
397
  t('cards.avgSalaryPlusCostsTooltip')
381
398
  ),
382
- value: formatCurrency(
383
- collaboratorStats?.avgSalaryPlusCosts ?? 0,
384
- getSettingValue,
385
- currentLocaleCode
386
- ),
399
+ value: valuesVisible
400
+ ? formatCurrency(
401
+ collaboratorStats?.avgSalaryPlusCosts ?? 0,
402
+ getSettingValue,
403
+ currentLocaleCode
404
+ )
405
+ : MASKED_VALUE,
387
406
  icon: Wallet,
388
407
  accentClassName: 'from-violet-500/20 via-purple-500/10 to-transparent',
389
408
  iconContainerClassName:
@@ -396,11 +415,13 @@ export default function OperationsCollaboratorsPage() {
396
415
  t('cards.avgSalaryPlusCostsPerCollaboratorDescription'),
397
416
  t('cards.avgSalaryPlusCostsPerCollaboratorTooltip')
398
417
  ),
399
- value: formatCurrency(
400
- collaboratorStats?.avgSalaryPlusCostsPerCollaborator ?? 0,
401
- getSettingValue,
402
- currentLocaleCode
403
- ),
418
+ value: valuesVisible
419
+ ? formatCurrency(
420
+ collaboratorStats?.avgSalaryPlusCostsPerCollaborator ?? 0,
421
+ getSettingValue,
422
+ currentLocaleCode
423
+ )
424
+ : MASKED_VALUE,
404
425
  icon: TrendingUp,
405
426
  accentClassName: 'from-rose-500/20 via-pink-500/10 to-transparent',
406
427
  iconContainerClassName:
@@ -413,6 +434,7 @@ export default function OperationsCollaboratorsPage() {
413
434
  formatCurrency,
414
435
  getSettingValue,
415
436
  currentLocaleCode,
437
+ valuesVisible,
416
438
  ]);
417
439
 
418
440
  const handleViewModeChange = (value: string) => {
@@ -452,13 +474,27 @@ export default function OperationsCollaboratorsPage() {
452
474
  description={t('description')}
453
475
  current={t('breadcrumb')}
454
476
  actions={
455
- access.isDirector ? (
456
- <div className="flex flex-wrap gap-2">
477
+ <div className="flex flex-wrap items-center gap-2">
478
+ <Button
479
+ size="icon"
480
+ variant="ghost"
481
+ onClick={toggleValuesVisible}
482
+ title={commonT(
483
+ valuesVisible ? 'actions.hideValues' : 'actions.showValues'
484
+ )}
485
+ >
486
+ {valuesVisible ? (
487
+ <EyeOff className="h-4 w-4" />
488
+ ) : (
489
+ <Eye className="h-4 w-4" />
490
+ )}
491
+ </Button>
492
+ {access.isDirector ? (
457
493
  <Button size="sm" onClick={openCreateSheet}>
458
494
  {commonT('actions.create')}
459
495
  </Button>
460
- </div>
461
- ) : undefined
496
+ ) : null}
497
+ </div>
462
498
  }
463
499
  />
464
500
 
@@ -620,11 +656,13 @@ export default function OperationsCollaboratorsPage() {
620
656
  {formT('fields.compensationAmount')}:
621
657
  </span>{' '}
622
658
  {collaborator.compensationAmount != null
623
- ? formatCurrency(
624
- Number(collaborator.compensationAmount),
625
- getSettingValue,
626
- currentLocaleCode
627
- )
659
+ ? valuesVisible
660
+ ? formatCurrency(
661
+ Number(collaborator.compensationAmount),
662
+ getSettingValue,
663
+ currentLocaleCode
664
+ )
665
+ : MASKED_VALUE
628
666
  : commonT('labels.notAvailable')}
629
667
  </div>
630
668
  <div>
@@ -653,6 +691,20 @@ export default function OperationsCollaboratorsPage() {
653
691
  </div>
654
692
  ) : null}
655
693
 
694
+ <div className="flex items-center gap-2 text-xs">
695
+ {collaborator.hasUser ? (
696
+ <span className="inline-flex items-center gap-1 font-medium text-emerald-600 dark:text-emerald-400">
697
+ <UserCheck className="size-3.5" />
698
+ {t('columns.linkedUserYes')}
699
+ </span>
700
+ ) : (
701
+ <span className="inline-flex items-center gap-1 font-medium text-muted-foreground">
702
+ <UserX className="size-3.5" />
703
+ {t('columns.linkedUserNo')}
704
+ </span>
705
+ )}
706
+ </div>
707
+
656
708
  <div className="flex items-center justify-end gap-1.5 border-t border-border/60 pt-3">
657
709
  {access.isDirector ? (
658
710
  <Button
@@ -718,14 +770,32 @@ export default function OperationsCollaboratorsPage() {
718
770
  <TableHead className="hidden lg:table-cell">
719
771
  {commonT('labels.supervisor')}
720
772
  </TableHead>
721
- <TableHead className="hidden xl:table-cell">
722
- {commonT('labels.weeklyCapacity')}
773
+ <TableHead className="hidden 2xl:table-cell">
774
+ <span
775
+ className="block truncate"
776
+ title={commonT('labels.weeklyCapacity')}
777
+ >
778
+ {commonT('labels.weeklyCapacity')}
779
+ </span>
780
+ </TableHead>
781
+ <TableHead className="hidden 2xl:table-cell">
782
+ <span
783
+ className="block truncate"
784
+ title={formT('fields.compensationAmount')}
785
+ >
786
+ {formT('fields.compensationAmount')}
787
+ </span>
723
788
  </TableHead>
724
789
  <TableHead className="hidden 2xl:table-cell">
725
- {formT('fields.compensationAmount')}
790
+ <span
791
+ className="block truncate"
792
+ title={commonT('labels.startDate')}
793
+ >
794
+ {commonT('labels.startDate')}
795
+ </span>
726
796
  </TableHead>
727
- <TableHead className="hidden xl:table-cell">
728
- {commonT('labels.startDate')}
797
+ <TableHead className="hidden md:table-cell">
798
+ {t('columns.linkedUser')}
729
799
  </TableHead>
730
800
  <TableHead className="w-30 text-right sm:w-42.5">
731
801
  {commonT('labels.actions')}
@@ -818,25 +888,40 @@ export default function OperationsCollaboratorsPage() {
818
888
  commonT('labels.notAssigned')}
819
889
  </div>
820
890
  </TableCell>
821
- <TableCell className="hidden xl:table-cell">
891
+ <TableCell className="hidden 2xl:table-cell">
822
892
  {formatHours(collaborator.weeklyCapacityHours)}
823
893
  </TableCell>
824
894
  <TableCell className="hidden 2xl:table-cell">
825
895
  {collaborator.compensationAmount != null
826
- ? formatCurrency(
827
- Number(collaborator.compensationAmount),
828
- getSettingValue,
829
- currentLocaleCode
830
- )
896
+ ? valuesVisible
897
+ ? formatCurrency(
898
+ Number(collaborator.compensationAmount),
899
+ getSettingValue,
900
+ currentLocaleCode
901
+ )
902
+ : MASKED_VALUE
831
903
  : commonT('labels.notAvailable')}
832
904
  </TableCell>
833
- <TableCell className="hidden xl:table-cell">
905
+ <TableCell className="hidden 2xl:table-cell">
834
906
  {formatDate(
835
907
  collaborator.joinedAt,
836
908
  getSettingValue,
837
909
  currentLocaleCode
838
910
  )}
839
911
  </TableCell>
912
+ <TableCell className="hidden md:table-cell">
913
+ {collaborator.hasUser ? (
914
+ <span className="inline-flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-400">
915
+ <UserCheck className="size-3.5" />
916
+ {t('columns.linkedUserYes')}
917
+ </span>
918
+ ) : (
919
+ <span className="inline-flex items-center gap-1 text-xs font-medium text-muted-foreground">
920
+ <UserX className="size-3.5" />
921
+ {t('columns.linkedUserNo')}
922
+ </span>
923
+ )}
924
+ </TableCell>
840
925
  <TableCell>
841
926
  <div className="flex items-center justify-end gap-1.5">
842
927
  {access.isDirector ? (