@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
@@ -1,166 +1,156 @@
1
- import { Role, User } from '@hed-hog/api';
2
- import {
3
- Body,
4
- Controller,
5
- Delete,
6
- Get,
7
- Param,
8
- ParseIntPipe,
9
- Patch,
10
- Post,
11
- Query,
12
- UploadedFile,
13
- UseInterceptors,
14
- } from '@nestjs/common';
15
- import { FileInterceptor } from '@nestjs/platform-express';
16
- import { CreateOperationsTaskDto } from '../dto/create-task.dto';
17
- import { ListMyTasksDto } from '../dto/list-my-tasks.dto';
18
- import { ListOperationsTasksDto } from '../dto/list-tasks.dto';
19
- import { UpdateOperationsTaskDto } from '../dto/update-task.dto';
20
- import { OperationsService } from '../operations.service';
21
-
22
- @Role()
23
- @Controller('operations')
24
- export class OperationsTasksController {
25
- constructor(private readonly operationsService: OperationsService) {}
26
-
27
- @Get('tasks')
28
- listTasks(
29
- @User() user,
30
- @Query() paginationParams: ListOperationsTasksDto,
31
- ) {
32
- return this.operationsService.listTasks(
33
- Number(user?.id || 0),
34
- paginationParams,
35
- );
36
- }
37
-
38
- @Get('my-tasks')
39
- listMyTasks(
40
- @User() user,
41
- @Query() paginationParams: ListMyTasksDto,
42
- ) {
43
- return this.operationsService.listMyTasks(
44
- Number(user?.id || 0),
45
- paginationParams,
46
- );
47
- }
48
-
49
- @Get('projects/:id/tasks')
50
- listProjectBoardTasks(
51
- @User() user,
52
- @Param('id', ParseIntPipe) id: number,
53
- ) {
54
- return this.operationsService.listProjectBoardTasks(
55
- Number(user?.id || 0),
56
- id,
57
- );
58
- }
59
-
60
- @Post('tasks')
61
- createTask(@User() user, @Body() data: CreateOperationsTaskDto) {
62
- return this.operationsService.createTask(Number(user?.id || 0), data);
63
- }
64
-
65
- @Patch('tasks/:id')
66
- updateTask(
67
- @User() user,
68
- @Param('id', ParseIntPipe) id: number,
69
- @Body() data: UpdateOperationsTaskDto,
70
- ) {
71
- return this.operationsService.updateTask(Number(user?.id || 0), id, data);
72
- }
73
-
74
- @Delete('tasks/:id')
75
- removeTask(
76
- @User() user,
77
- @Param('id', ParseIntPipe) id: number,
78
- @Query('permanent') permanent?: string,
79
- ) {
80
- return this.operationsService.removeTask(
81
- Number(user?.id || 0),
82
- id,
83
- permanent === 'true'
84
- );
85
- }
86
-
87
- @Get('tasks/:id/files')
88
- listTaskFiles(
89
- @User() user,
90
- @Param('id', ParseIntPipe) id: number,
91
- ) {
92
- return this.operationsService.listTaskFiles(Number(user?.id || 0), id);
93
- }
94
-
95
- @Post('tasks/:id/files')
96
- @UseInterceptors(FileInterceptor('file'))
97
- addTaskFile(
98
- @User() user,
99
- @Param('id', ParseIntPipe) id: number,
100
- @UploadedFile() file: MulterFile,
101
- ) {
102
- return this.operationsService.addTaskFile(Number(user?.id || 0), id, file);
103
- }
104
-
105
- @Delete('tasks/:id/files/:fileRelationId')
106
- removeTaskFile(
107
- @User() user,
108
- @Param('id', ParseIntPipe) id: number,
109
- @Param('fileRelationId', ParseIntPipe) fileRelationId: number,
110
- ) {
111
- return this.operationsService.removeTaskFile(
112
- Number(user?.id || 0),
113
- id,
114
- fileRelationId
115
- );
116
- }
117
-
118
- @Get('tasks/:id/comments')
119
- listTaskComments(
120
- @User() user,
121
- @Param('id', ParseIntPipe) id: number,
122
- ) {
123
- return this.operationsService.listTaskComments(Number(user?.id || 0), id);
124
- }
125
-
126
- @Post('tasks/:id/comments')
127
- addTaskComment(
128
- @User() user,
129
- @Param('id', ParseIntPipe) id: number,
130
- @Body('content') content: string,
131
- ) {
132
- return this.operationsService.addTaskComment(
133
- Number(user?.id || 0),
134
- id,
135
- content
136
- );
137
- }
138
-
139
- @Patch('tasks/:taskId/comments/:commentId')
140
- updateTaskComment(
141
- @User() user,
142
- @Param('taskId', ParseIntPipe) taskId: number,
143
- @Param('commentId', ParseIntPipe) commentId: number,
144
- @Body('content') content: string,
145
- ) {
146
- return this.operationsService.updateTaskComment(
147
- Number(user?.id || 0),
148
- taskId,
149
- commentId,
150
- content
151
- );
152
- }
153
-
154
- @Delete('tasks/:taskId/comments/:commentId')
155
- removeTaskComment(
156
- @User() user,
157
- @Param('taskId', ParseIntPipe) taskId: number,
158
- @Param('commentId', ParseIntPipe) commentId: number,
159
- ) {
160
- return this.operationsService.removeTaskComment(
161
- Number(user?.id || 0),
162
- taskId,
163
- commentId
164
- );
165
- }
166
- }
1
+ import { Role, User } from "@hed-hog/api";
2
+ import {
3
+ Body,
4
+ Controller,
5
+ Delete,
6
+ Get,
7
+ Param,
8
+ ParseIntPipe,
9
+ Patch,
10
+ Post,
11
+ Query,
12
+ UploadedFile,
13
+ UseInterceptors,
14
+ } from "@nestjs/common";
15
+ import { FileInterceptor } from "@nestjs/platform-express";
16
+ import { CreateOperationsTaskDto } from "../dto/create-task.dto";
17
+ import { ListMyTasksDto } from "../dto/list-my-tasks.dto";
18
+ import { ListOperationsTasksDto } from "../dto/list-tasks.dto";
19
+ import { UpdateOperationsTaskDto } from "../dto/update-task.dto";
20
+ import { OperationsService } from "../operations.service";
21
+
22
+ @Role()
23
+ @Controller("operations")
24
+ export class OperationsTasksController {
25
+ constructor(private readonly operationsService: OperationsService) {}
26
+
27
+ @Get("tasks")
28
+ listTasks(@User() user, @Query() paginationParams: ListOperationsTasksDto) {
29
+ return this.operationsService.listTasks(
30
+ Number(user?.id || 0),
31
+ paginationParams,
32
+ );
33
+ }
34
+
35
+ @Get("my-tasks")
36
+ listMyTasks(@User() user, @Query() paginationParams: ListMyTasksDto) {
37
+ return this.operationsService.listMyTasks(
38
+ Number(user?.id || 0),
39
+ paginationParams,
40
+ );
41
+ }
42
+
43
+ @Get("projects/:id/tasks")
44
+ listProjectBoardTasks(@User() user, @Param("id", ParseIntPipe) id: number) {
45
+ return this.operationsService.listProjectBoardTasks(
46
+ Number(user?.id || 0),
47
+ id,
48
+ );
49
+ }
50
+
51
+ @Post("tasks")
52
+ createTask(@User() user, @Body() data: CreateOperationsTaskDto) {
53
+ return this.operationsService.createTask(Number(user?.id || 0), data);
54
+ }
55
+
56
+ @Patch("tasks/:id")
57
+ updateTask(
58
+ @User() user,
59
+ @Param("id", ParseIntPipe) id: number,
60
+ @Body() data: UpdateOperationsTaskDto,
61
+ ) {
62
+ return this.operationsService.updateTask(Number(user?.id || 0), id, data);
63
+ }
64
+
65
+ @Delete("tasks/:id")
66
+ removeTask(
67
+ @User() user,
68
+ @Param("id", ParseIntPipe) id: number,
69
+ @Query("permanent") permanent?: string,
70
+ ) {
71
+ return this.operationsService.removeTask(
72
+ Number(user?.id || 0),
73
+ id,
74
+ permanent === "true",
75
+ );
76
+ }
77
+
78
+ @Get("tasks/:id/files")
79
+ listTaskFiles(@User() user, @Param("id", ParseIntPipe) id: number) {
80
+ return this.operationsService.listTaskFiles(Number(user?.id || 0), id);
81
+ }
82
+
83
+ @Post("tasks/:id/files")
84
+ @UseInterceptors(FileInterceptor("file"))
85
+ addTaskFile(
86
+ @User() user,
87
+ @Param("id", ParseIntPipe) id: number,
88
+ @UploadedFile() file: MulterFile,
89
+ ) {
90
+ return this.operationsService.addTaskFile(Number(user?.id || 0), id, file);
91
+ }
92
+
93
+ @Delete("tasks/:id/files/:fileRelationId")
94
+ removeTaskFile(
95
+ @User() user,
96
+ @Param("id", ParseIntPipe) id: number,
97
+ @Param("fileRelationId", ParseIntPipe) fileRelationId: number,
98
+ ) {
99
+ return this.operationsService.removeTaskFile(
100
+ Number(user?.id || 0),
101
+ id,
102
+ fileRelationId,
103
+ );
104
+ }
105
+
106
+ @Get("tasks/:id/comments")
107
+ listTaskComments(@User() user, @Param("id", ParseIntPipe) id: number) {
108
+ return this.operationsService.listTaskComments(Number(user?.id || 0), id);
109
+ }
110
+
111
+ @Get("tasks/:id/activities")
112
+ listTaskActivities(@User() user, @Param("id", ParseIntPipe) id: number) {
113
+ return this.operationsService.listTaskActivities(Number(user?.id || 0), id);
114
+ }
115
+
116
+ @Post("tasks/:id/comments")
117
+ addTaskComment(
118
+ @User() user,
119
+ @Param("id", ParseIntPipe) id: number,
120
+ @Body("content") content: string,
121
+ ) {
122
+ return this.operationsService.addTaskComment(
123
+ Number(user?.id || 0),
124
+ id,
125
+ content,
126
+ );
127
+ }
128
+
129
+ @Patch("tasks/:taskId/comments/:commentId")
130
+ updateTaskComment(
131
+ @User() user,
132
+ @Param("taskId", ParseIntPipe) taskId: number,
133
+ @Param("commentId", ParseIntPipe) commentId: number,
134
+ @Body("content") content: string,
135
+ ) {
136
+ return this.operationsService.updateTaskComment(
137
+ Number(user?.id || 0),
138
+ taskId,
139
+ commentId,
140
+ content,
141
+ );
142
+ }
143
+
144
+ @Delete("tasks/:taskId/comments/:commentId")
145
+ removeTaskComment(
146
+ @User() user,
147
+ @Param("taskId", ParseIntPipe) taskId: number,
148
+ @Param("commentId", ParseIntPipe) commentId: number,
149
+ ) {
150
+ return this.operationsService.removeTaskComment(
151
+ Number(user?.id || 0),
152
+ taskId,
153
+ commentId,
154
+ );
155
+ }
156
+ }
@@ -0,0 +1,214 @@
1
+ # Dashboard Widgets - Operations Module
2
+
3
+ ## Arquitetura
4
+
5
+ O dashboard do módulo operations segue um padrão de composição modular com 3 camadas de widgets baseados em roles:
6
+
7
+ ### Roles e Widgets
8
+
9
+ | Role | Widgets | Descrição |
10
+ |------|---------|-----------|
11
+ | `operations-collaborator` | 8 widgets | Visão pessoal: horas, timesheet, alocações, solicitações, prazos, ações rápidas |
12
+ | `admin-operations-supervisor` | 8 widgets | Visão de time: headcount, aprovações, horas, capacidade, utilização, alertas, projetos, fila |
13
+ | `admin-operations-director` | 7 widgets | Visão de portfólio: projetos, custos, esforço, risco, status, distribuição, prazos |
14
+
15
+ ### Estrutura de Pastas
16
+
17
+ ```
18
+ src/dashboard/
19
+ ├── hooks/
20
+ │ └── useDashboardData.ts # Hook para buscar dados do backend
21
+ ├── types/
22
+ │ └── widgets.types.ts # Tipos TypeScript para dados de widgets
23
+ ├── components/
24
+ │ └── DashboardLayout.tsx # Layout principal que renderiza widgets
25
+ └── widgets/
26
+ ├── MyHoursPeriodKpi.tsx # Exemplo: Collaborator widget
27
+ ├── TeamHeadcountKpi.tsx # Exemplo: Supervisor widget
28
+ ├── PortfolioProjectsKpi.tsx # Exemplo: Director widget
29
+ └── [outros widgets...] # A implementar
30
+ ```
31
+
32
+ ## Como Adicionar um Novo Widget
33
+
34
+ ### 1. Defina o tipo de dados em `types/widgets.types.ts`
35
+
36
+ Adicione a interface de dados para seu widget:
37
+
38
+ ```typescript
39
+ export interface MyNewWidgetData {
40
+ title: string;
41
+ value: number;
42
+ // ... outros campos
43
+ }
44
+ ```
45
+
46
+ ### 2. Crie o componente widget
47
+
48
+ Crie um arquivo em `widgets/MyNewWidget.tsx`:
49
+
50
+ ```typescript
51
+ 'use client';
52
+
53
+ import React from 'react';
54
+
55
+ interface MyNewWidgetProps {
56
+ slug: string;
57
+ title: string;
58
+ roleSlug: string;
59
+ width?: number;
60
+ height?: number;
61
+ data?: MyNewWidgetData;
62
+ style?: React.CSSProperties;
63
+ }
64
+
65
+ const MyNewWidget: React.FC<MyNewWidgetProps> = ({
66
+ title,
67
+ data,
68
+ style,
69
+ }) => {
70
+ return (
71
+ <div className="bg-white rounded-lg shadow-sm p-4" style={style}>
72
+ <h3 className="text-sm font-medium">{title}</h3>
73
+ {/* Renderizar dados aqui */}
74
+ </div>
75
+ );
76
+ };
77
+
78
+ export default MyNewWidget;
79
+ ```
80
+
81
+ ### 3. Registre o widget em `DashboardLayout.tsx`
82
+
83
+ Adicione ao `WIDGET_REGISTRY`:
84
+
85
+ ```typescript
86
+ 'my-new-widget': React.lazy(() => import('./widgets/MyNewWidget')),
87
+ ```
88
+
89
+ ### 4. Configure permissões no YAML
90
+
91
+ Atualize `libraries/operations/hedhog/data/dashboard_component.yaml`:
92
+
93
+ ```yaml
94
+ - slug: my-new-widget
95
+ library_slug: operations
96
+ width: 3
97
+ height: 1
98
+ name:
99
+ en: My New Widget
100
+ pt: Meu Novo Widget
101
+ ```
102
+
103
+ Atualize `libraries/operations/hedhog/data/dashboard_component_role.yaml`:
104
+
105
+ ```yaml
106
+ - component_id:
107
+ where:
108
+ slug: my-new-widget
109
+ role_id:
110
+ where:
111
+ slug: operations-collaborator # ou a role apropriada
112
+ ```
113
+
114
+ ## Backend Integration
115
+
116
+ ### Endpoint: GET /operations/dashboard
117
+
118
+ O backend retorna dados estruturados conforme a role do usuário:
119
+
120
+ ```typescript
121
+ {
122
+ actor: {
123
+ roleScope: 'full' | 'team' | 'self',
124
+ collaboratorId: number,
125
+ collaboratorName: string,
126
+ teamSize: number,
127
+ },
128
+ cards: {
129
+ // ... dados agregados
130
+ },
131
+ recentTimesheets: [],
132
+ // ... dados específicos por role
133
+ }
134
+ ```
135
+
136
+ ### Segurança
137
+
138
+ ⚠️ **IMPORTANTE:** O backend sanitiza automaticamente dados sensíveis por role:
139
+
140
+ - **Directors**: Veem TODOS os dados (salários, custos, etc.)
141
+ - **Supervisors**: Veem dados monetários da equipe apenas
142
+ - **Collaborators**: Veem APENAS seus próprios dados, não de colegas
143
+
144
+ Nenhuma sanitização adicional é necessária no frontend - confia no backend!
145
+
146
+ ## Padrões de Componente
147
+
148
+ ### KPI Card (Métrica simples)
149
+
150
+ ```typescript
151
+ {
152
+ "métrica_principal": número grande em destaque,
153
+ "contexto": "de total",
154
+ "breakdown": [array de sub-métricas],
155
+ "status_indicator": visual de saúde (verde/amarelo/vermelho)
156
+ }
157
+ ```
158
+
159
+ ### Chart/Graph (Visualização complexa)
160
+
161
+ ```typescript
162
+ {
163
+ "título": string,
164
+ "dados": array de pontos com x,y,label,
165
+ "legenda": tipos de dados mostrados
166
+ }
167
+ ```
168
+
169
+ ### Lista (Array de items)
170
+
171
+ ```typescript
172
+ {
173
+ "cabeçalhos": ["coluna1", "coluna2", ...],
174
+ "linhas": [{ coluna1: valor, coluna2: valor }, ...],
175
+ "paginação": opcional
176
+ }
177
+ ```
178
+
179
+ ## Testes
180
+
181
+ Para testar um widget com dados mock:
182
+
183
+ ```typescript
184
+ const mockData = {
185
+ plannedHours: 40,
186
+ approvedHours: 32,
187
+ pendingHours: 4,
188
+ };
189
+
190
+ <MyHoursPeriodKpi
191
+ slug="my-hours-period-kpi"
192
+ title="Horas no Período"
193
+ roleSlug="operations-collaborator"
194
+ data={mockData}
195
+ />
196
+ ```
197
+
198
+ ## Loading States
199
+
200
+ Cada widget implementa um fallback de loading usando `React.Suspense`:
201
+
202
+ ```typescript
203
+ <React.Suspense fallback={<SkeletonLoader />}>
204
+ <MyWidget data={data} />
205
+ </React.Suspense>
206
+ ```
207
+
208
+ ## Próximas Etapas
209
+
210
+ - [ ] Implementar hook `useDashboardData` com react-query
211
+ - [ ] Criar 20 widgets restantes (20/23 ainda faltam)
212
+ - [ ] Integrar com Recharts/Chart.js para gráficos
213
+ - [ ] Adicionar testes unitários para cada widget
214
+ - [ ] Documentar parâmetros de cada widget
@@ -0,0 +1,131 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Dashboard Principal - Renderiza widgets conforme role do usuário
5
+ *
6
+ * Fluxo:
7
+ * 1. Detecta role do usuário (collaborator/supervisor/director)
8
+ * 2. Busca dados via GET /operations/dashboard
9
+ * 3. Renderiza widgets apropriados para a role
10
+ * 4. Cada widget é um componente reutilizável
11
+ */
12
+
13
+ import React, { useMemo } from 'react';
14
+
15
+ // Tipos de widgets por role
16
+ interface WidgetDefinition {
17
+ slug: string;
18
+ title: string;
19
+ roleSlug: string;
20
+ width: number;
21
+ height: number;
22
+ xAxis: number;
23
+ yAxis: number;
24
+ componentPath: string;
25
+ }
26
+
27
+ // Mapear slugs aos componentes - importados dinamicamente do admin app
28
+ // Os widgets estão em: apps/admin/src/app/(app)/(libraries)/operations/dashboard/widgets/
29
+ const WIDGET_REGISTRY: Record<string, React.ComponentType<any>> = {};
30
+
31
+ // Lazy loading de widgets - para evitar imports circulares
32
+ const getWidget = (slug: string): React.ComponentType<any> | null => {
33
+ // Este mapa será populado em runtime via importação dinâmica
34
+ // Por enquanto, retorna null se widget não estiver pronto
35
+ return WIDGET_REGISTRY[slug] || null;
36
+ };
37
+
38
+ interface DashboardLayoutProps {
39
+ roleSlugs: string[];
40
+ dashboardSlug: string;
41
+ widgets: WidgetDefinition[];
42
+ data: any;
43
+ isLoading?: boolean;
44
+ }
45
+
46
+ export const DashboardLayout: React.FC<DashboardLayoutProps> = ({
47
+ roleSlugs,
48
+ dashboardSlug,
49
+ widgets,
50
+ data,
51
+ isLoading = false,
52
+ }) => {
53
+ // Filtrar widgets para a role atual
54
+ const visibleWidgets = useMemo(() => {
55
+ return widgets.filter(widget =>
56
+ roleSlugs.includes(widget.roleSlug)
57
+ );
58
+ }, [widgets, roleSlugs]);
59
+
60
+ if (isLoading) {
61
+ return (
62
+ <div className="grid gap-4 w-full h-full">
63
+ {Array(4).fill(0).map((_, i) => (
64
+ <div
65
+ key={i}
66
+ className="bg-gray-200 rounded-lg animate-pulse"
67
+ style={{ minHeight: '200px' }}
68
+ />
69
+ ))}
70
+ </div>
71
+ );
72
+ }
73
+
74
+ return (
75
+ <div className="grid gap-4 w-full auto-rows-max"
76
+ style={{
77
+ gridTemplateColumns: 'repeat(12, 1fr)',
78
+ }}>
79
+ {visibleWidgets.map(widget => {
80
+ const Component = WIDGET_REGISTRY[widget.slug];
81
+
82
+ if (!Component) {
83
+ return (
84
+ <div
85
+ key={widget.slug}
86
+ style={{
87
+ gridColumn: `span ${Math.min(widget.width, 12)}`,
88
+ gridRow: `auto / span ${widget.height}`,
89
+ }}
90
+ className="bg-red-50 border-2 border-red-200 rounded-lg p-4"
91
+ >
92
+ <p className="text-red-700 text-sm">
93
+ Component not found: {widget.slug}
94
+ </p>
95
+ </div>
96
+ );
97
+ }
98
+
99
+ return (
100
+ <React.Suspense
101
+ key={widget.slug}
102
+ fallback={
103
+ <div
104
+ style={{
105
+ gridColumn: `span ${Math.min(widget.width, 12)}`,
106
+ gridRow: `auto / span ${widget.height}`,
107
+ }}
108
+ className="bg-gray-200 rounded-lg animate-pulse"
109
+ />
110
+ }
111
+ >
112
+ <Component
113
+ slug={widget.slug}
114
+ title={widget.title}
115
+ roleSlug={roleSlugs[0]}
116
+ width={widget.width}
117
+ height={widget.height}
118
+ data={data?.[widget.slug]}
119
+ style={{
120
+ gridColumn: `span ${Math.min(widget.width, 12)}`,
121
+ gridRow: `auto / span ${widget.height}`,
122
+ }}
123
+ />
124
+ </React.Suspense>
125
+ );
126
+ })}
127
+ </div>
128
+ );
129
+ };
130
+
131
+ export default DashboardLayout;