@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
@@ -1,50 +1,53 @@
1
1
  'use client';
2
2
 
3
3
  import { EmptyState, Page } from '@/components/entity-list';
4
- import { RichTextEditor } from '@/components/rich-text-editor';
5
4
  import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
6
5
  import { Button } from '@/components/ui/button';
7
- import {
8
- Dialog,
9
- DialogContent,
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogDescription,
10
10
  DialogFooter,
11
11
  DialogHeader,
12
- DialogTitle,
13
- } from '@/components/ui/dialog';
14
- import { Input } from '@/components/ui/input';
15
- import { Label } from '@/components/ui/label';
16
- import { Progress } from '@/components/ui/progress';
17
- import {
18
- Select,
19
- SelectContent,
20
- SelectItem,
21
- SelectTrigger,
22
- SelectValue,
23
- } from '@/components/ui/select';
24
- import {
25
- Sheet,
26
- SheetContent,
27
- SheetHeader,
28
- SheetTitle,
29
- } from '@/components/ui/sheet';
30
- import {
31
- Table,
32
- TableBody,
33
- TableCell,
12
+ DialogTitle,
13
+ } from '@/components/ui/dialog';
14
+ import { Input } from '@/components/ui/input';
15
+ import { Label } from '@/components/ui/label';
16
+ import { Progress } from '@/components/ui/progress';
17
+ import {
18
+ Select,
19
+ SelectContent,
20
+ SelectItem,
21
+ SelectTrigger,
22
+ SelectValue,
23
+ } from '@/components/ui/select';
24
+ import {
25
+ Sheet,
26
+ SheetContent,
27
+ SheetHeader,
28
+ SheetTitle,
29
+ } from '@/components/ui/sheet';
30
+ import {
31
+ Table,
32
+ TableBody,
33
+ TableCell,
34
34
  TableHead,
35
35
  TableHeader,
36
- TableRow,
37
- } from '@/components/ui/table';
38
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
36
+ TableRow,
37
+ } from '@/components/ui/table';
38
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
39
+ import { RichTextEditor } from '@/components/rich-text-editor';
39
40
  import {
40
41
  closestCenter,
41
42
  DndContext,
43
+ DragOverlay,
42
44
  PointerSensor,
43
45
  useDraggable,
44
46
  useDroppable,
45
47
  useSensor,
46
48
  useSensors,
47
49
  type DragEndEvent,
50
+ type DragStartEvent,
48
51
  type UniqueIdentifier,
49
52
  } from '@dnd-kit/core';
50
53
  import { CSS } from '@dnd-kit/utilities';
@@ -60,16 +63,17 @@ import {
60
63
  Paperclip,
61
64
  Pencil,
62
65
  Plus,
66
+ Send,
63
67
  Timer,
64
68
  Trash2,
65
69
  } from 'lucide-react';
66
- import { useTranslations } from 'next-intl';
67
- import { useCallback, useMemo, useState } from 'react';
68
- import { fetchOperations, mutateOperations } from '../_lib/api';
69
- import { useMentionItems } from '../_lib/hooks/use-mention-items';
70
- import type {
71
- OperationsMyProjectSummary,
72
- OperationsTaskOption,
70
+ import { useTranslations } from 'next-intl';
71
+ import { useCallback, useMemo, useState } from 'react';
72
+ import { fetchOperations, mutateOperations } from '../_lib/api';
73
+ import { useMentionItems } from '../_lib/hooks/use-mention-items';
74
+ import type {
75
+ OperationsMyProjectSummary,
76
+ OperationsTaskOption,
73
77
  PaginatedResponse,
74
78
  } from '../_lib/types';
75
79
  import {
@@ -80,12 +84,13 @@ import {
80
84
  import { OperationsHeader } from './operations-header';
81
85
  import { SectionCard } from './section-card';
82
86
  import { StatusBadge } from './status-badge';
83
- import {
84
- TaskCommentsSection,
85
- TaskDetailSheet,
86
- type TaskDetailSheetData,
87
- } from './task-detail-sheet';
88
- import { TaskFileAttachments } from './task-file-attachments';
87
+ import {
88
+ TaskDetailSheet,
89
+ TaskCommentsSection,
90
+ type TaskDetailSheetData,
91
+ } from './task-detail-sheet';
92
+ import { TaskFileAttachments } from './task-file-attachments';
93
+ import { TimesheetEntryCreateSheet } from './timesheet-entry-create-sheet';
89
94
 
90
95
  type BoardColumnId = 'todo' | 'doing' | 'review' | 'done';
91
96
 
@@ -101,16 +106,19 @@ type BoardTask = {
101
106
  assigneeCollaboratorId: number | null;
102
107
  assigneeName: string | null;
103
108
  assigneeUserPhotoId: number | null;
104
- assigneePersonAvatarId: number | null;
105
- commentCount: number;
106
- fileCount: number;
107
- };
109
+ assigneePersonAvatarId: number | null;
110
+ commentCount: number;
111
+ fileCount: number;
112
+ doingStartedAt: string | null;
113
+ totalDoingMinutes: number;
114
+ };
108
115
 
109
116
  type TaskFormState = {
110
117
  name: string;
111
118
  description: string;
112
119
  priority: 'low' | 'medium' | 'high';
113
120
  status: BoardColumnId;
121
+ assigneeCollaboratorId: string;
114
122
  dueDate: string;
115
123
  estimateHours: string;
116
124
  tags: string;
@@ -121,6 +129,7 @@ const EMPTY_TASK_FORM: TaskFormState = {
121
129
  description: '',
122
130
  priority: 'medium',
123
131
  status: 'todo',
132
+ assigneeCollaboratorId: 'none',
124
133
  dueDate: '',
125
134
  estimateHours: '',
126
135
  tags: '',
@@ -133,6 +142,14 @@ type BoardState = {
133
142
  columns: BoardColumns;
134
143
  };
135
144
 
145
+ type TimesheetEntryPrefill = {
146
+ projectId: number;
147
+ projectAssignmentId?: number | null;
148
+ projectLabel: string;
149
+ taskId: number;
150
+ taskLabel: string;
151
+ };
152
+
136
153
  const KANBAN_COLUMNS: Array<{ id: BoardColumnId; label: string }> = [
137
154
  { id: 'todo', label: 'Backlog' },
138
155
  { id: 'doing', label: 'Em execução' },
@@ -154,24 +171,34 @@ function parseTaskId(value: UniqueIdentifier | null | undefined) {
154
171
  return match ? Number(match[1]) : null;
155
172
  }
156
173
 
157
- function parseColumnId(
158
- value: UniqueIdentifier | null | undefined
159
- ): BoardColumnId | null {
160
- if (!value) return null;
161
- const match = String(value).match(/^col-(.+)$/);
162
- const id = match?.[1];
163
- return KANBAN_COLUMNS.some((c) => c.id === id) ? (id as BoardColumnId) : null;
164
- }
165
-
166
- function apiTaskToBoardTask(
167
- row: OperationsMyProjectSummary['tasks'][number]
168
- ): BoardTask {
174
+ function parseColumnId(
175
+ value: UniqueIdentifier | null | undefined
176
+ ): BoardColumnId | null {
177
+ if (!value) return null;
178
+ const match = String(value).match(/^col-(.+)$/);
179
+ const id = match?.[1];
180
+ return KANBAN_COLUMNS.some((c) => c.id === id) ? (id as BoardColumnId) : null;
181
+ }
182
+
183
+ function normalizeDateInputValue(value?: string | null) {
184
+ if (!value) return '';
185
+ const match = String(value)
186
+ .trim()
187
+ .match(/^\d{4}-\d{2}-\d{2}/);
188
+ return match?.[0] ?? '';
189
+ }
190
+
191
+ function apiTaskToBoardTask(
192
+ row: OperationsMyProjectSummary['tasks'][number] | OperationsTaskOption
193
+ ): BoardTask {
169
194
  const status = KANBAN_COLUMNS.some((c) => c.id === row.status)
170
195
  ? (row.status as BoardColumnId)
171
196
  : 'todo';
172
197
  const taskCounts = row as typeof row & {
173
198
  commentCount?: number | null;
174
199
  fileCount?: number | null;
200
+ doingStartedAt?: string | null;
201
+ totalDoingMinutes?: number | null;
175
202
  };
176
203
 
177
204
  return {
@@ -191,6 +218,8 @@ function apiTaskToBoardTask(
191
218
  ((row as unknown as Record<string, unknown>).commentCount as number) ?? 0,
192
219
  fileCount:
193
220
  ((row as unknown as Record<string, unknown>).fileCount as number) ?? 0,
221
+ doingStartedAt: taskCounts.doingStartedAt ?? null,
222
+ totalDoingMinutes: taskCounts.totalDoingMinutes ?? 0,
194
223
  };
195
224
  }
196
225
 
@@ -203,6 +232,23 @@ function splitTasksByColumn(tasks: BoardTask[]): BoardColumns {
203
232
  };
204
233
  }
205
234
 
235
+ function replaceTaskInColumns(
236
+ columns: BoardColumns,
237
+ task: BoardTask
238
+ ): BoardColumns {
239
+ const nextColumns = {
240
+ todo: columns.todo.filter((item) => item.id !== task.id),
241
+ doing: columns.doing.filter((item) => item.id !== task.id),
242
+ review: columns.review.filter((item) => item.id !== task.id),
243
+ done: columns.done.filter((item) => item.id !== task.id),
244
+ };
245
+
246
+ return {
247
+ ...nextColumns,
248
+ [task.status]: [task, ...nextColumns[task.status]],
249
+ };
250
+ }
251
+
206
252
  function getInitials(value?: string | null) {
207
253
  const parts = String(value ?? '')
208
254
  .trim()
@@ -225,26 +271,6 @@ function getUserPhotoUrl(photoId?: number | null) {
225
271
  : null;
226
272
  }
227
273
 
228
- function normalizeDateInputValue(value?: string | null) {
229
- if (!value) {
230
- return '';
231
- }
232
-
233
- const normalizedValue = String(value).trim();
234
- const directMatch = normalizedValue.match(/^\d{4}-\d{2}-\d{2}/);
235
-
236
- if (directMatch?.[0]) {
237
- return directMatch[0];
238
- }
239
-
240
- const parsedDate = new Date(normalizedValue);
241
- if (Number.isNaN(parsedDate.getTime())) {
242
- return '';
243
- }
244
-
245
- return parsedDate.toISOString().slice(0, 10);
246
- }
247
-
248
274
  function getTaskPriorityLabel(value?: string | null) {
249
275
  const labels: Record<string, string> = {
250
276
  low: 'Baixa',
@@ -326,10 +352,12 @@ function DraggableTaskCard({
326
352
  return (
327
353
  <div
328
354
  ref={setNodeRef}
329
- style={{ transform: CSS.Translate.toString(transform) }}
355
+ style={{
356
+ transform: CSS.Translate.toString(transform),
357
+ ...(isDragging ? { opacity: 0, pointerEvents: 'none' } : {}),
358
+ }}
330
359
  {...listeners}
331
360
  {...attributes}
332
- className={isDragging ? 'z-20' : undefined}
333
361
  >
334
362
  {children(isDragging)}
335
363
  </div>
@@ -349,13 +377,12 @@ function DroppableColumn({
349
377
 
350
378
  export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
351
379
  const t = useTranslations('operations.ProjectDetailsPage');
352
- const commonT = useTranslations('operations.Common');
353
- const formT = useTranslations('operations.ProjectFormPage');
354
- const { request, currentLocaleCode, getSettingValue } = useApp();
355
-
356
- const mentionItems = useMentionItems(request);
357
-
358
- const getProjectStatusLabel = (value?: string | null) => {
380
+ const commonT = useTranslations('operations.Common');
381
+ const formT = useTranslations('operations.ProjectFormPage');
382
+ const { request, currentLocaleCode, getSettingValue } = useApp();
383
+ const mentionItems = useMentionItems(request);
384
+
385
+ const getProjectStatusLabel = (value?: string | null) => {
359
386
  if (!value) return commonT('labels.notAvailable');
360
387
  try {
361
388
  return formT(`options.statuses.${value}`);
@@ -397,7 +424,12 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
397
424
  const [editingTaskId, setEditingTaskId] = useState<number | null>(null);
398
425
  const [taskFormData, setTaskFormData] =
399
426
  useState<TaskFormState>(EMPTY_TASK_FORM);
427
+ const [activeDragTask, setActiveDragTask] = useState<BoardTask | null>(null);
400
428
  const [taskFormLoading, setTaskFormLoading] = useState(false);
429
+ const [isTimesheetEntrySheetOpen, setIsTimesheetEntrySheetOpen] =
430
+ useState(false);
431
+ const [timesheetPrefill, setTimesheetPrefill] =
432
+ useState<TimesheetEntryPrefill | null>(null);
401
433
 
402
434
  const apiTasks = useMemo(
403
435
  () => (project?.tasks ?? []).map(apiTaskToBoardTask),
@@ -429,6 +461,27 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
429
461
  return splitTasksByColumn(apiTasks);
430
462
  }, [project, boardState, apiTasks]);
431
463
 
464
+ const taskAssigneeOptions = useMemo(() => {
465
+ const seen = new Set<number>();
466
+ return (
467
+ project?.assignments
468
+ .filter((assignment) => {
469
+ if (
470
+ !assignment.collaboratorId ||
471
+ seen.has(assignment.collaboratorId)
472
+ ) {
473
+ return false;
474
+ }
475
+ seen.add(assignment.collaboratorId);
476
+ return true;
477
+ })
478
+ .map((assignment) => ({
479
+ id: String(assignment.collaboratorId),
480
+ label: assignment.collaboratorName,
481
+ })) ?? []
482
+ );
483
+ }, [project]);
484
+
432
485
  const sensors = useSensors(
433
486
  useSensor(PointerSensor, { activationConstraint: { distance: 6 } })
434
487
  );
@@ -464,31 +517,73 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
464
517
  },
465
518
  });
466
519
 
467
- mutateOperations(request, `/operations/tasks/${taskId}`, 'PATCH', {
468
- status: targetColumn,
469
- }).catch(() => {
470
- setBoardState(null);
471
- void refetch();
472
- });
520
+ mutateOperations<OperationsTaskOption>(
521
+ request,
522
+ `/operations/tasks/${taskId}`,
523
+ 'PATCH',
524
+ {
525
+ status: targetColumn,
526
+ }
527
+ )
528
+ .then((updatedTask) => {
529
+ if (!updatedTask) {
530
+ return;
531
+ }
532
+
533
+ const updatedBoardTask = apiTaskToBoardTask(updatedTask);
534
+ setBoardState((current) => ({
535
+ projectId: current?.projectId ?? project.id,
536
+ columns: replaceTaskInColumns(
537
+ current?.columns ?? taskColumns,
538
+ updatedBoardTask
539
+ ),
540
+ }));
541
+ })
542
+ .catch(() => {
543
+ setBoardState(null);
544
+ void refetch();
545
+ });
473
546
  },
474
547
  [taskColumns, project, request, refetch] // eslint-disable-line react-hooks/exhaustive-deps
475
548
  );
476
549
 
477
550
  const onBoardDragEnd = (event: DragEndEvent) => {
551
+ setActiveDragTask(null);
478
552
  const taskId = parseTaskId(event.active.id);
479
553
  const targetColumn = parseColumnId(event.over?.id);
480
554
  if (!taskId || !targetColumn) return;
481
555
  moveTaskToColumn(taskId, targetColumn);
482
556
  };
483
557
 
484
- const openCreateTaskForm = useCallback(
485
- (defaultStatus: BoardColumnId = 'todo') => {
486
- setEditingTaskId(null);
487
- setTaskFormData({ ...EMPTY_TASK_FORM, status: defaultStatus });
558
+ const onBoardDragStart = (event: DragStartEvent) => {
559
+ const taskId = parseTaskId(event.active.id);
560
+ if (!taskId) {
561
+ setActiveDragTask(null);
562
+ return;
563
+ }
564
+
565
+ const task = KANBAN_COLUMNS.map((column) => taskColumns[column.id])
566
+ .find((items) => items.some((item) => item.id === taskId))
567
+ ?.find((item) => item.id === taskId);
568
+
569
+ setActiveDragTask(task ?? null);
570
+ };
571
+
572
+ const openCreateTaskForm = useCallback(
573
+ (defaultStatus: BoardColumnId = 'todo') => {
574
+ setEditingTaskId(null);
575
+ setTaskFormData({
576
+ ...EMPTY_TASK_FORM,
577
+ status: defaultStatus,
578
+ assigneeCollaboratorId:
579
+ currentCollaboratorId != null
580
+ ? String(currentCollaboratorId)
581
+ : 'none',
582
+ });
488
583
  setSelectedTask(null);
489
584
  setTaskFormOpen(true);
490
585
  },
491
- []
586
+ [currentCollaboratorId]
492
587
  );
493
588
 
494
589
  const openEditTaskForm = useCallback((task: BoardTask) => {
@@ -498,6 +593,9 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
498
593
  description: task.description ?? '',
499
594
  priority: task.priority as TaskFormState['priority'],
500
595
  status: task.status,
596
+ assigneeCollaboratorId: task.assigneeCollaboratorId
597
+ ? String(task.assigneeCollaboratorId)
598
+ : 'none',
501
599
  dueDate: normalizeDateInputValue(task.dueDate),
502
600
  estimateHours:
503
601
  task.estimateHours != null ? String(task.estimateHours) : '',
@@ -519,7 +617,10 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
519
617
  const payload: Record<string, unknown> = {
520
618
  projectId,
521
619
  projectAssignmentId: project?.myAssignmentId ?? null,
522
- assigneeCollaboratorId: currentCollaboratorId,
620
+ assigneeCollaboratorId:
621
+ taskFormData.assigneeCollaboratorId !== 'none'
622
+ ? Number(taskFormData.assigneeCollaboratorId)
623
+ : null,
523
624
  name: taskFormData.name.trim(),
524
625
  description: taskFormData.description || null,
525
626
  priority: taskFormData.priority,
@@ -550,15 +651,7 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
550
651
  } finally {
551
652
  setTaskFormLoading(false);
552
653
  }
553
- }, [
554
- currentCollaboratorId,
555
- editingTaskId,
556
- project,
557
- projectId,
558
- refetchAll,
559
- request,
560
- taskFormData,
561
- ]);
654
+ }, [editingTaskId, project, projectId, refetchAll, request, taskFormData]);
562
655
 
563
656
  const [archivingTaskId, setArchivingTaskId] = useState<number | null>(null);
564
657
 
@@ -612,6 +705,29 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
612
705
  [request, refetchAll]
613
706
  );
614
707
 
708
+ const openTimesheetEntrySheet = useCallback(
709
+ (task: TaskDetailSheetData) => {
710
+ if (!project) {
711
+ return;
712
+ }
713
+
714
+ const projectLabel = [project.name, project.code]
715
+ .filter(Boolean)
716
+ .join(' • ');
717
+
718
+ setTimesheetPrefill({
719
+ projectId,
720
+ projectAssignmentId: project.myAssignmentId ?? null,
721
+ projectLabel: projectLabel || commonT('labels.notAssigned'),
722
+ taskId: task.id,
723
+ taskLabel: task.name,
724
+ });
725
+ setSelectedTask(null);
726
+ setIsTimesheetEntrySheetOpen(true);
727
+ },
728
+ [commonT, project, projectId]
729
+ );
730
+
615
731
  if (!project) {
616
732
  return (
617
733
  <Page>
@@ -708,6 +824,8 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
708
824
  <DndContext
709
825
  sensors={sensors}
710
826
  collisionDetection={closestCenter}
827
+ onDragStart={onBoardDragStart}
828
+ onDragCancel={() => setActiveDragTask(null)}
711
829
  onDragEnd={onBoardDragEnd}
712
830
  >
713
831
  <div className="grid gap-4 xl:grid-cols-4">
@@ -924,6 +1042,18 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
924
1042
  </DroppableColumn>
925
1043
  ))}
926
1044
  </div>
1045
+ <DragOverlay zIndex={1200}>
1046
+ {activeDragTask ? (
1047
+ <div className="w-76 cursor-grabbing rounded-2xl border border-primary/60 bg-card p-3 text-left shadow-2xl ring-2 ring-primary/20 opacity-95">
1048
+ <p className="line-clamp-2 text-sm font-semibold leading-snug">
1049
+ {activeDragTask.name}
1050
+ </p>
1051
+ <p className="mt-1 truncate text-xs text-muted-foreground">
1052
+ {activeDragTask.assigneeName || commonT('labels.notAssigned')}
1053
+ </p>
1054
+ </div>
1055
+ ) : null}
1056
+ </DragOverlay>
927
1057
  </DndContext>
928
1058
  </SectionCard>
929
1059
 
@@ -1091,13 +1221,13 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
1091
1221
  }}
1092
1222
  footer={
1093
1223
  selectedTask ? (
1094
- <div className="grid grid-cols-2 gap-3">
1224
+ <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
1095
1225
  {archivedTasks.some((task) => task.id === selectedTask.id) ? (
1096
1226
  <>
1097
1227
  <Button
1098
1228
  variant="outline"
1099
1229
  size="sm"
1100
- className="h-10 gap-2"
1230
+ className="h-10 gap-2 sm:col-span-2"
1101
1231
  onClick={() => void handleRestoreTask(selectedTask.id)}
1102
1232
  >
1103
1233
  <ArchiveRestore className="size-3.5" />
@@ -1115,6 +1245,15 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
1115
1245
  </>
1116
1246
  ) : (
1117
1247
  <>
1248
+ <Button
1249
+ variant="outline"
1250
+ size="sm"
1251
+ className="h-10 gap-2"
1252
+ onClick={() => openTimesheetEntrySheet(selectedTask)}
1253
+ >
1254
+ <Send className="size-3.5" />
1255
+ {commonT('actions.logHours')}
1256
+ </Button>
1118
1257
  <Button
1119
1258
  variant="outline"
1120
1259
  size="sm"
@@ -1140,13 +1279,43 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
1140
1279
  }
1141
1280
  />
1142
1281
 
1143
- <Sheet
1144
- open={taskFormOpen}
1282
+ <TimesheetEntryCreateSheet
1283
+ open={isTimesheetEntrySheetOpen}
1145
1284
  onOpenChange={(open) => {
1285
+ setIsTimesheetEntrySheetOpen(open);
1146
1286
  if (!open) {
1287
+ setTimesheetPrefill(null);
1288
+ }
1289
+ }}
1290
+ project={
1291
+ timesheetPrefill
1292
+ ? {
1293
+ id: timesheetPrefill.projectId,
1294
+ label: timesheetPrefill.projectLabel,
1295
+ projectAssignmentId: timesheetPrefill.projectAssignmentId,
1296
+ }
1297
+ : null
1298
+ }
1299
+ task={
1300
+ timesheetPrefill
1301
+ ? {
1302
+ id: timesheetPrefill.taskId,
1303
+ label: timesheetPrefill.taskLabel,
1304
+ }
1305
+ : null
1306
+ }
1307
+ onCreated={() => {
1308
+ void refetchAll();
1309
+ }}
1310
+ />
1311
+
1312
+
1313
+ <Sheet
1314
+ open={taskFormOpen}
1315
+ onOpenChange={(open) => {
1316
+ if (!open) {
1147
1317
  setTaskFormOpen(false);
1148
1318
  setEditingTaskId(null);
1149
- setTaskFormData(EMPTY_TASK_FORM);
1150
1319
  }
1151
1320
  }}
1152
1321
  >
@@ -1257,6 +1426,35 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
1257
1426
  </div>
1258
1427
  </div>
1259
1428
 
1429
+ <div className="space-y-1.5">
1430
+ <Label>{commonT('responsible')}</Label>
1431
+ <Select
1432
+ value={taskFormData.assigneeCollaboratorId}
1433
+ onValueChange={(value) =>
1434
+ setTaskFormData((prev) => ({
1435
+ ...prev,
1436
+ assigneeCollaboratorId: value,
1437
+ }))
1438
+ }
1439
+ >
1440
+ <SelectTrigger className="w-full">
1441
+ <SelectValue
1442
+ placeholder={commonT('labels.notAssigned')}
1443
+ />
1444
+ </SelectTrigger>
1445
+ <SelectContent>
1446
+ <SelectItem value="none">
1447
+ {commonT('labels.notAssigned')}
1448
+ </SelectItem>
1449
+ {taskAssigneeOptions.map((option) => (
1450
+ <SelectItem key={option.id} value={option.id}>
1451
+ {option.label}
1452
+ </SelectItem>
1453
+ ))}
1454
+ </SelectContent>
1455
+ </Select>
1456
+ </div>
1457
+
1260
1458
  <div className="grid grid-cols-2 gap-3">
1261
1459
  <div className="space-y-1.5">
1262
1460
  <Label htmlFor="task-due-date">
@@ -1398,10 +1596,10 @@ export function MyProjectSummaryScreen({ projectId }: { projectId: number }) {
1398
1596
  <DialogContent className="sm:max-w-lg">
1399
1597
  <DialogHeader>
1400
1598
  <DialogTitle>{t('dialogs.deleteTitle')}</DialogTitle>
1599
+ <DialogDescription>
1600
+ {t('dialogs.deleteDescription')}
1601
+ </DialogDescription>
1401
1602
  </DialogHeader>
1402
- <p className="text-sm text-muted-foreground">
1403
- {t('dialogs.deleteDescription')}
1404
- </p>
1405
1603
  <DialogFooter className="gap-2 sm:justify-between">
1406
1604
  <Button variant="ghost" onClick={() => setDeletePromptTask(null)}>
1407
1605
  {commonT('actions.cancel')}