@hed-hog/operations 0.0.330 → 0.0.332

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 (320) hide show
  1. package/README.md +5 -5
  2. package/dist/controllers/operations-collaborators.controller.d.ts +58 -213
  3. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
  4. package/dist/controllers/operations-collaborators.controller.js +100 -0
  5. package/dist/controllers/operations-collaborators.controller.js.map +1 -1
  6. package/dist/controllers/operations-contracts.controller.d.ts +6 -6
  7. package/dist/controllers/operations-projects.controller.d.ts +25 -0
  8. package/dist/controllers/operations-projects.controller.d.ts.map +1 -1
  9. package/dist/controllers/operations-projects.controller.js +48 -0
  10. package/dist/controllers/operations-projects.controller.js.map +1 -1
  11. package/dist/controllers/operations-reports.controller.d.ts +1 -1
  12. package/dist/controllers/operations-tasks.controller.d.ts +34 -9
  13. package/dist/controllers/operations-tasks.controller.d.ts.map +1 -1
  14. package/dist/controllers/operations-tasks.controller.js +43 -32
  15. package/dist/controllers/operations-tasks.controller.js.map +1 -1
  16. package/dist/controllers/operations-timesheets.controller.d.ts +9 -9
  17. package/dist/dashboard/components/DashboardLayout.d.ts +30 -0
  18. package/dist/dashboard/components/DashboardLayout.d.ts.map +1 -0
  19. package/dist/dashboard/components/DashboardLayout.js +87 -0
  20. package/dist/dashboard/components/DashboardLayout.js.map +1 -0
  21. package/dist/dashboard/components/widget-registry.d.ts +23 -0
  22. package/dist/dashboard/components/widget-registry.d.ts.map +1 -0
  23. package/dist/dashboard/components/widget-registry.js +245 -0
  24. package/dist/dashboard/components/widget-registry.js.map +1 -0
  25. package/dist/dashboard/hooks/useDashboardData.d.ts +20 -0
  26. package/dist/dashboard/hooks/useDashboardData.d.ts.map +1 -0
  27. package/dist/dashboard/hooks/useDashboardData.js +24 -0
  28. package/dist/dashboard/hooks/useDashboardData.js.map +1 -0
  29. package/dist/dashboard/types/widgets.types.d.ts +233 -0
  30. package/dist/dashboard/types/widgets.types.d.ts.map +1 -0
  31. package/dist/dashboard/types/widgets.types.js +6 -0
  32. package/dist/dashboard/types/widgets.types.js.map +1 -0
  33. package/dist/dashboard/widgets/CapacityDistribution.d.ts +23 -0
  34. package/dist/dashboard/widgets/CapacityDistribution.d.ts.map +1 -0
  35. package/dist/dashboard/widgets/CapacityDistribution.js +11 -0
  36. package/dist/dashboard/widgets/CapacityDistribution.js.map +1 -0
  37. package/dist/dashboard/widgets/EffortByProject.d.ts +22 -0
  38. package/dist/dashboard/widgets/EffortByProject.d.ts.map +1 -0
  39. package/dist/dashboard/widgets/EffortByProject.js +11 -0
  40. package/dist/dashboard/widgets/EffortByProject.js.map +1 -0
  41. package/dist/dashboard/widgets/HeadcountByArea.d.ts +24 -0
  42. package/dist/dashboard/widgets/HeadcountByArea.d.ts.map +1 -0
  43. package/dist/dashboard/widgets/HeadcountByArea.js +11 -0
  44. package/dist/dashboard/widgets/HeadcountByArea.js.map +1 -0
  45. package/dist/dashboard/widgets/ManagedProjectsStatus.d.ts +18 -0
  46. package/dist/dashboard/widgets/ManagedProjectsStatus.d.ts.map +1 -0
  47. package/dist/dashboard/widgets/ManagedProjectsStatus.js +12 -0
  48. package/dist/dashboard/widgets/ManagedProjectsStatus.js.map +1 -0
  49. package/dist/dashboard/widgets/MyHoursPeriodKpi.d.ts +22 -0
  50. package/dist/dashboard/widgets/MyHoursPeriodKpi.d.ts.map +1 -0
  51. package/dist/dashboard/widgets/MyHoursPeriodKpi.js +12 -0
  52. package/dist/dashboard/widgets/MyHoursPeriodKpi.js.map +1 -0
  53. package/dist/dashboard/widgets/MyOpenRequestsKpi.d.ts +19 -0
  54. package/dist/dashboard/widgets/MyOpenRequestsKpi.d.ts.map +1 -0
  55. package/dist/dashboard/widgets/MyOpenRequestsKpi.js +17 -0
  56. package/dist/dashboard/widgets/MyOpenRequestsKpi.js.map +1 -0
  57. package/dist/dashboard/widgets/MyPendingRequestsList.d.ts +23 -0
  58. package/dist/dashboard/widgets/MyPendingRequestsList.d.ts.map +1 -0
  59. package/dist/dashboard/widgets/MyPendingRequestsList.js +14 -0
  60. package/dist/dashboard/widgets/MyPendingRequestsList.js.map +1 -0
  61. package/dist/dashboard/widgets/MyProjectAllocationsKpi.d.ts +22 -0
  62. package/dist/dashboard/widgets/MyProjectAllocationsKpi.d.ts.map +1 -0
  63. package/dist/dashboard/widgets/MyProjectAllocationsKpi.js +11 -0
  64. package/dist/dashboard/widgets/MyProjectAllocationsKpi.js.map +1 -0
  65. package/dist/dashboard/widgets/MyQuickActions.d.ts +23 -0
  66. package/dist/dashboard/widgets/MyQuickActions.d.ts.map +1 -0
  67. package/dist/dashboard/widgets/MyQuickActions.js +18 -0
  68. package/dist/dashboard/widgets/MyQuickActions.js.map +1 -0
  69. package/dist/dashboard/widgets/MyRelevantDeadlines.d.ts +23 -0
  70. package/dist/dashboard/widgets/MyRelevantDeadlines.d.ts.map +1 -0
  71. package/dist/dashboard/widgets/MyRelevantDeadlines.js +22 -0
  72. package/dist/dashboard/widgets/MyRelevantDeadlines.js.map +1 -0
  73. package/dist/dashboard/widgets/MyTimesheetStatusKpi.d.ts +17 -0
  74. package/dist/dashboard/widgets/MyTimesheetStatusKpi.d.ts.map +1 -0
  75. package/dist/dashboard/widgets/MyTimesheetStatusKpi.js +11 -0
  76. package/dist/dashboard/widgets/MyTimesheetStatusKpi.js.map +1 -0
  77. package/dist/dashboard/widgets/MyWeeklyJourney.d.ts +21 -0
  78. package/dist/dashboard/widgets/MyWeeklyJourney.d.ts.map +1 -0
  79. package/dist/dashboard/widgets/MyWeeklyJourney.js +19 -0
  80. package/dist/dashboard/widgets/MyWeeklyJourney.js.map +1 -0
  81. package/dist/dashboard/widgets/PortfolioCostsKpi.d.ts +19 -0
  82. package/dist/dashboard/widgets/PortfolioCostsKpi.d.ts.map +1 -0
  83. package/dist/dashboard/widgets/PortfolioCostsKpi.js +12 -0
  84. package/dist/dashboard/widgets/PortfolioCostsKpi.js.map +1 -0
  85. package/dist/dashboard/widgets/PortfolioEffortKpi.d.ts +18 -0
  86. package/dist/dashboard/widgets/PortfolioEffortKpi.d.ts.map +1 -0
  87. package/dist/dashboard/widgets/PortfolioEffortKpi.js +8 -0
  88. package/dist/dashboard/widgets/PortfolioEffortKpi.js.map +1 -0
  89. package/dist/dashboard/widgets/PortfolioProjectsKpi.d.ts +22 -0
  90. package/dist/dashboard/widgets/PortfolioProjectsKpi.d.ts.map +1 -0
  91. package/dist/dashboard/widgets/PortfolioProjectsKpi.js +56 -0
  92. package/dist/dashboard/widgets/PortfolioProjectsKpi.js.map +1 -0
  93. package/dist/dashboard/widgets/PortfolioRiskKpi.d.ts +19 -0
  94. package/dist/dashboard/widgets/PortfolioRiskKpi.d.ts.map +1 -0
  95. package/dist/dashboard/widgets/PortfolioRiskKpi.js +11 -0
  96. package/dist/dashboard/widgets/PortfolioRiskKpi.js.map +1 -0
  97. package/dist/dashboard/widgets/ProjectStatusOverview.d.ts +19 -0
  98. package/dist/dashboard/widgets/ProjectStatusOverview.d.ts.map +1 -0
  99. package/dist/dashboard/widgets/ProjectStatusOverview.js +18 -0
  100. package/dist/dashboard/widgets/ProjectStatusOverview.js.map +1 -0
  101. package/dist/dashboard/widgets/StrategicDeadlines.d.ts +24 -0
  102. package/dist/dashboard/widgets/StrategicDeadlines.d.ts.map +1 -0
  103. package/dist/dashboard/widgets/StrategicDeadlines.js +22 -0
  104. package/dist/dashboard/widgets/StrategicDeadlines.js.map +1 -0
  105. package/dist/dashboard/widgets/TeamApprovalQueue.d.ts +24 -0
  106. package/dist/dashboard/widgets/TeamApprovalQueue.d.ts.map +1 -0
  107. package/dist/dashboard/widgets/TeamApprovalQueue.js +12 -0
  108. package/dist/dashboard/widgets/TeamApprovalQueue.js.map +1 -0
  109. package/dist/dashboard/widgets/TeamCapacityKpi.d.ts +18 -0
  110. package/dist/dashboard/widgets/TeamCapacityKpi.d.ts.map +1 -0
  111. package/dist/dashboard/widgets/TeamCapacityKpi.js +19 -0
  112. package/dist/dashboard/widgets/TeamCapacityKpi.js.map +1 -0
  113. package/dist/dashboard/widgets/TeamHeadcountKpi.d.ts +22 -0
  114. package/dist/dashboard/widgets/TeamHeadcountKpi.d.ts.map +1 -0
  115. package/dist/dashboard/widgets/TeamHeadcountKpi.js +56 -0
  116. package/dist/dashboard/widgets/TeamHeadcountKpi.js.map +1 -0
  117. package/dist/dashboard/widgets/TeamHoursKpi.d.ts +19 -0
  118. package/dist/dashboard/widgets/TeamHoursKpi.d.ts.map +1 -0
  119. package/dist/dashboard/widgets/TeamHoursKpi.js +13 -0
  120. package/dist/dashboard/widgets/TeamHoursKpi.js.map +1 -0
  121. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.d.ts +20 -0
  122. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.d.ts.map +1 -0
  123. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.js +11 -0
  124. package/dist/dashboard/widgets/TeamPendingApprovalsKpi.js.map +1 -0
  125. package/dist/dashboard/widgets/TeamUtilizationOverview.d.ts +18 -0
  126. package/dist/dashboard/widgets/TeamUtilizationOverview.d.ts.map +1 -0
  127. package/dist/dashboard/widgets/TeamUtilizationOverview.js +17 -0
  128. package/dist/dashboard/widgets/TeamUtilizationOverview.js.map +1 -0
  129. package/dist/dashboard/widgets/TeamWorkloadAlerts.d.ts +24 -0
  130. package/dist/dashboard/widgets/TeamWorkloadAlerts.d.ts.map +1 -0
  131. package/dist/dashboard/widgets/TeamWorkloadAlerts.js +19 -0
  132. package/dist/dashboard/widgets/TeamWorkloadAlerts.js.map +1 -0
  133. package/dist/dashboard/widgets/index.d.ts +24 -0
  134. package/dist/dashboard/widgets/index.d.ts.map +1 -0
  135. package/dist/dashboard/widgets/index.js +54 -0
  136. package/dist/dashboard/widgets/index.js.map +1 -0
  137. package/dist/dto/create-collaborator-invoice.dto.d.ts +11 -0
  138. package/dist/dto/create-collaborator-invoice.dto.d.ts.map +1 -0
  139. package/dist/dto/create-collaborator-invoice.dto.js +55 -0
  140. package/dist/dto/create-collaborator-invoice.dto.js.map +1 -0
  141. package/dist/dto/create-collaborator-payment.dto.d.ts +10 -0
  142. package/dist/dto/create-collaborator-payment.dto.d.ts.map +1 -0
  143. package/dist/dto/create-collaborator-payment.dto.js +50 -0
  144. package/dist/dto/create-collaborator-payment.dto.js.map +1 -0
  145. package/dist/dto/create-collaborator.dto.d.ts +0 -1
  146. package/dist/dto/create-collaborator.dto.d.ts.map +1 -1
  147. package/dist/dto/create-collaborator.dto.js +0 -6
  148. package/dist/dto/create-collaborator.dto.js.map +1 -1
  149. package/dist/dto/list-collaborator-invoice.dto.d.ts +4 -0
  150. package/dist/dto/list-collaborator-invoice.dto.d.ts.map +1 -0
  151. package/dist/dto/list-collaborator-invoice.dto.js +8 -0
  152. package/dist/dto/list-collaborator-invoice.dto.js.map +1 -0
  153. package/dist/dto/list-collaborator-payment.dto.d.ts +4 -0
  154. package/dist/dto/list-collaborator-payment.dto.d.ts.map +1 -0
  155. package/dist/dto/list-collaborator-payment.dto.js +8 -0
  156. package/dist/dto/list-collaborator-payment.dto.js.map +1 -0
  157. package/dist/dto/update-collaborator-invoice.dto.d.ts +6 -0
  158. package/dist/dto/update-collaborator-invoice.dto.d.ts.map +1 -0
  159. package/dist/dto/update-collaborator-invoice.dto.js +9 -0
  160. package/dist/dto/update-collaborator-invoice.dto.js.map +1 -0
  161. package/dist/dto/update-collaborator-payment.dto.d.ts +6 -0
  162. package/dist/dto/update-collaborator-payment.dto.d.ts.map +1 -0
  163. package/dist/dto/update-collaborator-payment.dto.js +9 -0
  164. package/dist/dto/update-collaborator-payment.dto.js.map +1 -0
  165. package/dist/index.d.ts +2 -0
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +2 -0
  168. package/dist/index.js.map +1 -1
  169. package/dist/operations.controller.d.ts +42 -0
  170. package/dist/operations.controller.d.ts.map +1 -1
  171. package/dist/operations.service.d.ts +258 -268
  172. package/dist/operations.service.d.ts.map +1 -1
  173. package/dist/operations.service.js +2381 -1341
  174. package/dist/operations.service.js.map +1 -1
  175. package/dist/operations.service.spec.js +345 -174
  176. package/dist/operations.service.spec.js.map +1 -1
  177. package/hedhog/data/dashboard_component.yaml +66 -0
  178. package/hedhog/data/dashboard_item.yaml +25 -25
  179. package/hedhog/data/menu.yaml +27 -8
  180. package/hedhog/data/route.yaml +133 -0
  181. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +78 -102
  182. package/hedhog/frontend/app/_components/collaborator-invoices-tab.tsx.ejs +443 -0
  183. package/hedhog/frontend/app/_components/collaborator-payment-history-tab.tsx.ejs +429 -0
  184. package/hedhog/frontend/app/_components/collaborator-picker.tsx.ejs +158 -0
  185. package/hedhog/frontend/app/_components/my-project-summary-screen.tsx.ejs +247 -50
  186. package/hedhog/frontend/app/_components/project-assignments-tab.tsx.ejs +643 -450
  187. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +992 -431
  188. package/hedhog/frontend/app/_components/project-file-attachments.tsx.ejs +371 -0
  189. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +558 -386
  190. package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +383 -157
  191. package/hedhog/frontend/app/_components/task-file-attachments.tsx.ejs +4 -1
  192. package/hedhog/frontend/app/_components/task-form-fields.tsx.ejs +406 -0
  193. package/hedhog/frontend/app/_components/task-form-sheet.tsx.ejs +629 -784
  194. package/hedhog/frontend/app/_components/task-info-display.tsx.ejs +137 -0
  195. package/hedhog/frontend/app/_components/timesheet-entry-create-sheet.tsx.ejs +306 -0
  196. package/hedhog/frontend/app/_lib/api.ts.ejs +155 -0
  197. package/hedhog/frontend/app/_lib/types.ts.ejs +62 -0
  198. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +0 -2
  199. package/hedhog/frontend/app/_lib/utils/task-ui.ts.ejs +61 -0
  200. package/hedhog/frontend/app/approvals/page.tsx.ejs +6 -1
  201. package/hedhog/frontend/app/collaborator-types/page.tsx.ejs +6 -1
  202. package/hedhog/frontend/app/collaborators/page.tsx.ejs +59 -8
  203. package/hedhog/frontend/app/contracts/page.tsx.ejs +29 -8
  204. package/hedhog/frontend/app/dashboard/widgets/CapacityDistribution.tsx.ejs +84 -0
  205. package/hedhog/frontend/app/dashboard/widgets/EffortByProject.tsx.ejs +85 -0
  206. package/hedhog/frontend/app/dashboard/widgets/HeadcountByArea.tsx.ejs +101 -0
  207. package/hedhog/frontend/app/dashboard/widgets/ManagedProjectsStatus.tsx.ejs +113 -0
  208. package/hedhog/frontend/app/dashboard/widgets/MyHoursPeriodKpi.tsx.ejs +87 -0
  209. package/hedhog/frontend/app/dashboard/widgets/MyOpenRequestsKpi.tsx.ejs +97 -0
  210. package/hedhog/frontend/app/dashboard/widgets/MyPendingRequestsList.tsx.ejs +99 -0
  211. package/hedhog/frontend/app/dashboard/widgets/MyProjectAllocationsKpi.tsx.ejs +78 -0
  212. package/hedhog/frontend/app/dashboard/widgets/MyQuickActions.tsx.ejs +130 -0
  213. package/hedhog/frontend/app/dashboard/widgets/MyRelevantDeadlines.tsx.ejs +144 -0
  214. package/hedhog/frontend/app/dashboard/widgets/MyTimesheetStatusKpi.tsx.ejs +78 -0
  215. package/hedhog/frontend/app/dashboard/widgets/MyWeeklyJourney.tsx.ejs +99 -0
  216. package/hedhog/frontend/app/dashboard/widgets/PortfolioCostsKpi.tsx.ejs +112 -0
  217. package/hedhog/frontend/app/dashboard/widgets/PortfolioEffortKpi.tsx.ejs +93 -0
  218. package/hedhog/frontend/app/dashboard/widgets/PortfolioProjectsKpi.tsx.ejs +96 -0
  219. package/hedhog/frontend/app/dashboard/widgets/PortfolioRiskKpi.tsx.ejs +115 -0
  220. package/hedhog/frontend/app/dashboard/widgets/ProjectStatusOverview.tsx.ejs +120 -0
  221. package/hedhog/frontend/app/dashboard/widgets/StrategicDeadlines.tsx.ejs +146 -0
  222. package/hedhog/frontend/app/dashboard/widgets/TeamApprovalQueue.tsx.ejs +108 -0
  223. package/hedhog/frontend/app/dashboard/widgets/TeamCapacityKpi.tsx.ejs +97 -0
  224. package/hedhog/frontend/app/dashboard/widgets/TeamHeadcountKpi.tsx.ejs +100 -0
  225. package/hedhog/frontend/app/dashboard/widgets/TeamHoursKpi.tsx.ejs +104 -0
  226. package/hedhog/frontend/app/dashboard/widgets/TeamPendingApprovalsKpi.tsx.ejs +110 -0
  227. package/hedhog/frontend/app/dashboard/widgets/TeamUtilizationOverview.tsx.ejs +115 -0
  228. package/hedhog/frontend/app/dashboard/widgets/TeamWorkloadAlerts.tsx.ejs +117 -0
  229. package/hedhog/frontend/app/dashboard/widgets/index.ts.ejs +26 -0
  230. package/hedhog/frontend/app/departments/page.tsx.ejs +6 -1
  231. package/hedhog/frontend/app/my-projects/page.tsx.ejs +30 -12
  232. package/hedhog/frontend/app/my-tasks/page.tsx.ejs +286 -125
  233. package/hedhog/frontend/app/project-cost-categories/page.tsx.ejs +58 -52
  234. package/hedhog/frontend/app/project-cost-types/page.tsx.ejs +58 -51
  235. package/hedhog/frontend/app/projects/page.tsx.ejs +415 -33
  236. package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +6 -1
  237. package/hedhog/frontend/app/tasks-gantt/page.tsx.ejs +953 -0
  238. package/hedhog/frontend/app/time-off/page.tsx.ejs +6 -1
  239. package/hedhog/frontend/app/timesheets/page.tsx.ejs +10 -4
  240. package/hedhog/frontend/messages/en.json +332 -46
  241. package/hedhog/frontend/messages/operations/en.json +61 -52
  242. package/hedhog/frontend/messages/operations/pt.json +59 -43
  243. package/hedhog/frontend/messages/pt.json +332 -46
  244. package/hedhog/frontend/widgets/capacity-distribution.tsx.ejs +17 -0
  245. package/hedhog/frontend/widgets/effort-by-project.tsx.ejs +17 -0
  246. package/hedhog/frontend/widgets/headcount-by-area.tsx.ejs +17 -0
  247. package/hedhog/frontend/widgets/index.ts.ejs +25 -0
  248. package/hedhog/frontend/widgets/managed-projects-status.tsx.ejs +17 -0
  249. package/hedhog/frontend/widgets/my-hours-period-kpi.tsx.ejs +17 -0
  250. package/hedhog/frontend/widgets/my-open-requests-kpi.tsx.ejs +17 -0
  251. package/hedhog/frontend/widgets/my-pending-requests-list.tsx.ejs +17 -0
  252. package/hedhog/frontend/widgets/my-project-allocations-kpi.tsx.ejs +17 -0
  253. package/hedhog/frontend/widgets/my-quick-actions.tsx.ejs +17 -0
  254. package/hedhog/frontend/widgets/my-relevant-deadlines.tsx.ejs +17 -0
  255. package/hedhog/frontend/widgets/my-timesheet-status-kpi.tsx.ejs +17 -0
  256. package/hedhog/frontend/widgets/my-weekly-journey.tsx.ejs +17 -0
  257. package/hedhog/frontend/widgets/portfolio-costs-kpi.tsx.ejs +17 -0
  258. package/hedhog/frontend/widgets/portfolio-effort-kpi.tsx.ejs +17 -0
  259. package/hedhog/frontend/widgets/portfolio-projects-kpi.tsx.ejs +17 -0
  260. package/hedhog/frontend/widgets/portfolio-risk-kpi.tsx.ejs +17 -0
  261. package/hedhog/frontend/widgets/project-status-overview.tsx.ejs +17 -0
  262. package/hedhog/frontend/widgets/shared-operations-widget.tsx.ejs +170 -0
  263. package/hedhog/frontend/widgets/strategic-deadlines.tsx.ejs +17 -0
  264. package/hedhog/frontend/widgets/team-approval-queue.tsx.ejs +17 -0
  265. package/hedhog/frontend/widgets/team-capacity-kpi.tsx.ejs +17 -0
  266. package/hedhog/frontend/widgets/team-headcount-kpi.tsx.ejs +17 -0
  267. package/hedhog/frontend/widgets/team-hours-kpi.tsx.ejs +17 -0
  268. package/hedhog/frontend/widgets/team-pending-approvals-kpi.tsx.ejs +17 -0
  269. package/hedhog/frontend/widgets/team-utilization-overview.tsx.ejs +17 -0
  270. package/hedhog/frontend/widgets/team-workload-alerts.tsx.ejs +17 -0
  271. package/hedhog/table/operations_collaborator.yaml +8 -13
  272. package/hedhog/table/operations_collaborator_invoice.yaml +35 -0
  273. package/hedhog/table/operations_collaborator_payment.yaml +32 -0
  274. package/hedhog/table/operations_project.yaml +1 -1
  275. package/hedhog/table/operations_project_file.yaml +23 -0
  276. package/hedhog/table/operations_task.yaml +76 -69
  277. package/hedhog/table/operations_task_activity.yaml +51 -0
  278. package/package.json +6 -5
  279. package/src/controllers/operations-collaborators.controller.ts +117 -8
  280. package/src/controllers/operations-projects.controller.ts +41 -8
  281. package/src/controllers/operations-tasks.controller.ts +156 -166
  282. package/src/dashboard/README.md +214 -0
  283. package/src/dashboard/components/DashboardLayout.tsx +131 -0
  284. package/src/dashboard/components/widget-registry.ts +255 -0
  285. package/src/dashboard/hooks/useDashboardData.ts +29 -0
  286. package/src/dashboard/types/widgets.types.ts +237 -0
  287. package/src/dashboard/widgets/CapacityDistribution.tsx +56 -0
  288. package/src/dashboard/widgets/EffortByProject.tsx +51 -0
  289. package/src/dashboard/widgets/HeadcountByArea.tsx +57 -0
  290. package/src/dashboard/widgets/ManagedProjectsStatus.tsx +53 -0
  291. package/src/dashboard/widgets/MyHoursPeriodKpi.tsx +87 -0
  292. package/src/dashboard/widgets/MyOpenRequestsKpi.tsx +51 -0
  293. package/src/dashboard/widgets/MyPendingRequestsList.tsx +63 -0
  294. package/src/dashboard/widgets/MyProjectAllocationsKpi.tsx +57 -0
  295. package/src/dashboard/widgets/MyQuickActions.tsx +62 -0
  296. package/src/dashboard/widgets/MyRelevantDeadlines.tsx +84 -0
  297. package/src/dashboard/widgets/MyTimesheetStatusKpi.tsx +65 -0
  298. package/src/dashboard/widgets/MyWeeklyJourney.tsx +57 -0
  299. package/src/dashboard/widgets/PortfolioCostsKpi.tsx +48 -0
  300. package/src/dashboard/widgets/PortfolioEffortKpi.tsx +41 -0
  301. package/src/dashboard/widgets/PortfolioRiskKpi.tsx +50 -0
  302. package/src/dashboard/widgets/ProjectStatusOverview.tsx +52 -0
  303. package/src/dashboard/widgets/StrategicDeadlines.tsx +93 -0
  304. package/src/dashboard/widgets/TeamApprovalQueue.tsx +70 -0
  305. package/src/dashboard/widgets/TeamCapacityKpi.tsx +50 -0
  306. package/src/dashboard/widgets/TeamHoursKpi.tsx +51 -0
  307. package/src/dashboard/widgets/TeamPendingApprovalsKpi.tsx +53 -0
  308. package/src/dashboard/widgets/TeamUtilizationOverview.tsx +62 -0
  309. package/src/dashboard/widgets/TeamWorkloadAlerts.tsx +81 -0
  310. package/src/dashboard/widgets/index.ts +26 -0
  311. package/src/dto/create-collaborator-invoice.dto.ts +39 -0
  312. package/src/dto/create-collaborator-payment.dto.ts +35 -0
  313. package/src/dto/create-collaborator.dto.ts +4 -11
  314. package/src/dto/list-collaborator-invoice.dto.ts +3 -0
  315. package/src/dto/list-collaborator-payment.dto.ts +3 -0
  316. package/src/dto/update-collaborator-invoice.dto.ts +6 -0
  317. package/src/dto/update-collaborator-payment.dto.ts +6 -0
  318. package/src/index.ts +3 -0
  319. package/src/operations.service.spec.ts +988 -764
  320. package/src/operations.service.ts +4689 -2624
@@ -0,0 +1,96 @@
1
+ 'use client';
2
+
3
+ import { Briefcase } from 'lucide-react';
4
+ import React from 'react';
5
+
6
+ interface PortfolioProjectsKpiProps {
7
+ slug: string;
8
+ title: string;
9
+ roleSlug: string;
10
+ width?: number;
11
+ height?: number;
12
+ data?: {
13
+ totalProjects: number;
14
+ activeProjects: number;
15
+ completedProjects: number;
16
+ onHoldProjects: number;
17
+ healthyPercent: number;
18
+ };
19
+ style?: React.CSSProperties;
20
+ }
21
+
22
+ const PortfolioProjectsKpi: React.FC<PortfolioProjectsKpiProps> = ({
23
+ title,
24
+ data = {
25
+ totalProjects: 0,
26
+ activeProjects: 0,
27
+ completedProjects: 0,
28
+ onHoldProjects: 0,
29
+ healthyPercent: 0,
30
+ },
31
+ style,
32
+ }) => {
33
+ const activePercent =
34
+ data.totalProjects > 0
35
+ ? Math.round((data.activeProjects / data.totalProjects) * 100)
36
+ : 0;
37
+
38
+ return (
39
+ <div
40
+ className="bg-linear-to-br from-white to-indigo-50 rounded-lg shadow-sm p-4 border border-indigo-100"
41
+ style={style}
42
+ >
43
+ <div className="flex items-center justify-between mb-4">
44
+ <h3 className="text-sm font-medium text-gray-700">{title}</h3>
45
+ <Briefcase className="w-4 h-4 text-indigo-600" />
46
+ </div>
47
+ <div className="bg-linear-to-r from-indigo-500 to-purple-600 rounded-lg p-4 text-white mb-3">
48
+ <div className="flex items-center justify-between">
49
+ <div>
50
+ <div className="text-xs opacity-90">Total de Projetos</div>
51
+ <div className="text-3xl font-bold">{data.totalProjects}</div>
52
+ </div>
53
+ <Briefcase className="w-12 h-12 opacity-30" />
54
+ </div>
55
+ </div>
56
+ <div className="space-y-2">
57
+ <div className="flex justify-between items-center">
58
+ <span className="text-xs font-medium text-gray-700">
59
+ Projetos Ativos
60
+ </span>
61
+ <span className="text-sm font-bold px-2 py-1 rounded-full bg-indigo-100 text-indigo-700">
62
+ {activePercent}%
63
+ </span>
64
+ </div>
65
+ <div className="relative w-full h-4 bg-gray-200 rounded-full overflow-hidden">
66
+ <div
67
+ className="h-full transition-all duration-500 ease-out rounded-full bg-linear-to-r from-indigo-400 to-indigo-600"
68
+ style={{ width: `${activePercent}%` }}
69
+ />
70
+ </div>
71
+ </div>
72
+ <div className="grid grid-cols-3 gap-2 bg-indigo-50 rounded-lg p-3 border border-indigo-200 mt-3">
73
+ <div>
74
+ <div className="text-xs text-gray-600 mb-1">Ativos</div>
75
+ <div className="text-xl font-bold text-indigo-600">
76
+ {data.activeProjects}
77
+ </div>
78
+ </div>
79
+ <div>
80
+ <div className="text-xs text-gray-600 mb-1">Concluídos</div>
81
+ <div className="text-xl font-bold text-green-600">
82
+ {data.completedProjects}
83
+ </div>
84
+ </div>
85
+ <div>
86
+ <div className="text-xs text-gray-600 mb-1">Em Espera</div>
87
+ <div className="text-xl font-bold text-yellow-600">
88
+ {data.onHoldProjects}
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ );
94
+ };
95
+
96
+ export default PortfolioProjectsKpi;
@@ -0,0 +1,115 @@
1
+ 'use client';
2
+
3
+ import { AlertTriangle, TrendingUp } from 'lucide-react';
4
+ import { useTranslations } from 'next-intl';
5
+ import React from 'react';
6
+
7
+ interface PortfolioRiskKpiProps {
8
+ slug: string;
9
+ title: string;
10
+ roleSlug: string;
11
+ width?: number;
12
+ height?: number;
13
+ data?: {
14
+ totalRisks: number;
15
+ criticalRisks: number;
16
+ highRisks: number;
17
+ mediumRisks: number;
18
+ riskTrend: 'increasing' | 'stable' | 'decreasing';
19
+ };
20
+ style?: React.CSSProperties;
21
+ }
22
+
23
+ const PortfolioRiskKpi: React.FC<PortfolioRiskKpiProps> = ({
24
+ title,
25
+ data = {
26
+ totalRisks: 0,
27
+ criticalRisks: 0,
28
+ highRisks: 0,
29
+ mediumRisks: 0,
30
+ riskTrend: 'stable',
31
+ },
32
+ style,
33
+ }) => {
34
+ const t = useTranslations('operations.PortfolioRiskKpi');
35
+ const hasHighRisk = data.criticalRisks > 0 || data.highRisks > 3;
36
+ return (
37
+ <div
38
+ className={`bg-linear-to-br from-white to-red-50 rounded-lg shadow-sm p-4 border ${hasHighRisk ? 'border-red-400 border-2' : 'border-red-100'} transition-all`}
39
+ style={style}
40
+ >
41
+ <div className="flex items-center justify-between mb-4">
42
+ <h3 className="text-sm font-medium text-gray-700">{title}</h3>
43
+ {hasHighRisk && (
44
+ <div className="relative">
45
+ <div
46
+ className="absolute inset-0 bg-red-600 rounded-full animate-pulse"
47
+ style={{ opacity: 0.25 }}
48
+ />
49
+ <AlertTriangle className="w-5 h-5 text-red-600 relative" />
50
+ </div>
51
+ )}
52
+ </div>
53
+ <div
54
+ className={`rounded-lg p-4 ${data.totalRisks > 10 ? 'bg-red-500 text-white' : data.totalRisks > 5 ? 'bg-yellow-500 text-white' : 'bg-green-500 text-white'}`}
55
+ >
56
+ <div className="flex items-center justify-between">
57
+ <div>
58
+ <div className="text-xs opacity-90">{t('label')}</div>
59
+ <div className="text-3xl font-bold">{data.totalRisks}</div>
60
+ </div>
61
+ <AlertTriangle className="w-12 h-12 opacity-30" />
62
+ </div>
63
+ </div>
64
+ <div className="space-y-2 mt-3">
65
+ {data.criticalRisks > 0 && (
66
+ <div className="flex items-center justify-between bg-red-50 p-2 rounded-lg border border-red-200">
67
+ <span className="text-xs font-medium text-red-700">
68
+ {t('critical')}
69
+ </span>
70
+ <span className="text-sm font-bold text-red-600">
71
+ {data.criticalRisks}
72
+ </span>
73
+ </div>
74
+ )}
75
+ {data.highRisks > 0 && (
76
+ <div className="flex items-center justify-between bg-yellow-50 p-2 rounded-lg border border-yellow-200">
77
+ <span className="text-xs font-medium text-yellow-700">
78
+ {t('high')}
79
+ </span>
80
+ <span className="text-sm font-bold text-yellow-600">
81
+ {data.highRisks}
82
+ </span>
83
+ </div>
84
+ )}
85
+ {data.mediumRisks > 0 && (
86
+ <div className="flex items-center justify-between bg-blue-50 p-2 rounded-lg border border-blue-200">
87
+ <span className="text-xs font-medium text-blue-700">
88
+ {t('medium')}
89
+ </span>
90
+ <span className="text-sm font-bold text-blue-600">
91
+ {data.mediumRisks}
92
+ </span>
93
+ </div>
94
+ )}
95
+ </div>
96
+ <div className="flex items-center gap-2 pt-2 border-t border-red-100 mt-3">
97
+ <TrendingUp
98
+ className={`w-4 h-4 ${data.riskTrend === 'increasing' ? 'text-red-600' : data.riskTrend === 'decreasing' ? 'text-green-600' : 'text-gray-600'}`}
99
+ />
100
+ <span className="text-xs font-medium text-gray-700">
101
+ {t('trendLabel')} {data.riskTrend === 'increasing' && t('increasing')}
102
+ {data.riskTrend === 'decreasing' && t('decreasing')}
103
+ {data.riskTrend === 'stable' && t('stable')}
104
+ </span>
105
+ </div>
106
+ {hasHighRisk && (
107
+ <div className="bg-red-100 rounded-lg p-2 border border-red-300 text-xs text-red-700 font-semibold text-center mt-3">
108
+ {t('urgentAttention')}
109
+ </div>
110
+ )}
111
+ </div>
112
+ );
113
+ };
114
+
115
+ export default PortfolioRiskKpi;
@@ -0,0 +1,120 @@
1
+ 'use client';
2
+
3
+ import { CheckCircle2 } from 'lucide-react';
4
+ import { useTranslations } from 'next-intl';
5
+ import React from 'react';
6
+
7
+ interface ProjectStatusOverviewProps {
8
+ slug: string;
9
+ title: string;
10
+ roleSlug: string;
11
+ width?: number;
12
+ height?: number;
13
+ data?: {
14
+ planning: number;
15
+ inProgress: number;
16
+ review: number;
17
+ completed: number;
18
+ onHold: number;
19
+ };
20
+ style?: React.CSSProperties;
21
+ }
22
+
23
+ const ProjectStatusOverview: React.FC<ProjectStatusOverviewProps> = ({
24
+ title,
25
+ data = { planning: 0, inProgress: 0, review: 0, completed: 0, onHold: 0 },
26
+ style,
27
+ }) => {
28
+ const t = useTranslations('operations.ProjectStatusOverview');
29
+ const total =
30
+ data.planning +
31
+ data.inProgress +
32
+ data.review +
33
+ data.completed +
34
+ data.onHold;
35
+ const statuses = [
36
+ {
37
+ label: t('statuses.planning'),
38
+ count: data.planning,
39
+ emoji: '📋',
40
+ color: 'blue',
41
+ width: total > 0 ? (data.planning / total) * 100 : 0,
42
+ },
43
+ {
44
+ label: t('statuses.inProgress'),
45
+ count: data.inProgress,
46
+ emoji: '🚀',
47
+ color: 'green',
48
+ width: total > 0 ? (data.inProgress / total) * 100 : 0,
49
+ },
50
+ {
51
+ label: t('statuses.review'),
52
+ count: data.review,
53
+ emoji: '👀',
54
+ color: 'yellow',
55
+ width: total > 0 ? (data.review / total) * 100 : 0,
56
+ },
57
+ {
58
+ label: t('statuses.completed'),
59
+ count: data.completed,
60
+ emoji: '✅',
61
+ color: 'purple',
62
+ width: total > 0 ? (data.completed / total) * 100 : 0,
63
+ },
64
+ {
65
+ label: t('statuses.onHold'),
66
+ count: data.onHold,
67
+ emoji: '⏸️',
68
+ color: 'gray',
69
+ width: total > 0 ? (data.onHold / total) * 100 : 0,
70
+ },
71
+ ];
72
+
73
+ return (
74
+ <div
75
+ className="bg-linear-to-br from-white to-violet-50 rounded-lg shadow-sm p-4 border border-violet-100"
76
+ style={style}
77
+ >
78
+ <div className="flex items-center justify-between mb-4">
79
+ <h3 className="text-sm font-medium text-gray-700">{title}</h3>
80
+ <CheckCircle2 className="w-4 h-4 text-violet-600" />
81
+ </div>
82
+ <div className="flex gap-1 h-8 rounded-lg overflow-hidden bg-gray-100 border border-gray-200 mb-3">
83
+ {statuses.map(
84
+ (status) =>
85
+ status.width > 0 && (
86
+ <div
87
+ key={status.label}
88
+ className={`bg-${status.color}-500 hover:brightness-110 transition-all`}
89
+ style={{ width: `${status.width}%` }}
90
+ />
91
+ )
92
+ )}
93
+ </div>
94
+ <div className="grid grid-cols-2 gap-2">
95
+ {statuses.map((status) => (
96
+ <div
97
+ key={status.label}
98
+ className={`bg-${status.color}-50 rounded-lg p-3 border border-${status.color}-200`}
99
+ >
100
+ <div className="text-lg mb-1">{status.emoji}</div>
101
+ <div className={`text-2xl font-bold text-${status.color}-600`}>
102
+ {status.count}
103
+ </div>
104
+ <div className="text-xs text-gray-600 truncate">{status.label}</div>
105
+ </div>
106
+ ))}
107
+ </div>
108
+ <div className="pt-2 border-t border-violet-100 mt-3">
109
+ <div className="flex items-center justify-between text-xs">
110
+ <span className="text-gray-700 font-medium">
111
+ {t('totalProjects')}
112
+ </span>
113
+ <span className="text-lg font-bold text-violet-600">{total}</span>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ );
118
+ };
119
+
120
+ export default ProjectStatusOverview;
@@ -0,0 +1,146 @@
1
+ 'use client';
2
+
3
+ import { AlertTriangle, CheckCircle2, Flag } from 'lucide-react';
4
+ import { useTranslations } from 'next-intl';
5
+ import React from 'react';
6
+
7
+ interface StrategicDeadline {
8
+ id: string;
9
+ title: string;
10
+ deadline: string;
11
+ daysLeft: number;
12
+ status: 'on-track' | 'at-risk' | 'critical';
13
+ priority: 'high' | 'critical';
14
+ impact: string;
15
+ }
16
+
17
+ interface StrategicDeadlinesProps {
18
+ slug: string;
19
+ title: string;
20
+ roleSlug: string;
21
+ width?: number;
22
+ height?: number;
23
+ data?: { deadlines: StrategicDeadline[] };
24
+ style?: React.CSSProperties;
25
+ }
26
+
27
+ const StrategicDeadlines: React.FC<StrategicDeadlinesProps> = ({
28
+ title,
29
+ data = { deadlines: [] },
30
+ style,
31
+ }) => {
32
+ const t = useTranslations('operations.StrategicDeadlines');
33
+ const criticalCount = data.deadlines.filter(
34
+ (d) => d.status === 'critical'
35
+ ).length;
36
+ const atRiskCount = data.deadlines.filter(
37
+ (d) => d.status === 'at-risk'
38
+ ).length;
39
+
40
+ const getStatusColor = (status: string) => {
41
+ switch (status) {
42
+ case 'critical':
43
+ return {
44
+ bg: 'bg-red-50',
45
+ border: 'border-red-300 border-l-4',
46
+ dot: 'bg-red-600 animate-pulse',
47
+ };
48
+ case 'at-risk':
49
+ return {
50
+ bg: 'bg-yellow-50',
51
+ border: 'border-yellow-300 border-l-4',
52
+ dot: 'bg-yellow-600',
53
+ };
54
+ default:
55
+ return {
56
+ bg: 'bg-green-50',
57
+ border: 'border-green-300 border-l-4',
58
+ dot: 'bg-green-600',
59
+ };
60
+ }
61
+ };
62
+
63
+ return (
64
+ <div
65
+ className={`bg-linear-to-br from-white to-rose-50 rounded-lg shadow-sm p-4 border ${criticalCount > 0 ? 'border-rose-400 border-2' : 'border-rose-100'} transition-all`}
66
+ style={style}
67
+ >
68
+ <div className="flex items-center justify-between mb-4">
69
+ <h3 className="text-sm font-medium text-gray-700">{title}</h3>
70
+ <Flag className="w-4 h-4 text-rose-600" />
71
+ </div>
72
+ <div className="space-y-3">
73
+ {data.deadlines.length === 0 ? (
74
+ <div className="text-center py-8">
75
+ <CheckCircle2 className="w-8 h-8 text-green-500 mx-auto mb-2" />
76
+ <p className="text-sm text-gray-600">{t('empty')}</p>
77
+ </div>
78
+ ) : (
79
+ <>
80
+ {(criticalCount > 0 || atRiskCount > 0) && (
81
+ <div className="flex gap-2 mb-2">
82
+ {criticalCount > 0 && (
83
+ <div className="bg-red-100 rounded-lg px-3 py-1 text-xs font-bold text-red-700 flex items-center gap-1">
84
+ <AlertTriangle className="w-3 h-3" />
85
+ {criticalCount} crítico{criticalCount !== 1 ? 's' : ''}
86
+ </div>
87
+ )}
88
+ {atRiskCount > 0 && (
89
+ <div className="bg-yellow-100 rounded-lg px-3 py-1 text-xs font-bold text-yellow-700">
90
+ {atRiskCount} em risco
91
+ </div>
92
+ )}
93
+ </div>
94
+ )}
95
+ <div className="space-y-2 max-h-72 overflow-y-auto">
96
+ {data.deadlines.map((deadline) => {
97
+ const colors = getStatusColor(deadline.status);
98
+ return (
99
+ <div
100
+ key={deadline.id}
101
+ className={`${colors.bg} rounded-lg p-3 border ${colors.border} hover:shadow-md transition-all`}
102
+ >
103
+ <div className="flex items-start gap-2">
104
+ <div
105
+ className={`w-3 h-3 rounded-full ${colors.dot} flex-shrink-0 mt-1`}
106
+ />
107
+ <div className="flex-1">
108
+ <div className="flex items-start justify-between gap-2 mb-1">
109
+ <p className="text-sm font-bold text-gray-900 truncate">
110
+ {deadline.title}
111
+ </p>
112
+ <span
113
+ className={`text-xs font-bold px-2 py-1 rounded-full flex-shrink-0 ${deadline.priority === 'critical' ? 'bg-red-100 text-red-700' : 'bg-orange-100 text-orange-700'}`}
114
+ >
115
+ {deadline.priority === 'critical' ? '🔴' : '🟠'}
116
+ </span>
117
+ </div>
118
+ <p className="text-xs text-gray-700 mb-2">
119
+ {deadline.impact}
120
+ </p>
121
+ <div className="flex items-center justify-between text-xs">
122
+ <span className="text-gray-600">
123
+ {deadline.deadline}
124
+ </span>
125
+ <span
126
+ className={`font-bold ${deadline.daysLeft <= 0 ? 'text-red-600' : deadline.daysLeft <= 7 ? 'text-orange-600' : 'text-gray-600'}`}
127
+ >
128
+ {deadline.daysLeft <= 0
129
+ ? '❌ Vencido'
130
+ : `⏱️ ${deadline.daysLeft}d`}
131
+ </span>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ );
137
+ })}
138
+ </div>
139
+ </>
140
+ )}
141
+ </div>
142
+ </div>
143
+ );
144
+ };
145
+
146
+ export default StrategicDeadlines;
@@ -0,0 +1,108 @@
1
+ 'use client';
2
+
3
+ import { Calendar, CheckCircle2, User } from 'lucide-react';
4
+ import { useTranslations } from 'next-intl';
5
+ import React from 'react';
6
+
7
+ interface ApprovalItem {
8
+ id: string;
9
+ type: string;
10
+ submittedBy: string;
11
+ submittedDate: string;
12
+ daysWaiting: number;
13
+ priority: 'high' | 'normal';
14
+ }
15
+
16
+ interface TeamApprovalQueueProps {
17
+ slug: string;
18
+ title: string;
19
+ roleSlug: string;
20
+ width?: number;
21
+ height?: number;
22
+ data?: { queue: ApprovalItem[]; totalPending: number };
23
+ style?: React.CSSProperties;
24
+ }
25
+
26
+ const TeamApprovalQueue: React.FC<TeamApprovalQueueProps> = ({
27
+ title,
28
+ data = { queue: [], totalPending: 0 },
29
+ style,
30
+ }) => {
31
+ const t = useTranslations('operations.TeamApprovalQueue');
32
+ const getTypeIcon = (type: string) =>
33
+ ({ timesheet: '⏱️', expense: '💰', vacation: '🏖️', schedule: '📅' })[
34
+ type
35
+ ] || '📋';
36
+ const getTypeLabel = (type: string) =>
37
+ (t.raw('typeLabels') as Record<string, string>)[type] || type;
38
+
39
+ return (
40
+ <div
41
+ className="bg-linear-to-br from-white to-purple-50 rounded-lg shadow-sm p-4 border border-purple-100"
42
+ style={style}
43
+ >
44
+ <div className="flex items-center justify-between mb-4">
45
+ <h3 className="text-sm font-medium text-gray-700">{title}</h3>
46
+ <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-bold bg-purple-100 text-purple-800">
47
+ {data.totalPending}
48
+ </span>
49
+ </div>
50
+ <div className="space-y-2 max-h-80 overflow-y-auto">
51
+ {data.queue.length === 0 ? (
52
+ <div className="text-center py-8">
53
+ <CheckCircle2 className="w-8 h-8 text-green-500 mx-auto mb-2" />
54
+ <p className="text-sm text-gray-600">{t('empty')}</p>
55
+ </div>
56
+ ) : (
57
+ data.queue.map((item) => (
58
+ <div
59
+ key={item.id}
60
+ className={`rounded-lg p-3 border transition-all ${item.priority === 'high' ? 'bg-red-50 border-red-300 border-l-4' : 'bg-blue-50 border-blue-200'}`}
61
+ >
62
+ <div className="flex items-start gap-2 mb-2">
63
+ <span className="text-lg">{getTypeIcon(item.type)}</span>
64
+ <div className="flex-1">
65
+ <div className="flex items-center justify-between gap-2">
66
+ <p className="text-sm font-medium text-gray-900 truncate">
67
+ {getTypeLabel(item.type)}
68
+ </p>
69
+ {item.priority === 'high' && (
70
+ <span className="text-xs font-bold bg-red-100 text-red-700 px-2 py-1 rounded">
71
+ 🔴 Alta
72
+ </span>
73
+ )}
74
+ </div>
75
+ </div>
76
+ </div>
77
+ <div className="space-y-1 text-xs">
78
+ <div className="flex items-center gap-1 text-gray-700">
79
+ <User className="w-3 h-3" />
80
+ <span className="truncate">{item.submittedBy}</span>
81
+ </div>
82
+ <div className="flex items-center justify-between">
83
+ <div className="flex items-center gap-1 text-gray-700">
84
+ <Calendar className="w-3 h-3" />
85
+ <span>{item.submittedDate}</span>
86
+ </div>
87
+ <div
88
+ className={`font-semibold ${item.daysWaiting > 14 ? 'text-red-600' : item.daysWaiting > 7 ? 'text-yellow-600' : 'text-blue-600'}`}
89
+ >
90
+ {item.daysWaiting}d
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ ))
96
+ )}
97
+ </div>
98
+ <div className="mt-3 pt-3 border-t border-purple-100">
99
+ <p className="text-xs text-gray-600">
100
+ 💡 <span className="font-semibold">Dica:</span> Itens com 🔴 Alta
101
+ prioridade precisam de atenção imediata
102
+ </p>
103
+ </div>
104
+ </div>
105
+ );
106
+ };
107
+
108
+ export default TeamApprovalQueue;
@@ -0,0 +1,97 @@
1
+ 'use client';
2
+
3
+ import { Zap } from 'lucide-react';
4
+ import { useTranslations } from 'next-intl';
5
+ import React from 'react';
6
+
7
+ interface TeamCapacityKpiProps {
8
+ slug: string;
9
+ title: string;
10
+ roleSlug: string;
11
+ width?: number;
12
+ height?: number;
13
+ data?: {
14
+ totalCapacity: number;
15
+ allocatedCapacity: number;
16
+ availableCapacity: number;
17
+ utilizationPercent: number;
18
+ };
19
+ style?: React.CSSProperties;
20
+ }
21
+
22
+ const TeamCapacityKpi: React.FC<TeamCapacityKpiProps> = ({
23
+ title,
24
+ data = {
25
+ totalCapacity: 100,
26
+ allocatedCapacity: 0,
27
+ availableCapacity: 100,
28
+ utilizationPercent: 0,
29
+ },
30
+ style,
31
+ }) => {
32
+ const t = useTranslations('operations.TeamCapacityKpi');
33
+ const getUtilizationColor = () => {
34
+ if (data.utilizationPercent > 95) return 'from-red-500 to-red-600';
35
+ if (data.utilizationPercent > 85) return 'from-yellow-500 to-yellow-600';
36
+ if (data.utilizationPercent > 70) return 'from-green-500 to-green-600';
37
+ return 'from-blue-500 to-blue-600';
38
+ };
39
+
40
+ return (
41
+ <div
42
+ className="bg-linear-to-br from-white to-indigo-50 rounded-lg shadow-sm p-4 border border-indigo-100"
43
+ style={style}
44
+ >
45
+ <div className="flex items-center justify-between mb-4">
46
+ <h3 className="text-sm font-medium text-gray-700">{title}</h3>
47
+ <Zap className="w-4 h-4 text-indigo-600" />
48
+ </div>
49
+ <div className="space-y-4">
50
+ <div className="space-y-2">
51
+ <div className="flex justify-between items-center">
52
+ <span className="text-xs font-medium text-gray-700">
53
+ {t('utilization')}
54
+ </span>
55
+ <span className="text-sm font-bold text-indigo-600">
56
+ {data.utilizationPercent}%
57
+ </span>
58
+ </div>
59
+ <div className="relative w-full h-5 bg-gray-200 rounded-full overflow-hidden">
60
+ <div
61
+ className={`h-full bg-linear-to-r ${getUtilizationColor()} transition-all duration-500 rounded-full`}
62
+ style={{ width: `${Math.min(data.utilizationPercent, 100)}%` }}
63
+ />
64
+ </div>
65
+ <div className="flex justify-between text-xs text-gray-600">
66
+ <span>{t('allocated', { hours: data.allocatedCapacity })}</span>
67
+ <span>{t('total', { hours: data.totalCapacity })}</span>
68
+ </div>
69
+ </div>
70
+ <div className="grid grid-cols-2 gap-2">
71
+ <div className="bg-indigo-100 rounded-lg p-3 border border-indigo-300">
72
+ <div className="text-xs text-indigo-700 mb-1">{t('available')}</div>
73
+ <div className="text-2xl font-bold text-indigo-600">
74
+ {data.availableCapacity}h
75
+ </div>
76
+ </div>
77
+ <div className="bg-purple-100 rounded-lg p-3 border border-purple-300">
78
+ <div className="text-xs text-purple-700 mb-1">{t('status')}</div>
79
+ <div
80
+ className={`text-sm font-bold ${data.utilizationPercent > 95 ? 'text-red-600' : data.utilizationPercent > 85 ? 'text-yellow-600' : 'text-green-600'}`}
81
+ >
82
+ {data.utilizationPercent > 95
83
+ ? t('critical')
84
+ : data.utilizationPercent > 85
85
+ ? t('high')
86
+ : data.utilizationPercent > 70
87
+ ? t('great')
88
+ : t('normal')}
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ );
95
+ };
96
+
97
+ export default TeamCapacityKpi;