@hed-hog/operations 0.0.328 → 0.0.330

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 (596) hide show
  1. package/dist/controllers/operations-tasks.controller.d.ts +5 -5
  2. package/dist/operations.service.d.ts +5 -5
  3. package/dist/operations.service.d.ts.map +1 -1
  4. package/dist/operations.service.js +24 -4
  5. package/dist/operations.service.js.map +1 -1
  6. package/dist/operations.service.spec.js +1 -1
  7. package/dist/operations.service.spec.js.map +1 -1
  8. package/hedhog/data/dashboard_component_role.yaml +8 -8
  9. package/hedhog/data/dashboard_role.yaml +1 -1
  10. package/hedhog/data/menu.yaml +6 -16
  11. package/hedhog/data/role.yaml +1 -1
  12. package/hedhog/data/route.yaml +55 -55
  13. package/hedhog/frontend/app/_components/async-options-combobox.tsx.ejs +15 -9
  14. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +7 -7
  15. package/hedhog/frontend/app/_components/department-picker.tsx.ejs +125 -0
  16. package/hedhog/frontend/app/_components/department-select-with-create.tsx.ejs +64 -325
  17. package/hedhog/frontend/app/_components/project-costs-section.tsx.ejs +51 -81
  18. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +39 -11
  19. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +37 -20
  20. package/hedhog/frontend/app/_components/system-user-picker.tsx.ejs +198 -0
  21. package/hedhog/frontend/app/_components/system-user-select-with-create.tsx.ejs +107 -569
  22. package/hedhog/frontend/app/_components/task-file-attachments.tsx.ejs +10 -8
  23. package/hedhog/frontend/app/_lib/hooks/use-values-visibility.ts.ejs +61 -0
  24. package/hedhog/frontend/app/approvals/page.tsx.ejs +5 -1
  25. package/hedhog/frontend/app/collaborators/page.tsx.ejs +68 -34
  26. package/hedhog/frontend/app/my-projects/page.tsx.ejs +45 -6
  27. package/hedhog/frontend/app/my-tasks/page.tsx.ejs +1 -1
  28. package/hedhog/frontend/app/projects/page.tsx.ejs +60 -5
  29. package/hedhog/frontend/app/reports/collaborators/page.tsx.ejs +65 -52
  30. package/hedhog/frontend/app/reports/projects/page.tsx.ejs +80 -82
  31. package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +7 -1
  32. package/hedhog/frontend/messages/en.json +284 -8
  33. package/hedhog/frontend/messages/operations/en.json +67 -3
  34. package/hedhog/frontend/messages/operations/pt.json +67 -3
  35. package/hedhog/frontend/messages/pt.json +282 -6
  36. package/package.json +5 -5
  37. package/src/operations.service.spec.ts +1 -1
  38. package/src/operations.service.ts +25 -5
  39. package/hedhog/frontend/app/_components/collaborator-details-screen.tsx.ejs +0 -476
  40. package/hedhog/frontend/app/_components/collaborator-select-with-create.tsx.ejs +0 -261
  41. package/hedhog/frontend/app/_components/contract-content-editor.tsx.ejs +0 -258
  42. package/hedhog/frontend/app/_components/person-select-with-create.tsx.ejs +0 -1
  43. package/hedhog/frontend/messages/en.json.ejs +0 -2060
  44. package/hedhog/frontend/messages/operations/operations/en.json +0 -2102
  45. package/hedhog/frontend/messages/operations/operations/pt.json +0 -2111
  46. package/hedhog/frontend/messages/pt.json.ejs +0 -2067
  47. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.d.ts +0 -29
  48. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.d.ts.map +0 -1
  49. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.js +0 -95
  50. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.js.map +0 -1
  51. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.tsx +0 -233
  52. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.d.ts +0 -10
  53. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.d.ts.map +0 -1
  54. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.js +0 -577
  55. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.js.map +0 -1
  56. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.tsx +0 -868
  57. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.d.ts +0 -4
  58. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.d.ts.map +0 -1
  59. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.js +0 -337
  60. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.js.map +0 -1
  61. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.tsx +0 -476
  62. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.d.ts +0 -9
  63. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.d.ts.map +0 -1
  64. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.js +0 -1348
  65. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.js.map +0 -1
  66. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.tsx +0 -2233
  67. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.d.ts +0 -12
  68. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.d.ts.map +0 -1
  69. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.js +0 -162
  70. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.js.map +0 -1
  71. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.tsx +0 -261
  72. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.d.ts +0 -18
  73. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.d.ts.map +0 -1
  74. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.js +0 -145
  75. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.js.map +0 -1
  76. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.tsx +0 -258
  77. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.d.ts +0 -4
  78. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.d.ts.map +0 -1
  79. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.js +0 -223
  80. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.js.map +0 -1
  81. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.tsx +0 -342
  82. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.d.ts +0 -58
  83. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.d.ts.map +0 -1
  84. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.js +0 -438
  85. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.js.map +0 -1
  86. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.tsx +0 -698
  87. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.d.ts +0 -20
  88. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.d.ts.map +0 -1
  89. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.js +0 -233
  90. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.js.map +0 -1
  91. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.tsx +0 -392
  92. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.d.ts +0 -4
  93. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.d.ts.map +0 -1
  94. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.js +0 -814
  95. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.js.map +0 -1
  96. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.tsx +0 -1288
  97. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.d.ts +0 -21
  98. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.d.ts.map +0 -1
  99. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.js +0 -174
  100. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.js.map +0 -1
  101. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.tsx +0 -306
  102. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.d.ts +0 -10
  103. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.d.ts.map +0 -1
  104. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.js +0 -12
  105. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.js.map +0 -1
  106. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.tsx +0 -29
  107. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.d.ts +0 -15
  108. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.d.ts.map +0 -1
  109. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.js +0 -501
  110. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.js.map +0 -1
  111. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.tsx +0 -853
  112. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.d.ts +0 -6
  113. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.d.ts.map +0 -1
  114. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.js +0 -847
  115. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.js.map +0 -1
  116. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.tsx +0 -1340
  117. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.d.ts +0 -4
  118. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.d.ts.map +0 -1
  119. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.js +0 -2930
  120. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.js.map +0 -1
  121. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.tsx +0 -4378
  122. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.d.ts +0 -9
  123. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.d.ts.map +0 -1
  124. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.js +0 -1013
  125. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.js.map +0 -1
  126. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.tsx +0 -1745
  127. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.d.ts +0 -13
  128. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.d.ts.map +0 -1
  129. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.js +0 -38
  130. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.js.map +0 -1
  131. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.tsx +0 -74
  132. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.d.ts +0 -7
  133. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.d.ts.map +0 -1
  134. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.js +0 -11
  135. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.js.map +0 -1
  136. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.tsx +0 -15
  137. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.d.ts +0 -18
  138. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.d.ts.map +0 -1
  139. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.js +0 -406
  140. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.js.map +0 -1
  141. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.tsx +0 -660
  142. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.d.ts +0 -26
  143. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.d.ts.map +0 -1
  144. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.js +0 -332
  145. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.js.map +0 -1
  146. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.tsx +0 -518
  147. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.d.ts +0 -6
  148. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.d.ts.map +0 -1
  149. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.js +0 -255
  150. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.js.map +0 -1
  151. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.tsx +0 -388
  152. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.d.ts +0 -10
  153. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.d.ts.map +0 -1
  154. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.js +0 -131
  155. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.js.map +0 -1
  156. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.tsx +0 -214
  157. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.d.ts +0 -108
  158. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.d.ts.map +0 -1
  159. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.js +0 -162
  160. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.js.map +0 -1
  161. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.ts +0 -428
  162. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.d.ts +0 -8
  163. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.d.ts.map +0 -1
  164. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.js +0 -36
  165. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.js.map +0 -1
  166. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.ts +0 -44
  167. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts +0 -837
  168. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts.map +0 -1
  169. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.js +0 -3
  170. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.js.map +0 -1
  171. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.ts +0 -861
  172. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.d.ts +0 -16
  173. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.d.ts.map +0 -1
  174. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.js +0 -182
  175. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.js.map +0 -1
  176. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.ts +0 -250
  177. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.d.ts +0 -4
  178. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.d.ts.map +0 -1
  179. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.js +0 -51
  180. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.js.map +0 -1
  181. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.ts +0 -61
  182. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.d.ts +0 -2
  183. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.d.ts.map +0 -1
  184. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.js +0 -954
  185. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.js.map +0 -1
  186. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.tsx +0 -1277
  187. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.d.ts +0 -2
  188. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.d.ts.map +0 -1
  189. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.js +0 -488
  190. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.js.map +0 -1
  191. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.tsx +0 -805
  192. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.d.ts +0 -6
  193. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.d.ts.map +0 -1
  194. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.js +0 -9
  195. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.js.map +0 -1
  196. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.tsx +0 -11
  197. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.d.ts +0 -6
  198. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.d.ts.map +0 -1
  199. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.js +0 -9
  200. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.js.map +0 -1
  201. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.tsx +0 -11
  202. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.d.ts +0 -2
  203. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.d.ts.map +0 -1
  204. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.js +0 -8
  205. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.js.map +0 -1
  206. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.tsx +0 -5
  207. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.d.ts +0 -2
  208. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.d.ts.map +0 -1
  209. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.js +0 -612
  210. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.js.map +0 -1
  211. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.tsx +0 -939
  212. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.d.ts +0 -6
  213. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.d.ts.map +0 -1
  214. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.js +0 -9
  215. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.js.map +0 -1
  216. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.tsx +0 -11
  217. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.d.ts +0 -6
  218. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.d.ts.map +0 -1
  219. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.js +0 -9
  220. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.js.map +0 -1
  221. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.tsx +0 -11
  222. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.d.ts +0 -6
  223. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.d.ts.map +0 -1
  224. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.js +0 -9
  225. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.js.map +0 -1
  226. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.tsx +0 -17
  227. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.d.ts +0 -2
  228. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.d.ts.map +0 -1
  229. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.js +0 -348
  230. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.js.map +0 -1
  231. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.tsx +0 -536
  232. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.d.ts +0 -2
  233. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.d.ts.map +0 -1
  234. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.js +0 -401
  235. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.js.map +0 -1
  236. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.tsx +0 -607
  237. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.d.ts +0 -5
  238. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.d.ts.map +0 -1
  239. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.js +0 -7
  240. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.js.map +0 -1
  241. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.tsx +0 -9
  242. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.d.ts +0 -6
  243. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.d.ts.map +0 -1
  244. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.js +0 -9
  245. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.js.map +0 -1
  246. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.tsx +0 -11
  247. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.d.ts +0 -2
  248. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.d.ts.map +0 -1
  249. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.js +0 -321
  250. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.js.map +0 -1
  251. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.tsx +0 -440
  252. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.d.ts +0 -2
  253. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.d.ts.map +0 -1
  254. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.js +0 -939
  255. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.js.map +0 -1
  256. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.tsx +0 -1499
  257. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.d.ts +0 -29
  258. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.d.ts.map +0 -1
  259. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.js +0 -95
  260. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.js.map +0 -1
  261. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.tsx +0 -233
  262. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.d.ts +0 -10
  263. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.d.ts.map +0 -1
  264. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.js +0 -577
  265. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.js.map +0 -1
  266. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.tsx +0 -868
  267. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.d.ts +0 -4
  268. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.d.ts.map +0 -1
  269. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.js +0 -337
  270. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.js.map +0 -1
  271. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.tsx +0 -476
  272. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.d.ts +0 -9
  273. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.d.ts.map +0 -1
  274. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.js +0 -1348
  275. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.js.map +0 -1
  276. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.tsx +0 -2233
  277. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.d.ts +0 -12
  278. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.d.ts.map +0 -1
  279. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.js +0 -162
  280. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.js.map +0 -1
  281. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.tsx +0 -261
  282. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.d.ts +0 -18
  283. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.d.ts.map +0 -1
  284. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.js +0 -145
  285. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.js.map +0 -1
  286. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.tsx +0 -258
  287. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.d.ts +0 -4
  288. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.d.ts.map +0 -1
  289. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.js +0 -223
  290. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.js.map +0 -1
  291. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.tsx +0 -342
  292. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.d.ts +0 -58
  293. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.d.ts.map +0 -1
  294. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.js +0 -438
  295. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.js.map +0 -1
  296. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.tsx +0 -698
  297. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.d.ts +0 -20
  298. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.d.ts.map +0 -1
  299. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.js +0 -233
  300. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.js.map +0 -1
  301. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.tsx +0 -392
  302. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.d.ts +0 -4
  303. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.d.ts.map +0 -1
  304. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.js +0 -814
  305. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.js.map +0 -1
  306. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.tsx +0 -1288
  307. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.d.ts +0 -21
  308. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.d.ts.map +0 -1
  309. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.js +0 -174
  310. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.js.map +0 -1
  311. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.tsx +0 -306
  312. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.d.ts +0 -10
  313. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.d.ts.map +0 -1
  314. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.js +0 -12
  315. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.js.map +0 -1
  316. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.tsx +0 -29
  317. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.d.ts +0 -15
  318. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.d.ts.map +0 -1
  319. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.js +0 -501
  320. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.js.map +0 -1
  321. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.tsx +0 -853
  322. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.d.ts +0 -6
  323. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.d.ts.map +0 -1
  324. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.js +0 -459
  325. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.js.map +0 -1
  326. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.tsx +0 -598
  327. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.d.ts +0 -6
  328. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.d.ts.map +0 -1
  329. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.js +0 -876
  330. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.js.map +0 -1
  331. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.tsx +0 -1368
  332. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.d.ts +0 -4
  333. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.d.ts.map +0 -1
  334. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.js +0 -2930
  335. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.js.map +0 -1
  336. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.tsx +0 -4378
  337. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.d.ts +0 -9
  338. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.d.ts.map +0 -1
  339. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.js +0 -1013
  340. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.js.map +0 -1
  341. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.tsx +0 -1745
  342. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.d.ts +0 -13
  343. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.d.ts.map +0 -1
  344. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.js +0 -38
  345. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.js.map +0 -1
  346. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.tsx +0 -74
  347. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.d.ts +0 -7
  348. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.d.ts.map +0 -1
  349. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.js +0 -11
  350. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.js.map +0 -1
  351. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.tsx +0 -15
  352. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.d.ts +0 -18
  353. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.d.ts.map +0 -1
  354. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.js +0 -406
  355. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.js.map +0 -1
  356. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.tsx +0 -660
  357. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.d.ts +0 -26
  358. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.d.ts.map +0 -1
  359. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.js +0 -332
  360. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.js.map +0 -1
  361. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.tsx +0 -518
  362. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.d.ts +0 -6
  363. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.d.ts.map +0 -1
  364. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.js +0 -255
  365. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.js.map +0 -1
  366. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.tsx +0 -388
  367. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.d.ts +0 -10
  368. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.d.ts.map +0 -1
  369. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.js +0 -131
  370. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.js.map +0 -1
  371. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.tsx +0 -214
  372. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.d.ts +0 -108
  373. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.d.ts.map +0 -1
  374. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.js +0 -162
  375. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.js.map +0 -1
  376. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.ts +0 -428
  377. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.d.ts +0 -8
  378. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.d.ts.map +0 -1
  379. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.js +0 -36
  380. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.js.map +0 -1
  381. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.ts +0 -44
  382. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts +0 -837
  383. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts.map +0 -1
  384. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.js +0 -3
  385. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.js.map +0 -1
  386. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.ts +0 -861
  387. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.d.ts +0 -16
  388. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.d.ts.map +0 -1
  389. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.js +0 -182
  390. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.js.map +0 -1
  391. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.ts +0 -250
  392. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.d.ts +0 -4
  393. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.d.ts.map +0 -1
  394. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.js +0 -51
  395. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.js.map +0 -1
  396. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.ts +0 -61
  397. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.d.ts +0 -2
  398. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.d.ts.map +0 -1
  399. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.js +0 -954
  400. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.js.map +0 -1
  401. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.tsx +0 -1277
  402. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.d.ts +0 -2
  403. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.d.ts.map +0 -1
  404. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.js +0 -488
  405. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.js.map +0 -1
  406. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.tsx +0 -805
  407. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.d.ts +0 -6
  408. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.d.ts.map +0 -1
  409. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.js +0 -9
  410. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.js.map +0 -1
  411. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.tsx +0 -11
  412. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.d.ts +0 -6
  413. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.d.ts.map +0 -1
  414. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.js +0 -9
  415. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.js.map +0 -1
  416. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.tsx +0 -11
  417. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.d.ts +0 -2
  418. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.d.ts.map +0 -1
  419. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.js +0 -8
  420. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.js.map +0 -1
  421. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.tsx +0 -5
  422. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.d.ts +0 -2
  423. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.d.ts.map +0 -1
  424. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.js +0 -612
  425. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.js.map +0 -1
  426. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.tsx +0 -939
  427. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.d.ts +0 -6
  428. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.d.ts.map +0 -1
  429. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.js +0 -9
  430. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.js.map +0 -1
  431. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.tsx +0 -11
  432. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.d.ts +0 -6
  433. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.d.ts.map +0 -1
  434. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.js +0 -9
  435. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.js.map +0 -1
  436. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.tsx +0 -11
  437. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.d.ts +0 -6
  438. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.d.ts.map +0 -1
  439. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.js +0 -9
  440. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.js.map +0 -1
  441. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.tsx +0 -17
  442. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.d.ts +0 -2
  443. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.d.ts.map +0 -1
  444. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.js +0 -348
  445. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.js.map +0 -1
  446. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.tsx +0 -536
  447. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.d.ts +0 -2
  448. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.d.ts.map +0 -1
  449. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.js +0 -401
  450. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.js.map +0 -1
  451. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.tsx +0 -607
  452. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.d.ts +0 -5
  453. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.d.ts.map +0 -1
  454. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.js +0 -7
  455. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.js.map +0 -1
  456. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.tsx +0 -9
  457. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.d.ts +0 -6
  458. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.d.ts.map +0 -1
  459. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.js +0 -9
  460. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.js.map +0 -1
  461. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.tsx +0 -11
  462. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.d.ts +0 -2
  463. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.d.ts.map +0 -1
  464. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.js +0 -321
  465. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.js.map +0 -1
  466. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.tsx +0 -440
  467. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.d.ts +0 -2
  468. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.d.ts.map +0 -1
  469. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.js +0 -939
  470. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.js.map +0 -1
  471. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.tsx +0 -1499
  472. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.d.ts +0 -2
  473. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.d.ts.map +0 -1
  474. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.js +0 -8
  475. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.js.map +0 -1
  476. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.tsx +0 -5
  477. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.d.ts +0 -2
  478. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.d.ts.map +0 -1
  479. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.js +0 -436
  480. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.js.map +0 -1
  481. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.tsx +0 -675
  482. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.d.ts +0 -2
  483. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.d.ts.map +0 -1
  484. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.js +0 -563
  485. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.js.map +0 -1
  486. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.tsx +0 -846
  487. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.d.ts +0 -6
  488. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.d.ts.map +0 -1
  489. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.js +0 -9
  490. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.js.map +0 -1
  491. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.tsx +0 -10
  492. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.d.ts +0 -6
  493. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.d.ts.map +0 -1
  494. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.js +0 -9
  495. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.js.map +0 -1
  496. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.tsx +0 -11
  497. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.d.ts +0 -6
  498. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.d.ts.map +0 -1
  499. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.js +0 -9
  500. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.js.map +0 -1
  501. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.tsx +0 -11
  502. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.d.ts +0 -2
  503. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.d.ts.map +0 -1
  504. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.js +0 -8
  505. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.js.map +0 -1
  506. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.tsx +0 -5
  507. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.d.ts +0 -2
  508. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.d.ts.map +0 -1
  509. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.js +0 -492
  510. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.js.map +0 -1
  511. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.tsx +0 -757
  512. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.d.ts +0 -2
  513. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.d.ts.map +0 -1
  514. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.js +0 -342
  515. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.js.map +0 -1
  516. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.tsx +0 -430
  517. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.d.ts +0 -2
  518. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.d.ts.map +0 -1
  519. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.js +0 -338
  520. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.js.map +0 -1
  521. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.tsx +0 -428
  522. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.d.ts +0 -2
  523. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.d.ts.map +0 -1
  524. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.js +0 -660
  525. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.js.map +0 -1
  526. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.tsx +0 -992
  527. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.d.ts +0 -2
  528. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.d.ts.map +0 -1
  529. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.js +0 -515
  530. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.js.map +0 -1
  531. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.tsx +0 -707
  532. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.d.ts +0 -2
  533. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.d.ts.map +0 -1
  534. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.js +0 -1141
  535. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.js.map +0 -1
  536. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.tsx +0 -1705
  537. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.d.ts +0 -2
  538. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.d.ts.map +0 -1
  539. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.js +0 -8
  540. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.js.map +0 -1
  541. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.tsx +0 -5
  542. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.d.ts +0 -2
  543. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.d.ts.map +0 -1
  544. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.js +0 -436
  545. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.js.map +0 -1
  546. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.tsx +0 -675
  547. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.d.ts +0 -2
  548. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.d.ts.map +0 -1
  549. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.js +0 -563
  550. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.js.map +0 -1
  551. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.tsx +0 -846
  552. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.d.ts +0 -6
  553. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.d.ts.map +0 -1
  554. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.js +0 -9
  555. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.js.map +0 -1
  556. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.tsx +0 -11
  557. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.d.ts +0 -6
  558. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.d.ts.map +0 -1
  559. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.js +0 -9
  560. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.js.map +0 -1
  561. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.tsx +0 -11
  562. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.d.ts +0 -2
  563. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.d.ts.map +0 -1
  564. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.js +0 -8
  565. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.js.map +0 -1
  566. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.tsx +0 -5
  567. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.d.ts +0 -2
  568. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.d.ts.map +0 -1
  569. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.js +0 -492
  570. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.js.map +0 -1
  571. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.tsx +0 -757
  572. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.d.ts +0 -2
  573. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.d.ts.map +0 -1
  574. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.js +0 -342
  575. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.js.map +0 -1
  576. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.tsx +0 -430
  577. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.d.ts +0 -2
  578. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.d.ts.map +0 -1
  579. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.js +0 -338
  580. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.js.map +0 -1
  581. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.tsx +0 -428
  582. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.d.ts +0 -2
  583. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.d.ts.map +0 -1
  584. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.js +0 -660
  585. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.js.map +0 -1
  586. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.tsx +0 -992
  587. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.d.ts +0 -2
  588. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.d.ts.map +0 -1
  589. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.js +0 -515
  590. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.js.map +0 -1
  591. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.tsx +0 -707
  592. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.d.ts +0 -2
  593. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.d.ts.map +0 -1
  594. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.js +0 -1141
  595. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.js.map +0 -1
  596. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.tsx +0 -1705
@@ -1,2930 +0,0 @@
1
- "use strict";
2
- 'use client';
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ProjectDetailsScreen = ProjectDetailsScreen;
8
- const entity_list_1 = require("@/components/entity-list");
9
- const rich_text_editor_1 = require("@/components/rich-text-editor");
10
- const avatar_1 = require("@/components/ui/avatar");
11
- const button_1 = require("@/components/ui/button");
12
- const card_1 = require("@/components/ui/card");
13
- const chart_1 = require("@/components/ui/chart");
14
- const dialog_1 = require("@/components/ui/dialog");
15
- const dropdown_menu_1 = require("@/components/ui/dropdown-menu");
16
- const input_1 = require("@/components/ui/input");
17
- const label_1 = require("@/components/ui/label");
18
- const progress_1 = require("@/components/ui/progress");
19
- const select_1 = require("@/components/ui/select");
20
- const sheet_1 = require("@/components/ui/sheet");
21
- const skeleton_1 = require("@/components/ui/skeleton");
22
- const table_1 = require("@/components/ui/table");
23
- const tooltip_1 = require("@/components/ui/tooltip");
24
- const core_1 = require("@dnd-kit/core");
25
- const utilities_1 = require("@dnd-kit/utilities");
26
- const next_app_provider_1 = require("@hed-hog/next-app-provider");
27
- const framer_motion_1 = require("framer-motion");
28
- const lucide_react_1 = require("lucide-react");
29
- const next_intl_1 = require("next-intl");
30
- const link_1 = __importDefault(require("next/link"));
31
- const navigation_1 = require("next/navigation");
32
- const react_1 = require("react");
33
- const recharts_1 = require("recharts");
34
- const api_1 = require("../_lib/api");
35
- const use_operations_access_1 = require("../_lib/hooks/use-operations-access");
36
- const format_1 = require("../_lib/utils/format");
37
- const operations_header_1 = require("./operations-header");
38
- const project_costs_section_1 = require("./project-costs-section");
39
- const project_form_screen_1 = require("./project-form-screen");
40
- const section_card_1 = require("./section-card");
41
- const status_badge_1 = require("./status-badge");
42
- const task_detail_sheet_1 = require("./task-detail-sheet");
43
- const task_file_attachments_1 = require("./task-file-attachments");
44
- const EMPTY_TASK_FORM = {
45
- name: '',
46
- description: '',
47
- priority: 'medium',
48
- status: 'todo',
49
- assigneeCollaboratorId: 'none',
50
- dueDate: '',
51
- estimateHours: '',
52
- tags: '',
53
- };
54
- const KANBAN_COLUMNS = [
55
- { id: 'todo', label: 'Backlog' },
56
- { id: 'doing', label: 'Em execução' },
57
- { id: 'review', label: 'Revisão' },
58
- { id: 'done', label: 'Concluído' },
59
- ];
60
- // Prefer pointer-within so any column the cursor enters triggers a drop target.
61
- // Falls back to closestCenter for the gap between columns.
62
- const kanbanCollision = (args) => {
63
- const within = (0, core_1.pointerWithin)(args);
64
- if (within.length > 0)
65
- return within;
66
- return (0, core_1.closestCenter)(args);
67
- };
68
- function apiTaskToBoardTask(row) {
69
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
70
- const status = KANBAN_COLUMNS.some((c) => c.id === row.status)
71
- ? row.status
72
- : 'todo';
73
- return {
74
- id: row.id,
75
- name: row.name,
76
- description: (_a = row.description) !== null && _a !== void 0 ? _a : null,
77
- status,
78
- priority: (_b = row.priority) !== null && _b !== void 0 ? _b : 'medium',
79
- dueDate: (_c = row.dueDate) !== null && _c !== void 0 ? _c : null,
80
- estimateHours: (_d = row.estimateHours) !== null && _d !== void 0 ? _d : null,
81
- tags: (_e = row.tags) !== null && _e !== void 0 ? _e : null,
82
- assigneeCollaboratorId: (_f = row.assigneeCollaboratorId) !== null && _f !== void 0 ? _f : null,
83
- assigneeName: (_g = row.assigneeName) !== null && _g !== void 0 ? _g : null,
84
- assigneeUserPhotoId: (_h = row.assigneeUserPhotoId) !== null && _h !== void 0 ? _h : null,
85
- assigneePersonAvatarId: (_j = row.assigneePersonAvatarId) !== null && _j !== void 0 ? _j : null,
86
- projectAssignmentId: (_k = row.projectAssignmentId) !== null && _k !== void 0 ? _k : null,
87
- createdAt: (_l = row.createdAt) !== null && _l !== void 0 ? _l : null,
88
- commentCount: (_m = row.commentCount) !== null && _m !== void 0 ? _m : 0,
89
- fileCount: (_o = row.fileCount) !== null && _o !== void 0 ? _o : 0,
90
- };
91
- }
92
- function splitTasksByColumn(tasks) {
93
- return {
94
- todo: tasks.filter((t) => t.status === 'todo'),
95
- doing: tasks.filter((t) => t.status === 'doing'),
96
- review: tasks.filter((t) => t.status === 'review'),
97
- done: tasks.filter((t) => t.status === 'done'),
98
- };
99
- }
100
- const boardChartConfig = {
101
- allocation: { label: 'Alocacao', color: 'hsl(201 96% 32%)' },
102
- loggedHours: { label: 'Horas', color: 'hsl(166 72% 28%)' },
103
- progress: { label: 'Progresso', color: 'hsl(262 83% 58%)' },
104
- planned: { label: 'Planejado', color: 'hsl(215 16% 47%)' },
105
- todo: { label: 'Backlog', color: 'hsl(215 16% 47%)' },
106
- doing: { label: 'Em execucao', color: 'hsl(201 96% 32%)' },
107
- review: { label: 'Revisao', color: 'hsl(38 92% 50%)' },
108
- done: { label: 'Concluido', color: 'hsl(166 72% 28%)' },
109
- health: { label: 'Saude', color: 'hsl(166 72% 28%)' },
110
- };
111
- function taskDragId(taskId) {
112
- return `task-${taskId}`;
113
- }
114
- function columnDropId(columnId) {
115
- return `col-${columnId}`;
116
- }
117
- function parseTaskId(value) {
118
- if (!value) {
119
- return null;
120
- }
121
- const id = String(value);
122
- if (!id.startsWith('task-')) {
123
- return null;
124
- }
125
- const parsed = Number(id.slice(5));
126
- return Number.isFinite(parsed) ? parsed : null;
127
- }
128
- function parseColumnId(value) {
129
- if (!value) {
130
- return null;
131
- }
132
- const id = String(value);
133
- if (!id.startsWith('col-')) {
134
- return null;
135
- }
136
- const column = id.slice(4);
137
- return KANBAN_COLUMNS.some((item) => item.id === column)
138
- ? column
139
- : null;
140
- }
141
- function DroppableColumn({ columnId, children, }) {
142
- const { isOver, setNodeRef } = (0, core_1.useDroppable)({ id: columnDropId(columnId) });
143
- return <div ref={setNodeRef}>{children(isOver)}</div>;
144
- }
145
- function DraggableTaskCard({ task, disabled = false, children, }) {
146
- const { attributes, listeners, setNodeRef, transform, isDragging } = (0, core_1.useDraggable)({ id: taskDragId(task.id), disabled });
147
- return (<div ref={setNodeRef} style={{ transform: utilities_1.CSS.Translate.toString(transform) }} {...(disabled ? {} : listeners)} {...(disabled ? {} : attributes)} className={isDragging ? 'z-20' : undefined}>
148
- {children(disabled ? false : isDragging)}
149
- </div>);
150
- }
151
- function shouldOpenEditSheet(value, projectId) {
152
- if (!value) {
153
- return false;
154
- }
155
- return value === '1' || value === 'true' || value === String(projectId);
156
- }
157
- function getInitials(value) {
158
- const parts = String(value !== null && value !== void 0 ? value : '')
159
- .trim()
160
- .split(/\s+/)
161
- .filter(Boolean)
162
- .slice(0, 2);
163
- if (!parts.length) {
164
- return '??';
165
- }
166
- return parts.map((part) => { var _a, _b; return (_b = (_a = part[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : ''; }).join('');
167
- }
168
- function getPersonAvatarUrl(avatarId) {
169
- return typeof avatarId === 'number' && avatarId > 0
170
- ? `${process.env.NEXT_PUBLIC_API_BASE_URL}/person/avatar/${avatarId}`
171
- : '/placeholder.png';
172
- }
173
- function getUserPhotoUrl(photoId) {
174
- return typeof photoId === 'number' && photoId > 0
175
- ? `${process.env.NEXT_PUBLIC_API_BASE_URL}/file/open/${photoId}`
176
- : null;
177
- }
178
- function normalizeDateInputValue(value) {
179
- if (!value) {
180
- return '';
181
- }
182
- const normalizedValue = String(value).trim();
183
- const directMatch = normalizedValue.match(/^\d{4}-\d{2}-\d{2}/);
184
- if (directMatch === null || directMatch === void 0 ? void 0 : directMatch[0]) {
185
- return directMatch[0];
186
- }
187
- const parsedDate = new Date(normalizedValue);
188
- if (Number.isNaN(parsedDate.getTime())) {
189
- return '';
190
- }
191
- return parsedDate.toISOString().slice(0, 10);
192
- }
193
- function clampPercent(value) {
194
- if (typeof value !== 'number' || Number.isNaN(value)) {
195
- return 0;
196
- }
197
- return Math.max(0, Math.min(100, Math.round(value)));
198
- }
199
- function isPastDue(value) {
200
- if (!value) {
201
- return false;
202
- }
203
- const date = new Date(value);
204
- if (Number.isNaN(date.getTime())) {
205
- return false;
206
- }
207
- const today = new Date();
208
- today.setHours(0, 0, 0, 0);
209
- date.setHours(0, 0, 0, 0);
210
- return date < today;
211
- }
212
- function getTaskProgress(status) {
213
- const progressByStatus = {
214
- todo: 12,
215
- doing: 48,
216
- review: 76,
217
- done: 100,
218
- };
219
- return progressByStatus[status];
220
- }
221
- function getPriorityClassName(priority) {
222
- if (priority === 'high') {
223
- return 'border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-300';
224
- }
225
- if (priority === 'medium') {
226
- return 'border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300';
227
- }
228
- return 'border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300';
229
- }
230
- function getColumnClassName(columnId) {
231
- const styles = {
232
- todo: 'from-slate-500/20 via-slate-500/5 to-transparent',
233
- doing: 'from-sky-500/20 via-cyan-500/5 to-transparent',
234
- review: 'from-amber-500/20 via-yellow-500/5 to-transparent',
235
- done: 'from-emerald-500/20 via-green-500/5 to-transparent',
236
- };
237
- return styles[columnId];
238
- }
239
- function getColumnDotClassName(columnId) {
240
- const styles = {
241
- todo: 'bg-slate-500',
242
- doing: 'bg-sky-500',
243
- review: 'bg-amber-500',
244
- done: 'bg-emerald-500',
245
- };
246
- return styles[columnId];
247
- }
248
- function getTaskTags(task) {
249
- var _a;
250
- return String((_a = task.tags) !== null && _a !== void 0 ? _a : '')
251
- .split(',')
252
- .map((tag) => tag.trim())
253
- .filter(Boolean);
254
- }
255
- function getTaskCommentCount(task) {
256
- var _a;
257
- return (_a = task.commentCount) !== null && _a !== void 0 ? _a : 0;
258
- }
259
- function getTaskAttachmentCount(task) {
260
- var _a;
261
- return (_a = task.fileCount) !== null && _a !== void 0 ? _a : 0;
262
- }
263
- function getAllocationTone(allocation) {
264
- if (allocation > 100) {
265
- return {
266
- labelKey: 'overload',
267
- text: 'text-rose-700 dark:text-rose-300',
268
- border: 'border-rose-500/30',
269
- bg: 'bg-rose-500/10',
270
- progress: '[&>div]:bg-rose-500',
271
- icon: lucide_react_1.AlertTriangle,
272
- };
273
- }
274
- if (allocation >= 85) {
275
- return {
276
- labelKey: 'high',
277
- text: 'text-amber-700 dark:text-amber-300',
278
- border: 'border-amber-500/30',
279
- bg: 'bg-amber-500/10',
280
- progress: '[&>div]:bg-amber-500',
281
- icon: lucide_react_1.Gauge,
282
- };
283
- }
284
- return {
285
- labelKey: 'available',
286
- text: 'text-emerald-700 dark:text-emerald-300',
287
- border: 'border-emerald-500/30',
288
- bg: 'bg-emerald-500/10',
289
- progress: '[&>div]:bg-emerald-500',
290
- icon: lucide_react_1.CheckCircle2,
291
- };
292
- }
293
- function getValidTimestamp(value) {
294
- if (!value) {
295
- return null;
296
- }
297
- const date = new Date(value);
298
- if (Number.isNaN(date.getTime())) {
299
- return null;
300
- }
301
- return date.toISOString();
302
- }
303
- function formatRelativeTime(value, locale) {
304
- const date = new Date(value);
305
- if (Number.isNaN(date.getTime())) {
306
- return '';
307
- }
308
- const diffSeconds = Math.round((date.getTime() - Date.now()) / 1000);
309
- const units = [
310
- ['year', 60 * 60 * 24 * 365],
311
- ['month', 60 * 60 * 24 * 30],
312
- ['day', 60 * 60 * 24],
313
- ['hour', 60 * 60],
314
- ['minute', 60],
315
- ];
316
- const formatter = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
317
- for (const [unit, seconds] of units) {
318
- if (Math.abs(diffSeconds) >= seconds) {
319
- return formatter.format(Math.round(diffSeconds / seconds), unit);
320
- }
321
- }
322
- return formatter.format(diffSeconds, 'second');
323
- }
324
- function getTimelineDayKey(value) {
325
- const date = new Date(value);
326
- if (Number.isNaN(date.getTime())) {
327
- return value;
328
- }
329
- return date.toISOString().slice(0, 10);
330
- }
331
- function getProjectHealthScore({ progress, averageAllocation, overdueTasks, pendingTimesheets, }) {
332
- const progressScore = clampPercent(progress);
333
- const allocation = typeof averageAllocation === 'number' && !Number.isNaN(averageAllocation)
334
- ? Math.round(averageAllocation)
335
- : 0;
336
- const allocationPenalty = allocation > 100 ? 16 : allocation > 85 ? 6 : 0;
337
- const overduePenalty = Math.min(overdueTasks * 9, 32);
338
- const timesheetPenalty = Math.min(pendingTimesheets * 4, 20);
339
- const value = clampPercent(72 +
340
- progressScore * 0.18 -
341
- allocationPenalty -
342
- overduePenalty -
343
- timesheetPenalty);
344
- if (value >= 75) {
345
- return { value, labelKey: 'good', tone: 'good' };
346
- }
347
- if (value >= 50) {
348
- return { value, labelKey: 'warning', tone: 'warning' };
349
- }
350
- return { value, labelKey: 'danger', tone: 'danger' };
351
- }
352
- const kpiToneStyles = {
353
- positive: {
354
- accent: 'from-emerald-500/25 via-teal-500/10 to-transparent',
355
- icon: 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-300',
356
- value: 'text-emerald-700 dark:text-emerald-300',
357
- indicator: 'bg-emerald-500',
358
- trend: 'text-emerald-700 dark:text-emerald-300',
359
- },
360
- warning: {
361
- accent: 'from-amber-500/25 via-yellow-500/10 to-transparent',
362
- icon: 'bg-amber-500/10 text-amber-700 dark:text-amber-300',
363
- value: 'text-amber-700 dark:text-amber-300',
364
- indicator: 'bg-amber-500',
365
- trend: 'text-amber-700 dark:text-amber-300',
366
- },
367
- critical: {
368
- accent: 'from-rose-500/25 via-red-500/10 to-transparent',
369
- icon: 'bg-rose-500/10 text-rose-700 dark:text-rose-300',
370
- value: 'text-rose-700 dark:text-rose-300',
371
- indicator: 'bg-rose-500',
372
- trend: 'text-rose-700 dark:text-rose-300',
373
- },
374
- info: {
375
- accent: 'from-sky-500/25 via-cyan-500/10 to-transparent',
376
- icon: 'bg-sky-500/10 text-sky-700 dark:text-sky-300',
377
- value: 'text-sky-700 dark:text-sky-300',
378
- indicator: 'bg-sky-500',
379
- trend: 'text-sky-700 dark:text-sky-300',
380
- },
381
- neutral: {
382
- accent: 'from-violet-500/25 via-indigo-500/10 to-transparent',
383
- icon: 'bg-violet-500/10 text-violet-700 dark:text-violet-300',
384
- value: 'text-foreground',
385
- indicator: 'bg-violet-500',
386
- trend: 'text-muted-foreground',
387
- },
388
- };
389
- function ProjectKpiWidget({ item, indicatorLabel, index = 0, }) {
390
- const Icon = item.icon;
391
- const tone = kpiToneStyles[item.tone];
392
- return (<framer_motion_1.motion.div initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{
393
- type: 'spring',
394
- stiffness: 340,
395
- damping: 26,
396
- delay: index * 0.07,
397
- }} whileHover={{ y: -4 }} className="min-w-0">
398
- <card_1.Card className="group relative h-full overflow-hidden border-border/70 bg-card py-0 shadow-xs transition-shadow hover:shadow-md">
399
- <div className={[
400
- 'absolute inset-x-0 top-0 h-20 bg-linear-to-br',
401
- tone.accent,
402
- ].join(' ')}/>
403
- <card_1.CardContent className="relative flex h-full flex-col gap-5 p-4">
404
- <div className="flex items-start justify-between gap-3">
405
- <div className={[
406
- 'flex size-10 items-center justify-center rounded-2xl transition-transform group-hover:scale-105',
407
- tone.icon,
408
- ].join(' ')}>
409
- <Icon className="size-5"/>
410
- </div>
411
- <span className={[
412
- 'rounded-full border bg-background/80 px-2 py-0.5 text-[11px] font-medium',
413
- tone.trend,
414
- ].join(' ')}>
415
- {item.trend}
416
- </span>
417
- </div>
418
-
419
- <div className="min-w-0">
420
- <div className={[
421
- 'truncate text-3xl font-semibold tracking-tight tabular-nums',
422
- tone.value,
423
- ].join(' ')}>
424
- {item.value}
425
- </div>
426
- <div className="mt-1 text-sm font-medium text-foreground">
427
- {item.title}
428
- </div>
429
- <div className="mt-1 line-clamp-2 text-xs leading-5 text-muted-foreground">
430
- {item.subtitle}
431
- </div>
432
- </div>
433
-
434
- <div className="mt-auto space-y-2">
435
- <div className="flex items-center justify-between text-[11px] text-muted-foreground">
436
- <span>{indicatorLabel}</span>
437
- <span>{clampPercent(item.indicator)}%</span>
438
- </div>
439
- <div className="h-1.5 overflow-hidden rounded-full bg-muted">
440
- <div className={[
441
- 'h-full rounded-full transition-all duration-500',
442
- tone.indicator,
443
- ].join(' ')} style={{ width: `${clampPercent(item.indicator)}%` }}/>
444
- </div>
445
- </div>
446
- </card_1.CardContent>
447
- </card_1.Card>
448
- </framer_motion_1.motion.div>);
449
- }
450
- function ChartEmptyState({ icon: Icon, title, description, }) {
451
- return (<div className="flex h-72 flex-col items-center justify-center rounded-xl border border-dashed bg-muted/10 p-6 text-center">
452
- <div className="flex size-11 items-center justify-center rounded-2xl bg-muted text-muted-foreground">
453
- <Icon className="size-5"/>
454
- </div>
455
- <div className="mt-3 text-sm font-medium">{title}</div>
456
- <div className="mt-1 max-w-xs text-xs leading-5 text-muted-foreground">
457
- {description}
458
- </div>
459
- </div>);
460
- }
461
- function ProjectChartCard({ title, description, icon: Icon, metric, children, className, isLoading = false, }) {
462
- return (<framer_motion_1.motion.div initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.22 }} className={className}>
463
- <card_1.Card className="h-full overflow-hidden border-border/70 bg-card py-0 shadow-sm">
464
- <card_1.CardContent className="flex h-full flex-col gap-4 p-4">
465
- <div className="flex items-start justify-between gap-4">
466
- <div className="flex min-w-0 items-start gap-3">
467
- <div className="flex size-10 shrink-0 items-center justify-center rounded-2xl bg-muted text-foreground">
468
- <Icon className="size-5"/>
469
- </div>
470
- <div className="min-w-0">
471
- <div className="text-sm font-semibold">{title}</div>
472
- {description ? (<div className="mt-1 text-xs leading-5 text-muted-foreground">
473
- {description}
474
- </div>) : null}
475
- </div>
476
- </div>
477
- {metric ? (<div className="shrink-0 rounded-full border bg-background px-3 py-1 text-xs font-medium text-muted-foreground">
478
- {metric}
479
- </div>) : null}
480
- </div>
481
- {isLoading ? <skeleton_1.Skeleton className="h-72 rounded-xl"/> : children}
482
- </card_1.CardContent>
483
- </card_1.Card>
484
- </framer_motion_1.motion.div>);
485
- }
486
- function ProjectDetailsSkeleton() {
487
- return (<entity_list_1.Page>
488
- <div className="space-y-6">
489
- {/* Hero header */}
490
- <div className="overflow-hidden rounded-3xl border bg-card shadow-sm">
491
- <div className="border-b p-5 sm:p-6">
492
- <div className="space-y-4">
493
- {/* Breadcrumb */}
494
- <div className="flex items-center gap-2">
495
- <skeleton_1.Skeleton className="h-4 w-20 rounded-full"/>
496
- <skeleton_1.Skeleton className="h-3 w-3 rounded-full"/>
497
- <skeleton_1.Skeleton className="h-4 w-16 rounded-full"/>
498
- <skeleton_1.Skeleton className="h-3 w-3 rounded-full"/>
499
- <skeleton_1.Skeleton className="h-4 w-32 rounded-full"/>
500
- </div>
501
- {/* Title row */}
502
- <div className="flex items-start gap-4">
503
- <skeleton_1.Skeleton className="size-14 shrink-0 rounded-2xl"/>
504
- <div className="flex-1 space-y-2">
505
- <div className="flex gap-2">
506
- <skeleton_1.Skeleton className="h-6 w-20 rounded-full"/>
507
- <skeleton_1.Skeleton className="h-6 w-16 rounded-full"/>
508
- </div>
509
- <skeleton_1.Skeleton className="h-8 w-72"/>
510
- <skeleton_1.Skeleton className="h-4 w-full max-w-md"/>
511
- </div>
512
- <div className="hidden flex-shrink-0 gap-2 lg:flex">
513
- <skeleton_1.Skeleton className="h-9 w-20 rounded-lg"/>
514
- <skeleton_1.Skeleton className="h-9 w-28 rounded-lg"/>
515
- <skeleton_1.Skeleton className="h-9 w-9 rounded-lg"/>
516
- </div>
517
- </div>
518
- {/* Meta grid */}
519
- <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-7">
520
- <skeleton_1.Skeleton className="h-16 rounded-xl xl:col-span-2"/>
521
- <skeleton_1.Skeleton className="h-16 rounded-xl"/>
522
- <skeleton_1.Skeleton className="h-16 rounded-xl"/>
523
- <skeleton_1.Skeleton className="h-16 rounded-xl"/>
524
- <skeleton_1.Skeleton className="h-16 rounded-xl"/>
525
- <skeleton_1.Skeleton className="h-16 rounded-xl"/>
526
- </div>
527
- {/* Team row */}
528
- <div className="rounded-2xl border p-4">
529
- <div className="flex items-center justify-between gap-4">
530
- <div className="flex items-center gap-3">
531
- <div className="space-y-1">
532
- <skeleton_1.Skeleton className="h-3 w-12"/>
533
- <skeleton_1.Skeleton className="h-5 w-24"/>
534
- </div>
535
- <div className="flex -space-x-2">
536
- {Array.from({ length: 4 }).map((_, i) => (<skeleton_1.Skeleton key={i} className="size-10 rounded-full border-2 border-background"/>))}
537
- </div>
538
- </div>
539
- <div className="grid grid-cols-3 gap-3">
540
- <skeleton_1.Skeleton className="h-16 w-28 rounded-xl"/>
541
- <skeleton_1.Skeleton className="h-16 w-28 rounded-xl"/>
542
- <skeleton_1.Skeleton className="h-16 w-28 rounded-xl"/>
543
- </div>
544
- </div>
545
- </div>
546
- </div>
547
- </div>
548
- </div>
549
-
550
- {/* KPI row */}
551
- <div className="rounded-3xl border p-3 sm:p-4">
552
- <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-6">
553
- {Array.from({ length: 6 }).map((_, i) => (<div key={i} className="overflow-hidden rounded-xl border p-4">
554
- <div className="flex items-start justify-between gap-3">
555
- <skeleton_1.Skeleton className="size-10 rounded-2xl"/>
556
- <skeleton_1.Skeleton className="h-5 w-16 rounded-full"/>
557
- </div>
558
- <div className="mt-5 space-y-2">
559
- <skeleton_1.Skeleton className="h-8 w-24"/>
560
- <skeleton_1.Skeleton className="h-4 w-32"/>
561
- <skeleton_1.Skeleton className="h-3 w-full"/>
562
- </div>
563
- <div className="mt-auto pt-4 space-y-2">
564
- <div className="flex justify-between">
565
- <skeleton_1.Skeleton className="h-3 w-16"/>
566
- <skeleton_1.Skeleton className="h-3 w-8"/>
567
- </div>
568
- <skeleton_1.Skeleton className="h-1.5 w-full rounded-full"/>
569
- </div>
570
- </div>))}
571
- </div>
572
- </div>
573
-
574
- {/* Overview */}
575
- <div className="rounded-xl border p-4">
576
- <skeleton_1.Skeleton className="mb-4 h-5 w-28"/>
577
- <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
578
- {Array.from({ length: 9 }).map((_, i) => (<div key={i} className="space-y-1.5">
579
- <skeleton_1.Skeleton className="h-3 w-20"/>
580
- <skeleton_1.Skeleton className="h-5 w-32"/>
581
- </div>))}
582
- </div>
583
- <div className="mt-6 space-y-1.5">
584
- <skeleton_1.Skeleton className="h-3 w-16"/>
585
- <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
586
- {Array.from({ length: 4 }).map((_, i) => (<div key={i} className="space-y-1.5">
587
- <skeleton_1.Skeleton className="h-3 w-24"/>
588
- <skeleton_1.Skeleton className="h-5 w-36"/>
589
- </div>))}
590
- </div>
591
- </div>
592
- </div>
593
-
594
- {/* Charts */}
595
- <div className="rounded-3xl border p-4">
596
- <skeleton_1.Skeleton className="mb-4 h-5 w-36"/>
597
- <div className="grid gap-4 xl:grid-cols-12">
598
- <skeleton_1.Skeleton className="h-80 rounded-xl xl:col-span-8"/>
599
- <skeleton_1.Skeleton className="h-80 rounded-xl xl:col-span-4"/>
600
- <skeleton_1.Skeleton className="h-72 rounded-xl xl:col-span-5"/>
601
- <skeleton_1.Skeleton className="h-72 rounded-xl xl:col-span-4"/>
602
- <skeleton_1.Skeleton className="h-72 rounded-xl xl:col-span-3"/>
603
- </div>
604
- </div>
605
-
606
- {/* Kanban */}
607
- <div className="rounded-3xl border p-4">
608
- <div className="mb-4 flex items-center justify-between">
609
- <skeleton_1.Skeleton className="h-5 w-28"/>
610
- <skeleton_1.Skeleton className="h-9 w-28 rounded-lg"/>
611
- </div>
612
- <div className="mb-4 rounded-2xl border p-3">
613
- <div className="flex gap-3">
614
- <skeleton_1.Skeleton className="h-10 flex-1 rounded-lg"/>
615
- <skeleton_1.Skeleton className="h-10 w-44 rounded-lg"/>
616
- <skeleton_1.Skeleton className="h-10 w-44 rounded-lg"/>
617
- </div>
618
- </div>
619
- <div className="grid gap-4 xl:grid-cols-4">
620
- {Array.from({ length: 4 }).map((_, col) => (<div key={col} className="min-h-48 rounded-3xl border p-3 space-y-3">
621
- <div className="rounded-2xl border bg-background/85 p-3 flex items-center justify-between">
622
- <div className="space-y-1">
623
- <div className="flex items-center gap-2">
624
- <skeleton_1.Skeleton className="size-2.5 rounded-full"/>
625
- <skeleton_1.Skeleton className="h-4 w-20"/>
626
- </div>
627
- <skeleton_1.Skeleton className="h-3 w-12"/>
628
- </div>
629
- <skeleton_1.Skeleton className="size-5 rounded-full"/>
630
- </div>
631
- {Array.from({ length: col === 0 ? 3 : col === 1 ? 2 : 1 }).map((_, card) => (<div key={card} className="rounded-2xl border bg-card p-3 space-y-3">
632
- <div className="flex items-start justify-between gap-2">
633
- <div className="flex-1 space-y-1">
634
- <skeleton_1.Skeleton className="h-4 w-full"/>
635
- <skeleton_1.Skeleton className="h-3 w-3/4"/>
636
- </div>
637
- <skeleton_1.Skeleton className="h-5 w-12 rounded-full"/>
638
- </div>
639
- <div className="grid grid-cols-2 gap-2">
640
- <skeleton_1.Skeleton className="h-8 rounded-xl"/>
641
- <skeleton_1.Skeleton className="h-8 rounded-xl"/>
642
- </div>
643
- <div className="space-y-1.5">
644
- <skeleton_1.Skeleton className="h-1.5 w-full rounded-full"/>
645
- </div>
646
- <div className="flex items-center justify-between border-t pt-3">
647
- <div className="flex items-center gap-2">
648
- <skeleton_1.Skeleton className="size-7 rounded-full"/>
649
- <skeleton_1.Skeleton className="h-3 w-20"/>
650
- </div>
651
- <div className="flex gap-2">
652
- <skeleton_1.Skeleton className="h-3 w-6"/>
653
- <skeleton_1.Skeleton className="h-3 w-6"/>
654
- </div>
655
- </div>
656
- </div>))}
657
- </div>))}
658
- </div>
659
- </div>
660
-
661
- {/* Timeline */}
662
- <div className="rounded-3xl border p-4">
663
- <skeleton_1.Skeleton className="mb-4 h-5 w-24"/>
664
- <div className="rounded-3xl border p-4 space-y-6">
665
- {Array.from({ length: 3 }).map((_, group) => (<div key={group} className="space-y-3">
666
- <skeleton_1.Skeleton className="h-6 w-28 rounded-full"/>
667
- {Array.from({ length: 2 }).map((_, event) => (<div key={event} className="grid grid-cols-[2rem_1fr] gap-3">
668
- <div className="flex flex-col items-center">
669
- <skeleton_1.Skeleton className="size-8 rounded-full"/>
670
- {event === 0 ? (<div className="w-px flex-1 bg-border mt-1"/>) : null}
671
- </div>
672
- <div className="pb-5">
673
- <div className="rounded-2xl border p-4 space-y-3">
674
- <div className="flex justify-between">
675
- <div className="space-y-1.5">
676
- <skeleton_1.Skeleton className="h-4 w-40"/>
677
- <skeleton_1.Skeleton className="h-3 w-56"/>
678
- </div>
679
- <skeleton_1.Skeleton className="h-3 w-16"/>
680
- </div>
681
- <div className="flex items-center gap-2 border-t pt-3">
682
- <skeleton_1.Skeleton className="size-7 rounded-full"/>
683
- <skeleton_1.Skeleton className="h-3 w-24"/>
684
- </div>
685
- </div>
686
- </div>
687
- </div>))}
688
- </div>))}
689
- </div>
690
- </div>
691
- </div>
692
- </entity_list_1.Page>);
693
- }
694
- function ProjectDetailsScreen({ projectId }) {
695
- var _a, _b, _c, _d, _e;
696
- const t = (0, next_intl_1.useTranslations)('operations.ProjectDetailsPage');
697
- const commonT = (0, next_intl_1.useTranslations)('operations.Common');
698
- const formT = (0, next_intl_1.useTranslations)('operations.ProjectFormPage');
699
- const contractT = (0, next_intl_1.useTranslations)('operations.ContractFormPage');
700
- const { request, currentLocaleCode, getSettingValue } = (0, next_app_provider_1.useApp)();
701
- const access = (0, use_operations_access_1.useOperationsAccess)();
702
- const isLimitedView = !access.isDirector && !access.isSupervisor;
703
- const router = (0, navigation_1.useRouter)();
704
- const pathname = (0, navigation_1.usePathname)();
705
- const searchParams = (0, navigation_1.useSearchParams)();
706
- const getProjectStatusLabel = (value) => {
707
- if (!value)
708
- return commonT('labels.notAvailable');
709
- try {
710
- return formT(`options.statuses.${value}`);
711
- }
712
- catch (_a) {
713
- return (0, format_1.formatEnumLabel)(value);
714
- }
715
- };
716
- const getContractStatusLabel = (value) => {
717
- if (!value)
718
- return commonT('labels.notAvailable');
719
- try {
720
- return contractT(`options.statuses.${value}`);
721
- }
722
- catch (_a) {
723
- return (0, format_1.formatEnumLabel)(value);
724
- }
725
- };
726
- const getContractCategoryLabel = (value) => {
727
- if (!value)
728
- return commonT('labels.notAvailable');
729
- try {
730
- return contractT(`options.contractCategories.${value}`);
731
- }
732
- catch (_a) {
733
- return (0, format_1.formatEnumLabel)(value);
734
- }
735
- };
736
- const getContractTypeLabel = (value) => {
737
- if (!value)
738
- return commonT('labels.notAvailable');
739
- try {
740
- return contractT(`options.contractTypes.${value}`);
741
- }
742
- catch (_a) {
743
- return (0, format_1.formatEnumLabel)(value);
744
- }
745
- };
746
- const getSignatureStatusLabel = (value) => {
747
- if (!value)
748
- return commonT('labels.notAvailable');
749
- try {
750
- return contractT(`options.signatureStatuses.${value}`);
751
- }
752
- catch (_a) {
753
- return (0, format_1.formatEnumLabel)(value);
754
- }
755
- };
756
- const isEditSheetOpen = (0, react_1.useMemo)(() => !isLimitedView &&
757
- shouldOpenEditSheet(searchParams.get('edit'), projectId), [isLimitedView, projectId, searchParams]);
758
- const updateSheetQuery = (open) => {
759
- const params = new URLSearchParams(searchParams.toString());
760
- if (open) {
761
- params.set('edit', '1');
762
- }
763
- else {
764
- params.delete('edit');
765
- }
766
- const query = params.toString();
767
- router.replace(query ? `${pathname}?${query}` : pathname, {
768
- scroll: false,
769
- });
770
- };
771
- const openEditSheet = () => {
772
- updateSheetQuery(true);
773
- };
774
- const closeEditSheet = () => {
775
- updateSheetQuery(false);
776
- };
777
- const getDeliveryModelLabel = (value) => {
778
- if (!value) {
779
- return commonT('labels.notAvailable');
780
- }
781
- try {
782
- return formT(`options.deliveryModels.${value}`);
783
- }
784
- catch (_a) {
785
- return (0, format_1.formatEnumLabel)(value);
786
- }
787
- };
788
- const getBillingModelLabel = (value) => {
789
- if (!value) {
790
- return commonT('labels.notAvailable');
791
- }
792
- try {
793
- return formT(`options.billingModels.${value}`);
794
- }
795
- catch (_a) {
796
- return (0, format_1.formatEnumLabel)(value);
797
- }
798
- };
799
- const getTaskPriorityLabel = (value) => {
800
- var _a;
801
- const labels = currentLocaleCode.startsWith('pt')
802
- ? { low: 'Baixa', medium: 'Média', high: 'Alta' }
803
- : { low: 'Low', medium: 'Medium', high: 'High' };
804
- return (_a = labels[value]) !== null && _a !== void 0 ? _a : (0, format_1.formatEnumLabel)(value);
805
- };
806
- const { data: project, refetch, isLoading: isProjectLoading, } = (0, next_app_provider_1.useQuery)({
807
- queryKey: ['operations-project-details', currentLocaleCode, projectId],
808
- queryFn: () => (0, api_1.fetchOperations)(request, `/operations/projects/${projectId}`),
809
- });
810
- const { data: rawTasks = [], refetch: refetchTasks, isLoading: isTasksLoading, } = (0, next_app_provider_1.useQuery)({
811
- queryKey: ['operations-project-board-tasks', projectId],
812
- queryFn: () => (0, api_1.fetchOperations)(request, `/operations/projects/${projectId}/tasks`),
813
- enabled: Boolean(project),
814
- });
815
- const { data: archivedTasksResponse, refetch: refetchArchivedTasks } = (0, next_app_provider_1.useQuery)({
816
- queryKey: ['operations-project-archived-tasks', projectId],
817
- queryFn: () => (0, api_1.fetchOperations)(request, `/operations/tasks?projectId=${projectId}&pageSize=100&sortField=createdAt&sortOrder=desc&archived=true`),
818
- enabled: Boolean(project),
819
- });
820
- const { data: projectStats, isLoading: isProjectStatsLoading } = (0, next_app_provider_1.useQuery)({
821
- queryKey: ['operations-project-stats', projectId],
822
- queryFn: () => (0, api_1.fetchOperations)(request, `/operations/projects/${projectId}/stats`),
823
- enabled: Boolean(project) && !isLimitedView,
824
- });
825
- const [boardState, setBoardState] = (0, react_1.useState)(null);
826
- const [selectedTask, setSelectedTask] = (0, react_1.useState)(null);
827
- const [taskFormOpen, setTaskFormOpen] = (0, react_1.useState)(false);
828
- const [editingTaskId, setEditingTaskId] = (0, react_1.useState)(null);
829
- const [taskFormData, setTaskFormData] = (0, react_1.useState)(EMPTY_TASK_FORM);
830
- const [taskFormLoading, setTaskFormLoading] = (0, react_1.useState)(false);
831
- const [deletePromptTask, setDeletePromptTask] = (0, react_1.useState)(null);
832
- const [inlineCreateColumn, setInlineCreateColumn] = (0, react_1.useState)(null);
833
- const [inlineCreateName, setInlineCreateName] = (0, react_1.useState)('');
834
- const [inlineCreateLoading, setInlineCreateLoading] = (0, react_1.useState)(false);
835
- const [boardSearch, setBoardSearch] = (0, react_1.useState)('');
836
- const [boardPriorityFilter, setBoardPriorityFilter] = (0, react_1.useState)('all');
837
- const [boardGroupMode, setBoardGroupMode] = (0, react_1.useState)('status');
838
- const [timelineTypeFilter, setTimelineTypeFilter] = (0, react_1.useState)('all');
839
- const [timelineVisibleCount, setTimelineVisibleCount] = (0, react_1.useState)(8);
840
- const [archivingTaskId, setArchivingTaskId] = (0, react_1.useState)(null);
841
- const [restoringTaskId, setRestoringTaskId] = (0, react_1.useState)(null);
842
- const [deletingTaskId, setDeletingTaskId] = (0, react_1.useState)(null);
843
- const [activeDragTask, setActiveDragTask] = (0, react_1.useState)(null);
844
- const apiTasks = (0, react_1.useMemo)(() => rawTasks.map(apiTaskToBoardTask), [rawTasks]);
845
- const archivedTasks = (0, react_1.useMemo)(() => {
846
- var _a;
847
- return ((_a = archivedTasksResponse === null || archivedTasksResponse === void 0 ? void 0 : archivedTasksResponse.data) !== null && _a !== void 0 ? _a : []).filter((task) => Boolean(task.deletedAt));
848
- }, [archivedTasksResponse]);
849
- const taskColumns = (0, react_1.useMemo)(() => {
850
- if (project && (boardState === null || boardState === void 0 ? void 0 : boardState.projectId) === project.id) {
851
- return boardState.columns;
852
- }
853
- return splitTasksByColumn(apiTasks);
854
- }, [project, boardState, apiTasks]);
855
- const filteredTaskColumns = (0, react_1.useMemo)(() => {
856
- const normalizedSearch = boardSearch.trim().toLocaleLowerCase();
857
- const filterTask = (task) => {
858
- const matchesSearch = !normalizedSearch ||
859
- [
860
- task.name,
861
- task.description,
862
- task.assigneeName,
863
- task.tags,
864
- task.priority,
865
- ]
866
- .filter(Boolean)
867
- .some((value) => String(value).toLocaleLowerCase().includes(normalizedSearch));
868
- const matchesPriority = boardPriorityFilter === 'all' || task.priority === boardPriorityFilter;
869
- return matchesSearch && matchesPriority;
870
- };
871
- return {
872
- todo: taskColumns.todo.filter(filterTask),
873
- doing: taskColumns.doing.filter(filterTask),
874
- review: taskColumns.review.filter(filterTask),
875
- done: taskColumns.done.filter(filterTask),
876
- };
877
- }, [boardPriorityFilter, boardSearch, taskColumns]);
878
- const taskAssigneeOptions = (0, react_1.useMemo)(() => {
879
- var _a;
880
- const seen = new Set();
881
- return ((_a = project === null || project === void 0 ? void 0 : project.assignments.filter((assignment) => {
882
- if (!assignment.collaboratorId ||
883
- seen.has(assignment.collaboratorId)) {
884
- return false;
885
- }
886
- seen.add(assignment.collaboratorId);
887
- return true;
888
- }).map((assignment) => ({
889
- id: String(assignment.collaboratorId),
890
- label: assignment.collaboratorName,
891
- }))) !== null && _a !== void 0 ? _a : []);
892
- }, [project]);
893
- const openCreateTaskForm = (0, react_1.useCallback)((defaultStatus = 'todo') => {
894
- setEditingTaskId(null);
895
- setTaskFormData(Object.assign(Object.assign({}, EMPTY_TASK_FORM), { status: defaultStatus }));
896
- setTaskFormOpen(true);
897
- }, []);
898
- const openEditTaskForm = (0, react_1.useCallback)((task) => {
899
- var _a, _b;
900
- setEditingTaskId(task.id);
901
- setTaskFormData({
902
- name: task.name,
903
- description: (_a = task.description) !== null && _a !== void 0 ? _a : '',
904
- priority: task.priority,
905
- status: task.status,
906
- assigneeCollaboratorId: task.assigneeCollaboratorId
907
- ? String(task.assigneeCollaboratorId)
908
- : 'none',
909
- dueDate: normalizeDateInputValue(task.dueDate),
910
- estimateHours: task.estimateHours != null ? String(task.estimateHours) : '',
911
- tags: (_b = task.tags) !== null && _b !== void 0 ? _b : '',
912
- });
913
- setSelectedTask(null);
914
- setTaskFormOpen(true);
915
- }, []);
916
- const handleTaskFormSubmit = (0, react_1.useCallback)(async () => {
917
- if (!taskFormData.name.trim())
918
- return;
919
- setTaskFormLoading(true);
920
- try {
921
- const payload = {
922
- name: taskFormData.name.trim(),
923
- description: taskFormData.description || null,
924
- priority: taskFormData.priority,
925
- status: taskFormData.status,
926
- assigneeCollaboratorId: taskFormData.assigneeCollaboratorId !== 'none'
927
- ? Number(taskFormData.assigneeCollaboratorId)
928
- : null,
929
- dueDate: taskFormData.dueDate || null,
930
- estimateHours: taskFormData.estimateHours
931
- ? Number(taskFormData.estimateHours)
932
- : null,
933
- tags: taskFormData.tags || null,
934
- };
935
- if (editingTaskId) {
936
- await (0, api_1.mutateOperations)(request, `/operations/tasks/${editingTaskId}`, 'PATCH', payload);
937
- }
938
- else {
939
- await (0, api_1.mutateOperations)(request, '/operations/tasks', 'POST', Object.assign({ projectId }, payload));
940
- }
941
- setBoardState(null);
942
- await refetchTasks();
943
- await refetchArchivedTasks();
944
- setTaskFormOpen(false);
945
- setEditingTaskId(null);
946
- setTaskFormData(EMPTY_TASK_FORM);
947
- }
948
- finally {
949
- setTaskFormLoading(false);
950
- }
951
- }, [
952
- taskFormData,
953
- editingTaskId,
954
- projectId,
955
- request,
956
- refetchTasks,
957
- refetchArchivedTasks,
958
- ]);
959
- const handleArchiveTask = (0, react_1.useCallback)(async (taskId) => {
960
- setArchivingTaskId(taskId);
961
- try {
962
- await (0, api_1.mutateOperations)(request, `/operations/tasks/${taskId}`, 'PATCH', {
963
- archived: true,
964
- });
965
- setBoardState(null);
966
- setSelectedTask(null);
967
- await refetchTasks();
968
- await refetchArchivedTasks();
969
- }
970
- catch (_a) {
971
- // ignore
972
- }
973
- finally {
974
- setArchivingTaskId(null);
975
- }
976
- }, [request, refetchTasks, refetchArchivedTasks]);
977
- const handleRestoreTask = (0, react_1.useCallback)(async (taskId) => {
978
- setRestoringTaskId(taskId);
979
- try {
980
- await (0, api_1.mutateOperations)(request, `/operations/tasks/${taskId}`, 'PATCH', {
981
- archived: false,
982
- });
983
- setSelectedTask(null);
984
- await refetchTasks();
985
- await refetchArchivedTasks();
986
- }
987
- catch (_a) {
988
- // ignore
989
- }
990
- finally {
991
- setRestoringTaskId(null);
992
- }
993
- }, [request, refetchTasks, refetchArchivedTasks]);
994
- const handleInlineCreateTask = (0, react_1.useCallback)(async (column, name) => {
995
- const trimmed = name.trim();
996
- if (!trimmed) {
997
- setInlineCreateColumn(null);
998
- setInlineCreateName('');
999
- return;
1000
- }
1001
- setInlineCreateLoading(true);
1002
- try {
1003
- await (0, api_1.mutateOperations)(request, '/operations/tasks', 'POST', {
1004
- projectId,
1005
- name: trimmed,
1006
- status: column,
1007
- priority: 'medium',
1008
- });
1009
- setBoardState(null);
1010
- setInlineCreateColumn(null);
1011
- setInlineCreateName('');
1012
- await refetchTasks();
1013
- }
1014
- finally {
1015
- setInlineCreateLoading(false);
1016
- }
1017
- }, [projectId, request, refetchTasks]);
1018
- const handleDeleteTask = (0, react_1.useCallback)(async (taskId) => {
1019
- setDeletingTaskId(taskId);
1020
- try {
1021
- await (0, api_1.mutateOperations)(request, `/operations/tasks/${taskId}?permanent=true`, 'DELETE');
1022
- setBoardState(null);
1023
- setSelectedTask(null);
1024
- setDeletePromptTask(null);
1025
- await refetchTasks();
1026
- await refetchArchivedTasks();
1027
- }
1028
- catch (_a) {
1029
- // ignore
1030
- }
1031
- finally {
1032
- setDeletingTaskId(null);
1033
- }
1034
- }, [request, refetchTasks, refetchArchivedTasks]);
1035
- const allocationChartData = (0, react_1.useMemo)(() => {
1036
- var _a;
1037
- if ((_a = projectStats === null || projectStats === void 0 ? void 0 : projectStats.allocationByCollaborator) === null || _a === void 0 ? void 0 : _a.length) {
1038
- return projectStats.allocationByCollaborator;
1039
- }
1040
- if (!project) {
1041
- return [];
1042
- }
1043
- return project.assignments.slice(0, 6).map((assignment) => ({
1044
- name: getInitials(assignment.collaboratorName),
1045
- allocation: typeof assignment.allocationPercent === 'number'
1046
- ? Math.round(assignment.allocationPercent)
1047
- : 0,
1048
- }));
1049
- }, [project, projectStats]);
1050
- const sensors = (0, core_1.useSensors)((0, core_1.useSensor)(core_1.PointerSensor, {
1051
- activationConstraint: { distance: 6 },
1052
- }));
1053
- const velocityChartData = (0, react_1.useMemo)(() => {
1054
- var _a;
1055
- if ((_a = projectStats === null || projectStats === void 0 ? void 0 : projectStats.weeklyVelocity) === null || _a === void 0 ? void 0 : _a.length) {
1056
- return projectStats.weeklyVelocity.map((row) => ({
1057
- week: row.weekLabel,
1058
- loggedHours: row.loggedHours,
1059
- completedTasks: 0,
1060
- }));
1061
- }
1062
- return [];
1063
- }, [projectStats]);
1064
- const findColumnByTask = (0, react_1.useCallback)((taskId) => {
1065
- var _a;
1066
- const match = KANBAN_COLUMNS.find((column) => taskColumns[column.id].some((task) => task.id === taskId));
1067
- return (_a = match === null || match === void 0 ? void 0 : match.id) !== null && _a !== void 0 ? _a : null;
1068
- }, [taskColumns]);
1069
- const moveTaskToColumn = (0, react_1.useCallback)((taskId, targetColumn) => {
1070
- const originColumn = findColumnByTask(taskId);
1071
- if (!originColumn || originColumn === targetColumn) {
1072
- return;
1073
- }
1074
- const sourceTask = taskColumns[originColumn].find((task) => task.id === taskId);
1075
- if (!sourceTask || !project) {
1076
- return;
1077
- }
1078
- // Optimistic update
1079
- setBoardState({
1080
- projectId: project.id,
1081
- columns: Object.assign(Object.assign({}, taskColumns), { [originColumn]: taskColumns[originColumn].filter((task) => task.id !== taskId), [targetColumn]: [
1082
- Object.assign(Object.assign({}, sourceTask), { status: targetColumn }),
1083
- ...taskColumns[targetColumn],
1084
- ] }),
1085
- });
1086
- // Persist to API
1087
- (0, api_1.mutateOperations)(request, `/operations/tasks/${taskId}`, 'PATCH', {
1088
- status: targetColumn,
1089
- }).catch(() => {
1090
- // Rollback optimistic update on error
1091
- setBoardState(null);
1092
- void refetchTasks();
1093
- });
1094
- }, [findColumnByTask, taskColumns, project, request, refetchTasks]);
1095
- const onBoardDragStart = (event) => {
1096
- var _a;
1097
- const taskId = parseTaskId(event.active.id);
1098
- if (!taskId)
1099
- return;
1100
- const col = findColumnByTask(taskId);
1101
- if (!col)
1102
- return;
1103
- const task = (_a = taskColumns[col].find((t) => t.id === taskId)) !== null && _a !== void 0 ? _a : null;
1104
- setActiveDragTask(task);
1105
- };
1106
- const onBoardDragEnd = (event) => {
1107
- var _a;
1108
- setActiveDragTask(null);
1109
- const taskId = parseTaskId(event.active.id);
1110
- const targetColumn = parseColumnId((_a = event.over) === null || _a === void 0 ? void 0 : _a.id);
1111
- if (!taskId || !targetColumn) {
1112
- return;
1113
- }
1114
- moveTaskToColumn(taskId, targetColumn);
1115
- };
1116
- const timelineEvents = (0, react_1.useMemo)(() => {
1117
- if (!project) {
1118
- return [];
1119
- }
1120
- const events = [];
1121
- const projectStart = getValidTimestamp(project.startDate);
1122
- const projectEnd = getValidTimestamp(project.endDate);
1123
- if (projectStart) {
1124
- events.push({
1125
- id: `project-start-${project.id}`,
1126
- type: 'status',
1127
- title: t('timeline.projectStarted'),
1128
- description: t('timeline.projectStartedDescription', {
1129
- project: project.name,
1130
- }),
1131
- timestamp: projectStart,
1132
- actorName: project.managerName,
1133
- actorAvatarId: project.managerAvatarId,
1134
- icon: lucide_react_1.Rocket,
1135
- toneClassName: 'bg-sky-500 text-white',
1136
- });
1137
- }
1138
- if (projectEnd) {
1139
- events.push({
1140
- id: `project-deadline-${project.id}`,
1141
- type: 'status',
1142
- title: t('timeline.targetDate'),
1143
- description: t('timeline.targetDateDescription'),
1144
- timestamp: projectEnd,
1145
- actorName: project.managerName,
1146
- actorAvatarId: project.managerAvatarId,
1147
- icon: lucide_react_1.CalendarClock,
1148
- toneClassName: isPastDue(project.endDate)
1149
- ? 'bg-rose-500 text-white'
1150
- : 'bg-violet-500 text-white',
1151
- });
1152
- }
1153
- apiTasks.forEach((task) => {
1154
- var _a, _b, _c, _d;
1155
- const taskCreatedAt = (_b = (_a = getValidTimestamp(task.createdAt)) !== null && _a !== void 0 ? _a : getValidTimestamp(task.dueDate)) !== null && _b !== void 0 ? _b : projectStart;
1156
- const actorName = task.assigneeName || project.managerName;
1157
- if (taskCreatedAt) {
1158
- events.push({
1159
- id: `task-created-${task.id}`,
1160
- type: 'task',
1161
- title: t('timeline.taskCreated'),
1162
- description: task.name,
1163
- timestamp: taskCreatedAt,
1164
- actorName,
1165
- actorAvatarId: task.assigneePersonAvatarId,
1166
- actorUserPhotoId: task.assigneeUserPhotoId,
1167
- icon: lucide_react_1.Plus,
1168
- toneClassName: 'bg-slate-500 text-white',
1169
- });
1170
- }
1171
- if (task.status === 'done') {
1172
- events.push({
1173
- id: `task-done-${task.id}`,
1174
- type: 'status',
1175
- title: t('timeline.taskCompleted'),
1176
- description: task.name,
1177
- timestamp: (_d = (_c = getValidTimestamp(task.dueDate)) !== null && _c !== void 0 ? _c : taskCreatedAt) !== null && _d !== void 0 ? _d : new Date().toISOString(),
1178
- actorName,
1179
- actorAvatarId: task.assigneePersonAvatarId,
1180
- actorUserPhotoId: task.assigneeUserPhotoId,
1181
- icon: lucide_react_1.CheckCircle2,
1182
- toneClassName: 'bg-emerald-500 text-white',
1183
- });
1184
- }
1185
- if (task.description) {
1186
- events.push({
1187
- id: `task-comment-${task.id}`,
1188
- type: 'comment',
1189
- title: t('timeline.commentAdded'),
1190
- description: task.name,
1191
- timestamp: taskCreatedAt !== null && taskCreatedAt !== void 0 ? taskCreatedAt : new Date().toISOString(),
1192
- actorName,
1193
- actorAvatarId: task.assigneePersonAvatarId,
1194
- actorUserPhotoId: task.assigneeUserPhotoId,
1195
- icon: lucide_react_1.MessageSquare,
1196
- toneClassName: 'bg-indigo-500 text-white',
1197
- });
1198
- }
1199
- });
1200
- if (project.timesheetSummary.totalTimesheets > 0) {
1201
- events.push({
1202
- id: `timesheets-${project.id}`,
1203
- type: 'timesheet',
1204
- title: t('timeline.timesheetLogged'),
1205
- description: t('timeline.timesheetLoggedDescription', {
1206
- count: project.timesheetSummary.totalTimesheets,
1207
- hours: (0, format_1.formatHours)(project.timesheetSummary.totalHours),
1208
- }),
1209
- timestamp: new Date().toISOString(),
1210
- actorName: project.managerName,
1211
- actorAvatarId: project.managerAvatarId,
1212
- icon: lucide_react_1.Timer,
1213
- toneClassName: 'bg-cyan-500 text-white',
1214
- });
1215
- }
1216
- if (project.timesheetSummary.pendingTimesheets > 0) {
1217
- events.push({
1218
- id: `approvals-${project.id}`,
1219
- type: 'approval',
1220
- title: t('timeline.approvalPending'),
1221
- description: t('timeline.approvalPendingDescription', {
1222
- count: project.timesheetSummary.pendingTimesheets,
1223
- }),
1224
- timestamp: new Date().toISOString(),
1225
- actorName: project.managerName,
1226
- actorAvatarId: project.managerAvatarId,
1227
- icon: lucide_react_1.GitCommitHorizontal,
1228
- toneClassName: 'bg-amber-500 text-white',
1229
- });
1230
- }
1231
- return events.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
1232
- }, [apiTasks, project, t]);
1233
- if (isProjectLoading) {
1234
- return <ProjectDetailsSkeleton />;
1235
- }
1236
- if (!project) {
1237
- return (<entity_list_1.Page>
1238
- <operations_header_1.OperationsHeader title={t('title')} description={t('description')} current={t('breadcrumb')}/>
1239
- <entity_list_1.EmptyState icon={<lucide_react_1.FolderKanban className="size-12"/>} title={commonT('states.emptyTitle')} description={t('notFound')} actionLabel={commonT('actions.refresh')} onAction={() => void refetch()}/>
1240
- </entity_list_1.Page>);
1241
- }
1242
- const totalTasks = apiTasks.length;
1243
- const completedTasks = taskColumns.done.length;
1244
- const pendingTasks = totalTasks - completedTasks;
1245
- const activeCollaborators = project.operationalIndicators.activeAssignments ||
1246
- project.assignments.filter((assignment) => assignment.status === 'active')
1247
- .length ||
1248
- project.assignments.length;
1249
- const overdueTasks = apiTasks.filter((task) => task.status !== 'done' && isPastDue(task.dueDate)).length;
1250
- const projectProgress = clampPercent(project.progressPercent);
1251
- const taskProgress = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
1252
- const displayedProgress = projectProgress || taskProgress;
1253
- const averageAllocation = clampPercent(project.operationalIndicators.averageAllocation);
1254
- const weeklyVelocity = (_e = (_c = (_b = (_a = projectStats === null || projectStats === void 0 ? void 0 : projectStats.weeklyVelocity) === null || _a === void 0 ? void 0 : _a.at(-1)) === null || _b === void 0 ? void 0 : _b.loggedHours) !== null && _c !== void 0 ? _c : (_d = projectStats === null || projectStats === void 0 ? void 0 : projectStats.quickRadar) === null || _d === void 0 ? void 0 : _d.totalWeeklyHours) !== null && _e !== void 0 ? _e : project.operationalIndicators.totalWeeklyHours;
1255
- const projectHealth = getProjectHealthScore({
1256
- progress: displayedProgress,
1257
- averageAllocation,
1258
- overdueTasks,
1259
- pendingTimesheets: project.timesheetSummary.pendingTimesheets,
1260
- });
1261
- const projectHealthLabel = projectHealth.labelKey === 'good'
1262
- ? t('health.good')
1263
- : projectHealth.labelKey === 'warning'
1264
- ? t('health.warning')
1265
- : t('health.danger');
1266
- const projectHealthTrend = projectHealth.labelKey === 'good'
1267
- ? t('kpi.trends.health.good')
1268
- : projectHealth.labelKey === 'warning'
1269
- ? t('kpi.trends.health.warning')
1270
- : t('kpi.trends.health.danger');
1271
- const teamPreview = project.assignments.slice(0, 5);
1272
- const hiddenTeamCount = Math.max(project.assignments.length - teamPreview.length, 0);
1273
- const overloadedAssignments = project.assignments.filter((assignment) => { var _a; return ((_a = assignment.allocationPercent) !== null && _a !== void 0 ? _a : 0) > 100; }).length;
1274
- const highAllocationAssignments = project.assignments.filter((assignment) => {
1275
- var _a;
1276
- const allocation = (_a = assignment.allocationPercent) !== null && _a !== void 0 ? _a : 0;
1277
- return allocation >= 85 && allocation <= 100;
1278
- }).length;
1279
- const availableAssignments = project.assignments.filter((assignment) => { var _a; return ((_a = assignment.allocationPercent) !== null && _a !== void 0 ? _a : 0) < 85; }).length;
1280
- const burnupChartData = velocityChartData.length > 0
1281
- ? velocityChartData.reduce((items, row, index) => {
1282
- var _a, _b, _c;
1283
- const previous = (_b = (_a = items[index - 1]) === null || _a === void 0 ? void 0 : _a.loggedHours) !== null && _b !== void 0 ? _b : 0;
1284
- const loggedHours = previous + Number((_c = row.loggedHours) !== null && _c !== void 0 ? _c : 0);
1285
- const planned = project.operationalIndicators.totalWeeklyHours > 0
1286
- ? project.operationalIndicators.totalWeeklyHours * (index + 1)
1287
- : loggedHours;
1288
- items.push({ week: row.week, loggedHours, planned });
1289
- return items;
1290
- }, [])
1291
- : [
1292
- { week: t('charts.start'), loggedHours: 0, planned: 0 },
1293
- {
1294
- week: t('charts.current'),
1295
- loggedHours: project.timesheetSummary.totalHours,
1296
- planned: project.operationalIndicators.totalWeeklyHours ||
1297
- project.timesheetSummary.totalHours,
1298
- },
1299
- ];
1300
- const taskDistributionData = KANBAN_COLUMNS.map((column) => ({
1301
- key: column.id,
1302
- name: column.label,
1303
- value: taskColumns[column.id].length,
1304
- fill: `var(--color-${column.id})`,
1305
- })).filter((item) => item.value > 0);
1306
- const healthChartData = [
1307
- {
1308
- name: t('charts.healthScore'),
1309
- value: projectHealth.value,
1310
- fill: projectHealth.tone === 'danger'
1311
- ? 'hsl(0 84% 60%)'
1312
- : projectHealth.tone === 'warning'
1313
- ? 'hsl(38 92% 50%)'
1314
- : 'var(--color-health)',
1315
- },
1316
- ];
1317
- const chartDashboardLoading = isProjectStatsLoading || isTasksLoading;
1318
- const filteredTimelineEvents = timelineEvents.filter((event) => timelineTypeFilter === 'all' || event.type === timelineTypeFilter);
1319
- const visibleTimelineEvents = filteredTimelineEvents.slice(0, timelineVisibleCount);
1320
- const groupedTimelineEvents = visibleTimelineEvents.reduce((groups, event) => {
1321
- const dayKey = getTimelineDayKey(event.timestamp);
1322
- const currentGroup = groups[groups.length - 1];
1323
- if ((currentGroup === null || currentGroup === void 0 ? void 0 : currentGroup.dayKey) === dayKey) {
1324
- currentGroup.events.push(event);
1325
- }
1326
- else {
1327
- groups.push({ dayKey, events: [event] });
1328
- }
1329
- return groups;
1330
- }, []);
1331
- const allocationTone = project.operationalIndicators.averageAllocation > 100
1332
- ? 'critical'
1333
- : project.operationalIndicators.averageAllocation > 85
1334
- ? 'warning'
1335
- : 'positive';
1336
- const pendingTasksTone = overdueTasks > 0 ? 'critical' : pendingTasks > 0 ? 'warning' : 'positive';
1337
- const velocityTone = weeklyVelocity > 0 ? 'positive' : 'info';
1338
- const kpiWidgets = [
1339
- {
1340
- key: 'hours',
1341
- title: t('cards.loggedHours'),
1342
- value: (0, format_1.formatHours)(project.timesheetSummary.totalHours),
1343
- subtitle: t('cards.loggedHoursDescription'),
1344
- trend: t('kpi.trends.hours', {
1345
- count: project.timesheetSummary.totalTimesheets,
1346
- }),
1347
- indicator: Math.min(project.timesheetSummary.totalHours, 100),
1348
- icon: lucide_react_1.Timer,
1349
- tone: 'info',
1350
- },
1351
- {
1352
- key: 'health',
1353
- title: t('cards.projectHealth'),
1354
- value: projectHealthLabel,
1355
- subtitle: t('kpi.subtitles.health'),
1356
- trend: projectHealthTrend,
1357
- indicator: projectHealth.value,
1358
- icon: lucide_react_1.HeartPulse,
1359
- tone: projectHealth.tone === 'danger'
1360
- ? 'critical'
1361
- : projectHealth.tone === 'warning'
1362
- ? 'warning'
1363
- : 'positive',
1364
- },
1365
- {
1366
- key: 'velocity',
1367
- title: t('cards.weeklyVelocity'),
1368
- value: (0, format_1.formatHours)(weeklyVelocity),
1369
- subtitle: t('cards.weeklyVelocityDescription'),
1370
- trend: weeklyVelocity > 0
1371
- ? t('kpi.trends.velocity.active')
1372
- : t('kpi.trends.velocity.empty'),
1373
- indicator: Math.min(weeklyVelocity, 100),
1374
- icon: lucide_react_1.TrendingUp,
1375
- tone: velocityTone,
1376
- },
1377
- {
1378
- key: 'allocation',
1379
- title: t('cards.allocation'),
1380
- value: (0, format_1.formatPercent)(project.operationalIndicators.averageAllocation),
1381
- subtitle: t('cards.allocationDescription'),
1382
- trend: allocationTone === 'critical'
1383
- ? t('kpi.trends.allocation.critical')
1384
- : allocationTone === 'warning'
1385
- ? t('kpi.trends.allocation.warning')
1386
- : t('kpi.trends.allocation.good'),
1387
- indicator: averageAllocation,
1388
- icon: lucide_react_1.Gauge,
1389
- tone: allocationTone,
1390
- },
1391
- {
1392
- key: 'pendingTasks',
1393
- title: t('cards.pendingTasks'),
1394
- value: pendingTasks,
1395
- subtitle: t('cards.pendingTasksDescription', { overdue: overdueTasks }),
1396
- trend: pendingTasksTone === 'critical'
1397
- ? t('kpi.trends.tasks.critical', { count: overdueTasks })
1398
- : pendingTasksTone === 'warning'
1399
- ? t('kpi.trends.tasks.warning')
1400
- : t('kpi.trends.tasks.good'),
1401
- indicator: totalTasks > 0 ? Math.round((pendingTasks / totalTasks) * 100) : 0,
1402
- icon: lucide_react_1.ClipboardList,
1403
- tone: pendingTasksTone,
1404
- },
1405
- {
1406
- key: 'activeCollaborators',
1407
- title: t('cards.activeCollaborators'),
1408
- value: activeCollaborators,
1409
- subtitle: t('cards.activeCollaboratorsDescription'),
1410
- trend: activeCollaborators > 0
1411
- ? t('kpi.trends.collaborators.active')
1412
- : t('kpi.trends.collaborators.empty'),
1413
- indicator: project.assignments.length > 0
1414
- ? Math.round((activeCollaborators / project.assignments.length) * 100)
1415
- : 0,
1416
- icon: lucide_react_1.Users,
1417
- tone: activeCollaborators > 0 ? 'positive' : 'warning',
1418
- },
1419
- ];
1420
- return (<entity_list_1.Page>
1421
- <framer_motion_1.motion.section initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.25 }} className="overflow-hidden rounded-3xl border bg-card shadow-sm">
1422
- <div className="relative overflow-hidden border-b bg-linear-to-br from-muted/70 via-background to-background p-5 sm:p-6">
1423
- <div className="absolute inset-x-0 top-0 h-px bg-linear-to-r from-transparent via-primary/40 to-transparent"/>
1424
- <div className="flex flex-col gap-6">
1425
- <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
1426
- <div className="min-w-0 space-y-4">
1427
- <nav aria-label="Breadcrumb" className="flex min-w-0 flex-wrap items-center gap-1.5 text-xs text-muted-foreground">
1428
- <link_1.default href="/operations/projects" className="transition hover:text-foreground">
1429
- {t('breadcrumbTrail.operations')}
1430
- </link_1.default>
1431
- <lucide_react_1.ChevronRight className="size-3.5"/>
1432
- <link_1.default href="/operations/projects" className="transition hover:text-foreground">
1433
- {t('breadcrumbTrail.projects')}
1434
- </link_1.default>
1435
- <lucide_react_1.ChevronRight className="size-3.5"/>
1436
- <span className="max-w-[12rem] truncate font-medium text-foreground sm:max-w-md">
1437
- {project.code || project.name}
1438
- </span>
1439
- </nav>
1440
-
1441
- <div className="flex min-w-0 items-start gap-4">
1442
- <div className="flex size-14 shrink-0 items-center justify-center rounded-2xl border bg-background shadow-xs">
1443
- <lucide_react_1.FolderKanban className="size-7 text-primary"/>
1444
- </div>
1445
- <div className="min-w-0 space-y-2">
1446
- <div className="flex flex-wrap items-center gap-2">
1447
- <span className="rounded-full border bg-background px-3 py-1 text-xs font-medium text-muted-foreground">
1448
- {project.code || commonT('labels.notAvailable')}
1449
- </span>
1450
- <status_badge_1.StatusBadge label={getProjectStatusLabel(project.status)} className={(0, format_1.getStatusBadgeClass)(project.status)}/>
1451
- </div>
1452
- <div className="space-y-1.5">
1453
- <h1 className="max-w-5xl text-2xl font-semibold tracking-tight text-foreground sm:text-3xl">
1454
- {project.name}
1455
- </h1>
1456
- <p className="max-w-3xl text-sm leading-6 text-muted-foreground">
1457
- {project.summary || t('executive.fallbackDescription')}
1458
- </p>
1459
- </div>
1460
- </div>
1461
- </div>
1462
- </div>
1463
-
1464
- <div className="flex flex-wrap gap-2 lg:justify-end">
1465
- {access.isDirector ? (<button_1.Button size="sm" onClick={openEditSheet} className="cursor-pointer gap-2">
1466
- <lucide_react_1.Pencil className="size-4"/>
1467
- {commonT('actions.edit')}
1468
- </button_1.Button>) : null}
1469
- {!isLimitedView ? (<button_1.Button variant="outline" size="sm" onClick={() => openCreateTaskForm()} className="cursor-pointer gap-2">
1470
- <lucide_react_1.Plus className="size-4"/>
1471
- {t('taskForm.titleNew')}
1472
- </button_1.Button>) : null}
1473
- <button_1.Button variant="outline" size="sm" asChild>
1474
- <link_1.default href="/operations/timesheets">
1475
- <lucide_react_1.Timer className="size-4"/>
1476
- {t('quickActions.timesheet')}
1477
- </link_1.default>
1478
- </button_1.Button>
1479
- <dropdown_menu_1.DropdownMenu>
1480
- <dropdown_menu_1.DropdownMenuTrigger asChild>
1481
- <button_1.Button variant="outline" size="icon" className="size-9 cursor-pointer" aria-label={t('quickActions.more')}>
1482
- <lucide_react_1.MoreHorizontal className="size-4"/>
1483
- </button_1.Button>
1484
- </dropdown_menu_1.DropdownMenuTrigger>
1485
- <dropdown_menu_1.DropdownMenuContent align="end" className="w-56">
1486
- <dropdown_menu_1.DropdownMenuItem asChild>
1487
- <link_1.default href="/operations/reports/projects">
1488
- <lucide_react_1.BarChart2 className="size-4"/>
1489
- {t('quickActions.reports')}
1490
- </link_1.default>
1491
- </dropdown_menu_1.DropdownMenuItem>
1492
- {project.contractId ? (<dropdown_menu_1.DropdownMenuItem asChild>
1493
- <link_1.default href={`/operations/contracts?edit=${project.contractId}`}>
1494
- <lucide_react_1.FileText className="size-4"/>
1495
- {commonT('actions.openContract')}
1496
- </link_1.default>
1497
- </dropdown_menu_1.DropdownMenuItem>) : null}
1498
- <dropdown_menu_1.DropdownMenuSeparator />
1499
- <dropdown_menu_1.DropdownMenuItem asChild>
1500
- <link_1.default href="/operations/projects">
1501
- <lucide_react_1.FolderKanban className="size-4"/>
1502
- {t('breadcrumbTrail.projects')}
1503
- </link_1.default>
1504
- </dropdown_menu_1.DropdownMenuItem>
1505
- </dropdown_menu_1.DropdownMenuContent>
1506
- </dropdown_menu_1.DropdownMenu>
1507
- </div>
1508
- </div>
1509
-
1510
- <div className="grid gap-3 text-sm md:grid-cols-2 xl:grid-cols-7">
1511
- <div className="rounded-xl border bg-background/70 p-3 xl:col-span-2">
1512
- <div className="flex items-center gap-2 text-muted-foreground">
1513
- <lucide_react_1.Users className="size-4"/>
1514
- {commonT('labels.client')}
1515
- </div>
1516
- <div className="mt-2 flex items-center gap-2 font-medium">
1517
- <avatar_1.Avatar className="size-7 border bg-muted">
1518
- <avatar_1.AvatarImage src={getPersonAvatarUrl(project.clientAvatarId)} alt={project.clientName || commonT('labels.client')}/>
1519
- <avatar_1.AvatarFallback className="text-[10px]">
1520
- {getInitials(project.clientName)}
1521
- </avatar_1.AvatarFallback>
1522
- </avatar_1.Avatar>
1523
- <span className="truncate">
1524
- {project.clientName || commonT('labels.notAvailable')}
1525
- </span>
1526
- </div>
1527
- </div>
1528
- <div className="rounded-xl border bg-background/70 p-3">
1529
- <div className="flex items-center gap-2 text-muted-foreground">
1530
- <lucide_react_1.Rocket className="size-4"/>
1531
- {commonT('labels.deliveryModel')}
1532
- </div>
1533
- <div className="mt-2 truncate font-medium">
1534
- {project.deliveryModel
1535
- ? getDeliveryModelLabel(project.deliveryModel)
1536
- : commonT('labels.notAvailable')}
1537
- </div>
1538
- </div>
1539
- <div className="rounded-xl border bg-background/70 p-3">
1540
- <div className="flex items-center gap-2 text-muted-foreground">
1541
- <lucide_react_1.Users className="size-4"/>
1542
- {commonT('labels.manager')}
1543
- </div>
1544
- <div className="mt-2 truncate font-medium">
1545
- {project.managerName || commonT('labels.notAssigned')}
1546
- </div>
1547
- </div>
1548
- <div className="rounded-xl border bg-background/70 p-3">
1549
- <div className="flex items-center gap-2 text-muted-foreground">
1550
- <lucide_react_1.CalendarDays className="size-4"/>
1551
- {commonT('labels.startDate')}
1552
- </div>
1553
- <div className="mt-2 font-medium">
1554
- {(0, format_1.formatDate)(project.startDate, getSettingValue, currentLocaleCode)}
1555
- </div>
1556
- </div>
1557
- <div className="rounded-xl border bg-background/70 p-3">
1558
- <div className="flex items-center gap-2 text-muted-foreground">
1559
- <lucide_react_1.CalendarClock className="size-4"/>
1560
- {commonT('labels.endDate')}
1561
- </div>
1562
- <div className="mt-2 font-medium">
1563
- {(0, format_1.formatDate)(project.endDate, getSettingValue, currentLocaleCode)}
1564
- </div>
1565
- </div>
1566
- <div className="rounded-xl border bg-background/70 p-3">
1567
- <div className="flex items-center gap-2 text-muted-foreground">
1568
- <lucide_react_1.Gauge className="size-4"/>
1569
- {commonT('labels.progress')}
1570
- </div>
1571
- <div className="mt-2 flex items-center gap-3">
1572
- <progress_1.Progress value={displayedProgress} className="h-2"/>
1573
- <span className="text-sm font-semibold tabular-nums">
1574
- {displayedProgress}%
1575
- </span>
1576
- </div>
1577
- </div>
1578
- </div>
1579
-
1580
- <div className="flex flex-col gap-4 rounded-2xl border bg-background/75 p-4 sm:flex-row sm:items-center sm:justify-between">
1581
- <div className="flex items-center gap-3">
1582
- <div>
1583
- <div className="flex items-center gap-2 text-muted-foreground">
1584
- <lucide_react_1.Users className="size-4"/>
1585
- <span className="text-xs font-medium uppercase tracking-[0.18em]">
1586
- {t('executive.team')}
1587
- </span>
1588
- </div>
1589
- <div className="mt-1 text-sm font-semibold">
1590
- {t('executive.membersCount', {
1591
- count: project.assignments.length,
1592
- })}
1593
- </div>
1594
- </div>
1595
- <div className="flex -space-x-2">
1596
- {teamPreview.map((assignment) => (<tooltip_1.Tooltip key={assignment.id}>
1597
- <tooltip_1.TooltipTrigger asChild>
1598
- <avatar_1.Avatar className="size-10 cursor-default border-2 border-background bg-muted transition-transform hover:z-10 hover:scale-110">
1599
- <avatar_1.AvatarImage src={getUserPhotoUrl(assignment.userPhotoId) ||
1600
- getPersonAvatarUrl(assignment.personAvatarId)} alt={assignment.collaboratorName}/>
1601
- <avatar_1.AvatarFallback className="text-xs">
1602
- {getInitials(assignment.collaboratorName)}
1603
- </avatar_1.AvatarFallback>
1604
- </avatar_1.Avatar>
1605
- </tooltip_1.TooltipTrigger>
1606
- <tooltip_1.TooltipContent side="bottom" className="text-xs">
1607
- <p className="font-medium">
1608
- {assignment.collaboratorName}
1609
- </p>
1610
- {assignment.roleLabel ? (<p className="text-muted-foreground">
1611
- {assignment.roleLabel}
1612
- </p>) : null}
1613
- </tooltip_1.TooltipContent>
1614
- </tooltip_1.Tooltip>))}
1615
- {hiddenTeamCount > 0 ? (<div className="flex size-10 items-center justify-center rounded-full border-2 border-background bg-muted text-xs font-semibold text-muted-foreground">
1616
- +{hiddenTeamCount}
1617
- </div>) : null}
1618
- </div>
1619
- </div>
1620
-
1621
- <div className="grid grid-cols-3 gap-3 text-sm sm:min-w-80">
1622
- <div className="rounded-xl border bg-muted/20 p-3">
1623
- <div className="text-muted-foreground">
1624
- {commonT('labels.status')}
1625
- </div>
1626
- <div className="mt-1">
1627
- <status_badge_1.StatusBadge label={getProjectStatusLabel(project.status)} className={(0, format_1.getStatusBadgeClass)(project.status)}/>
1628
- </div>
1629
- </div>
1630
- <div className="rounded-xl border bg-muted/20 p-3">
1631
- <div className="text-muted-foreground">
1632
- {t('cards.projectHealth')}
1633
- </div>
1634
- <div className="mt-1 font-semibold">{projectHealthLabel}</div>
1635
- </div>
1636
- <div className="rounded-xl border bg-muted/20 p-3">
1637
- <div className="text-muted-foreground">
1638
- {t('executive.completedTasks')}
1639
- </div>
1640
- <div className="mt-1 font-semibold">
1641
- {completedTasks}/{totalTasks}
1642
- </div>
1643
- </div>
1644
- </div>
1645
- </div>
1646
- </div>
1647
- </div>
1648
- </framer_motion_1.motion.section>
1649
-
1650
- {!isLimitedView ? (<>
1651
- <div className="rounded-3xl border bg-linear-to-b from-muted/50 to-background p-3 shadow-sm sm:p-4">
1652
- <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-6">
1653
- {kpiWidgets.map((item, index) => (<ProjectKpiWidget key={item.key} item={item} index={index} indicatorLabel={t('kpi.indicator')}/>))}
1654
- </div>
1655
- </div>
1656
-
1657
- <div className="grid gap-4 xl:grid-cols-12">
1658
- <section_card_1.SectionCard title={t('sections.overview')} className="rounded-xl border bg-card p-4 shadow-sm xl:col-span-12">
1659
- <dl className="grid gap-3 text-sm sm:grid-cols-2 xl:grid-cols-3">
1660
- <div>
1661
- <dt className="text-muted-foreground">
1662
- {commonT('labels.project')}
1663
- </dt>
1664
- <dd className="font-medium">{project.name}</dd>
1665
- </div>
1666
- <div>
1667
- <dt className="text-muted-foreground">
1668
- {commonT('labels.code')}
1669
- </dt>
1670
- <dd className="font-medium">
1671
- {project.code || commonT('labels.notAvailable')}
1672
- </dd>
1673
- </div>
1674
- <div>
1675
- <dt className="text-muted-foreground">
1676
- {commonT('labels.client')}
1677
- </dt>
1678
- <dd className="font-medium">
1679
- <div className="flex items-center gap-2">
1680
- <avatar_1.Avatar className="h-8 w-8 border border-border/60 bg-muted">
1681
- <avatar_1.AvatarImage src={getPersonAvatarUrl(project.clientAvatarId)} alt={project.clientName || commonT('labels.client')}/>
1682
- <avatar_1.AvatarFallback className="bg-muted text-xs font-semibold text-foreground">
1683
- {getInitials(project.clientName || commonT('labels.client'))}
1684
- </avatar_1.AvatarFallback>
1685
- </avatar_1.Avatar>
1686
- <span>
1687
- {project.clientName || commonT('labels.notAvailable')}
1688
- </span>
1689
- </div>
1690
- </dd>
1691
- </div>
1692
- <div>
1693
- <dt className="text-muted-foreground">
1694
- {commonT('labels.manager')}
1695
- </dt>
1696
- <dd className="font-medium">
1697
- {project.managerName || commonT('labels.notAssigned')}
1698
- </dd>
1699
- </div>
1700
- <div>
1701
- <dt className="text-muted-foreground">
1702
- {commonT('labels.status')}
1703
- </dt>
1704
- <dd className="font-medium">
1705
- <status_badge_1.StatusBadge label={getProjectStatusLabel(project.status)} className={(0, format_1.getStatusBadgeClass)(project.status)}/>
1706
- </dd>
1707
- </div>
1708
- <div>
1709
- <dt className="text-muted-foreground">
1710
- {commonT('labels.deliveryModel')}
1711
- </dt>
1712
- <dd className="font-medium">
1713
- {project.deliveryModel
1714
- ? getDeliveryModelLabel(project.deliveryModel)
1715
- : commonT('labels.notAvailable')}
1716
- </dd>
1717
- </div>
1718
- <div>
1719
- <dt className="text-muted-foreground">
1720
- {commonT('labels.startDate')}
1721
- </dt>
1722
- <dd className="font-medium">
1723
- {(0, format_1.formatDate)(project.startDate, getSettingValue, currentLocaleCode)}
1724
- </dd>
1725
- </div>
1726
- <div>
1727
- <dt className="text-muted-foreground">
1728
- {commonT('labels.endDate')}
1729
- </dt>
1730
- <dd className="font-medium">
1731
- {(0, format_1.formatDate)(project.endDate, getSettingValue, currentLocaleCode)}
1732
- </dd>
1733
- </div>
1734
- <div>
1735
- <dt className="text-muted-foreground">
1736
- {commonT('labels.budget')}
1737
- </dt>
1738
- <dd className="font-medium">
1739
- {project.budgetAmount
1740
- ? (0, format_1.formatCurrency)(project.budgetAmount, getSettingValue, currentLocaleCode)
1741
- : commonT('labels.notAvailable')}
1742
- </dd>
1743
- </div>
1744
- <div>
1745
- <dt className="text-muted-foreground">
1746
- {commonT('labels.progress')}
1747
- </dt>
1748
- <dd className="font-medium">
1749
- {(0, format_1.formatPercent)(project.progressPercent)}
1750
- </dd>
1751
- </div>
1752
- <div>
1753
- <dt className="text-muted-foreground">
1754
- {commonT('labels.timeline')}
1755
- </dt>
1756
- <dd className="font-medium">
1757
- {(0, format_1.formatDateRange)(project.startDate, project.endDate, getSettingValue, currentLocaleCode)}
1758
- </dd>
1759
- </div>
1760
- <div>
1761
- <dt className="text-muted-foreground">
1762
- {commonT('labels.contractStatus')}
1763
- </dt>
1764
- <dd className="font-medium">
1765
- {project.contractStatus ? (<status_badge_1.StatusBadge label={getContractStatusLabel(project.contractStatus)} className={(0, format_1.getStatusBadgeClass)(project.contractStatus)}/>) : (commonT('labels.notAssigned'))}
1766
- </dd>
1767
- </div>
1768
- </dl>
1769
- {project.summary ? (<div className="mt-4 rounded-lg border border-border/70 bg-muted/30 p-3 text-sm text-muted-foreground">
1770
- {project.summary}
1771
- </div>) : null}
1772
-
1773
- {/* Contrato vinculado */}
1774
- <div className="mt-6 border-t pt-6">
1775
- <div className="mb-4 flex items-center gap-2 text-sm font-semibold">
1776
- <lucide_react_1.FileText className="size-4 text-muted-foreground"/>
1777
- {t('sections.contract')}
1778
- </div>
1779
- {project.relatedContract ? (<div className="space-y-4">
1780
- <div className="flex flex-col gap-3 rounded-xl border bg-muted/20 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
1781
- <div>
1782
- <div className="font-medium">
1783
- {project.relatedContract.name}
1784
- </div>
1785
- <div className="text-sm text-muted-foreground">
1786
- {[
1787
- project.relatedContract.code,
1788
- project.relatedContract.clientName,
1789
- ]
1790
- .filter(Boolean)
1791
- .join(' • ') || commonT('labels.notAvailable')}
1792
- </div>
1793
- </div>
1794
- <div className="flex items-center gap-3">
1795
- <status_badge_1.StatusBadge label={getContractStatusLabel(project.relatedContract.status)} className={(0, format_1.getStatusBadgeClass)(project.relatedContract.status)}/>
1796
- <button_1.Button variant="outline" size="sm" asChild className="shrink-0">
1797
- <link_1.default href={`/operations/contracts?edit=${project.relatedContract.id}`}>
1798
- <lucide_react_1.FileText className="size-4"/>
1799
- {commonT('actions.openContract')}
1800
- </link_1.default>
1801
- </button_1.Button>
1802
- </div>
1803
- </div>
1804
- <dl className="grid gap-3 text-sm sm:grid-cols-2 xl:grid-cols-3">
1805
- <div>
1806
- <dt className="text-muted-foreground">
1807
- {commonT('labels.contractCategory')}
1808
- </dt>
1809
- <dd className="font-medium">
1810
- {project.relatedContract.contractCategory
1811
- ? getContractCategoryLabel(project.relatedContract.contractCategory)
1812
- : commonT('labels.notAvailable')}
1813
- </dd>
1814
- </div>
1815
- <div>
1816
- <dt className="text-muted-foreground">
1817
- {commonT('labels.contractType')}
1818
- </dt>
1819
- <dd className="font-medium">
1820
- {project.relatedContract.contractType
1821
- ? getContractTypeLabel(project.relatedContract.contractType)
1822
- : commonT('labels.notAvailable')}
1823
- </dd>
1824
- </div>
1825
- <div>
1826
- <dt className="text-muted-foreground">
1827
- {commonT('labels.billingModel')}
1828
- </dt>
1829
- <dd className="font-medium">
1830
- {getBillingModelLabel(project.relatedContract.billingModel)}
1831
- </dd>
1832
- </div>
1833
- <div>
1834
- <dt className="text-muted-foreground">
1835
- {commonT('labels.timeline')}
1836
- </dt>
1837
- <dd className="font-medium">
1838
- {(0, format_1.formatDateRange)(project.relatedContract.startDate, project.relatedContract.endDate, getSettingValue, currentLocaleCode)}
1839
- </dd>
1840
- </div>
1841
- <div>
1842
- <dt className="text-muted-foreground">
1843
- {commonT('labels.signatureStatus')}
1844
- </dt>
1845
- <dd className="font-medium">
1846
- {project.relatedContract.signatureStatus
1847
- ? getSignatureStatusLabel(project.relatedContract.signatureStatus)
1848
- : commonT('labels.notAvailable')}
1849
- </dd>
1850
- </div>
1851
- <div>
1852
- <dt className="text-muted-foreground">
1853
- {commonT('labels.budget')}
1854
- </dt>
1855
- <dd className="font-medium">
1856
- {project.relatedContract.budgetAmount
1857
- ? (0, format_1.formatCurrency)(project.relatedContract.budgetAmount, getSettingValue, currentLocaleCode)
1858
- : commonT('labels.notAvailable')}
1859
- </dd>
1860
- </div>
1861
- </dl>
1862
- </div>) : (<p className="text-sm text-muted-foreground">
1863
- {t('noContract')}
1864
- </p>)}
1865
- </div>
1866
- </section_card_1.SectionCard>
1867
- </div>
1868
-
1869
- <section_card_1.SectionCard title={t('sections.deliveryHealth')} description={t('sections.deliveryHealthDescription')} className="rounded-3xl border bg-card p-4 shadow-sm">
1870
- <div className="grid gap-4 xl:grid-cols-12">
1871
- <ProjectChartCard title={t('charts.burnup')} description={t('charts.burnupDescription')} icon={lucide_react_1.LineChart} metric={(0, format_1.formatPercent)(displayedProgress)} className="xl:col-span-8" isLoading={chartDashboardLoading}>
1872
- {burnupChartData.length > 1 ? (<chart_1.ChartContainer className="h-80 w-full" config={boardChartConfig}>
1873
- <recharts_1.AreaChart data={burnupChartData}>
1874
- <defs>
1875
- <linearGradient id="burnupLogged" x1="0" y1="0" x2="0" y2="1">
1876
- <stop offset="5%" stopColor="var(--color-loggedHours)" stopOpacity={0.26}/>
1877
- <stop offset="95%" stopColor="var(--color-loggedHours)" stopOpacity={0.02}/>
1878
- </linearGradient>
1879
- </defs>
1880
- <recharts_1.CartesianGrid vertical={false} strokeDasharray="3 3"/>
1881
- <recharts_1.XAxis dataKey="week" tickLine={false} axisLine={false}/>
1882
- <recharts_1.YAxis tickLine={false} axisLine={false} width={36}/>
1883
- <chart_1.ChartTooltip content={<chart_1.ChartTooltipContent />}/>
1884
- <recharts_1.Area type="monotone" dataKey="planned" stroke="var(--color-planned)" strokeDasharray="4 4" strokeWidth={2} fill="transparent"/>
1885
- <recharts_1.Area type="monotone" dataKey="loggedHours" stroke="var(--color-loggedHours)" strokeWidth={2.5} fill="url(#burnupLogged)"/>
1886
- </recharts_1.AreaChart>
1887
- </chart_1.ChartContainer>) : (<ChartEmptyState icon={lucide_react_1.LineChart} title={t('charts.emptyTitle')} description={t('charts.emptyBurnup')}/>)}
1888
- </ProjectChartCard>
1889
-
1890
- <ProjectChartCard title={t('charts.weeklyVelocity')} description={t('charts.weeklyVelocityDescription')} icon={lucide_react_1.Rocket} metric={(0, format_1.formatHours)(weeklyVelocity)} className="xl:col-span-4" isLoading={isProjectStatsLoading}>
1891
- {velocityChartData.length > 0 ? (<chart_1.ChartContainer className="h-80 w-full" config={boardChartConfig}>
1892
- <recharts_1.LineChart data={velocityChartData}>
1893
- <recharts_1.CartesianGrid vertical={false} strokeDasharray="3 3"/>
1894
- <recharts_1.XAxis dataKey="week" tickLine={false} axisLine={false}/>
1895
- <recharts_1.YAxis tickLine={false} axisLine={false} width={30}/>
1896
- <chart_1.ChartTooltip content={<chart_1.ChartTooltipContent />}/>
1897
- <recharts_1.Line type="monotone" dataKey="loggedHours" stroke="var(--color-loggedHours)" strokeWidth={2.5} dot={{ r: 3 }} activeDot={{ r: 5 }}/>
1898
- </recharts_1.LineChart>
1899
- </chart_1.ChartContainer>) : (<ChartEmptyState icon={lucide_react_1.Rocket} title={t('charts.emptyTitle')} description={t('charts.emptyVelocity')}/>)}
1900
- </ProjectChartCard>
1901
-
1902
- <ProjectChartCard title={t('charts.allocationByCollaborator')} description={t('charts.allocationDescription')} icon={lucide_react_1.BarChart3} metric={(0, format_1.formatPercent)(project.operationalIndicators.averageAllocation)} className="xl:col-span-5" isLoading={chartDashboardLoading}>
1903
- {allocationChartData.length > 0 ? (<chart_1.ChartContainer className="h-72 w-full" config={boardChartConfig}>
1904
- <recharts_1.BarChart data={allocationChartData}>
1905
- <recharts_1.CartesianGrid vertical={false} strokeDasharray="3 3"/>
1906
- <recharts_1.XAxis dataKey="name" tickLine={false} axisLine={false}/>
1907
- <recharts_1.YAxis tickLine={false} axisLine={false} width={32}/>
1908
- <chart_1.ChartTooltip content={<chart_1.ChartTooltipContent hideLabel/>}/>
1909
- <recharts_1.Bar dataKey="allocation" radius={[8, 8, 3, 3]} fill="var(--color-allocation)"/>
1910
- </recharts_1.BarChart>
1911
- </chart_1.ChartContainer>) : (<ChartEmptyState icon={lucide_react_1.BarChart3} title={t('charts.emptyTitle')} description={t('charts.emptyAllocation')}/>)}
1912
- </ProjectChartCard>
1913
-
1914
- <ProjectChartCard title={t('charts.taskDistribution')} description={t('charts.taskDistributionDescription')} icon={lucide_react_1.ClipboardList} metric={`${totalTasks} ${t('kanban.items')}`} className="xl:col-span-4" isLoading={isTasksLoading}>
1915
- {taskDistributionData.length > 0 ? (<div className="grid gap-4 md:grid-cols-[1fr_11rem]">
1916
- <chart_1.ChartContainer className="h-72 w-full" config={boardChartConfig}>
1917
- <recharts_1.PieChart>
1918
- <chart_1.ChartTooltip content={<chart_1.ChartTooltipContent hideLabel/>}/>
1919
- <recharts_1.Pie data={taskDistributionData} dataKey="value" nameKey="name" innerRadius={58} outerRadius={92} paddingAngle={4}>
1920
- {taskDistributionData.map((entry) => (<recharts_1.Cell key={entry.key} fill={entry.fill}/>))}
1921
- </recharts_1.Pie>
1922
- </recharts_1.PieChart>
1923
- </chart_1.ChartContainer>
1924
- <div className="flex flex-col justify-center gap-2">
1925
- {taskDistributionData.map((item) => (<div key={item.key} className="flex items-center justify-between gap-3 rounded-lg border bg-muted/10 px-3 py-2 text-xs">
1926
- <span className="flex min-w-0 items-center gap-2">
1927
- <span className="size-2.5 shrink-0 rounded-full" style={{ backgroundColor: item.fill }}/>
1928
- <span className="truncate">{item.name}</span>
1929
- </span>
1930
- <span className="font-semibold">{item.value}</span>
1931
- </div>))}
1932
- </div>
1933
- </div>) : (<ChartEmptyState icon={lucide_react_1.ClipboardList} title={t('charts.emptyTitle')} description={t('charts.emptyTasks')}/>)}
1934
- </ProjectChartCard>
1935
-
1936
- <ProjectChartCard title={t('charts.operationalHealth')} description={t('charts.operationalHealthDescription')} icon={lucide_react_1.HeartPulse} metric={projectHealthLabel} className="xl:col-span-3" isLoading={chartDashboardLoading}>
1937
- <div className="grid h-72 place-items-center">
1938
- <chart_1.ChartContainer className="h-56 w-full" config={boardChartConfig}>
1939
- <recharts_1.RadialBarChart data={healthChartData} innerRadius="72%" outerRadius="100%" startAngle={180} endAngle={0}>
1940
- <recharts_1.PolarAngleAxis type="number" domain={[0, 100]} tick={false}/>
1941
- <recharts_1.RadialBar dataKey="value" cornerRadius={12} background={{ fill: 'hsl(var(--muted))' }}/>
1942
- <chart_1.ChartTooltip content={<chart_1.ChartTooltipContent hideLabel/>}/>
1943
- </recharts_1.RadialBarChart>
1944
- </chart_1.ChartContainer>
1945
- <div className="-mt-20 text-center">
1946
- <div className="text-3xl font-semibold tabular-nums">
1947
- {projectHealth.value}%
1948
- </div>
1949
- <div className="mt-1 text-xs text-muted-foreground">
1950
- {t('charts.healthScore')}
1951
- </div>
1952
- </div>
1953
- </div>
1954
- </ProjectChartCard>
1955
- </div>
1956
- </section_card_1.SectionCard>
1957
- </>) : null}
1958
-
1959
- <section_card_1.SectionCard title={t('sections.taskBoard')} description={t('sections.taskBoardDescription')} className="rounded-3xl border bg-card p-4 shadow-sm" actions={!isLimitedView ? (<button_1.Button size="sm" variant="default" className="gap-2" onClick={() => openCreateTaskForm()}>
1960
- <lucide_react_1.Plus className="size-4"/>
1961
- {t('taskForm.titleNew')}
1962
- </button_1.Button>) : undefined}>
1963
- <div className="mb-4 flex flex-col gap-3 rounded-2xl border bg-muted/20 p-3 lg:flex-row lg:items-center lg:justify-between">
1964
- <div className="relative min-w-0 flex-1">
1965
- <lucide_react_1.Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground"/>
1966
- <input_1.Input value={boardSearch} onChange={(event) => setBoardSearch(event.target.value)} placeholder={t('kanban.searchPlaceholder')} className="h-10 bg-background pl-9"/>
1967
- </div>
1968
- <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
1969
- <div className="flex items-center gap-2 rounded-xl border bg-background px-3 py-2 text-xs text-muted-foreground">
1970
- <lucide_react_1.SlidersHorizontal className="size-4"/>
1971
- {t('kanban.filters')}
1972
- </div>
1973
- <select_1.Select value={boardPriorityFilter} onValueChange={(value) => setBoardPriorityFilter(value)}>
1974
- <select_1.SelectTrigger className="h-10 w-full bg-background sm:w-44">
1975
- <select_1.SelectValue />
1976
- </select_1.SelectTrigger>
1977
- <select_1.SelectContent>
1978
- <select_1.SelectItem value="all">{t('kanban.allPriorities')}</select_1.SelectItem>
1979
- <select_1.SelectItem value="high">
1980
- {getTaskPriorityLabel('high')}
1981
- </select_1.SelectItem>
1982
- <select_1.SelectItem value="medium">
1983
- {getTaskPriorityLabel('medium')}
1984
- </select_1.SelectItem>
1985
- <select_1.SelectItem value="low">
1986
- {getTaskPriorityLabel('low')}
1987
- </select_1.SelectItem>
1988
- </select_1.SelectContent>
1989
- </select_1.Select>
1990
- <select_1.Select value={boardGroupMode} onValueChange={setBoardGroupMode}>
1991
- <select_1.SelectTrigger className="h-10 w-full bg-background sm:w-44">
1992
- <select_1.SelectValue />
1993
- </select_1.SelectTrigger>
1994
- <select_1.SelectContent>
1995
- <select_1.SelectItem value="status">
1996
- {t('kanban.groupStatus')}
1997
- </select_1.SelectItem>
1998
- </select_1.SelectContent>
1999
- </select_1.Select>
2000
- </div>
2001
- </div>
2002
-
2003
- <core_1.DndContext sensors={sensors} collisionDetection={kanbanCollision} onDragStart={onBoardDragStart} onDragCancel={() => setActiveDragTask(null)} onDragEnd={onBoardDragEnd}>
2004
- <div className="relative">
2005
- <div className="grid auto-cols-[minmax(19rem,1fr)] grid-flow-col gap-4 overflow-x-auto pb-2 xl:grid-flow-row xl:grid-cols-4 xl:overflow-visible xl:pb-0">
2006
- {KANBAN_COLUMNS.map((column) => (<DroppableColumn key={column.id} columnId={column.id}>
2007
- {(isOver) => (<div className={[
2008
- 'flex min-h-[32rem] flex-col overflow-hidden rounded-3xl border bg-linear-to-b p-3 transition-all',
2009
- getColumnClassName(column.id),
2010
- isOver
2011
- ? 'border-primary shadow-lg ring-2 ring-primary/15'
2012
- : 'border-border',
2013
- ].join(' ')}>
2014
- <div className="mb-3 flex items-center justify-between gap-3 rounded-2xl border bg-background/85 p-3 shadow-xs">
2015
- <div className="min-w-0">
2016
- <div className="flex items-center gap-2 text-sm font-semibold">
2017
- <span className={[
2018
- 'size-2.5 rounded-full',
2019
- getColumnDotClassName(column.id),
2020
- ].join(' ')}/>
2021
- {column.label}
2022
- </div>
2023
- <div className="mt-1 text-xs text-muted-foreground">
2024
- {filteredTaskColumns[column.id].length}/
2025
- {taskColumns[column.id].length} {t('kanban.items')}
2026
- </div>
2027
- </div>
2028
- <div className="flex items-center gap-1">
2029
- <span className="rounded-full border bg-background px-2 py-0.5 text-xs font-medium text-muted-foreground">
2030
- {filteredTaskColumns[column.id].length}
2031
- </span>
2032
- {!isLimitedView ? (<button type="button" className="flex size-5 cursor-pointer items-center justify-center rounded-full text-muted-foreground transition hover:bg-muted hover:text-foreground" onClick={() => {
2033
- setInlineCreateColumn(column.id);
2034
- setInlineCreateName('');
2035
- }}>
2036
- <lucide_react_1.Plus className="size-3.5"/>
2037
- </button>) : null}
2038
- </div>
2039
- </div>
2040
-
2041
- <div className="flex flex-1 flex-col gap-2">
2042
- <framer_motion_1.AnimatePresence initial={false}>
2043
- {filteredTaskColumns[column.id].map((task) => {
2044
- const tags = getTaskTags(task);
2045
- const comments = getTaskCommentCount(task);
2046
- const attachments = getTaskAttachmentCount(task);
2047
- return (<DraggableTaskCard key={task.id} task={task} disabled={false}>
2048
- {(isDragging) => (<framer_motion_1.motion.div initial={{ opacity: 0, scale: 0.96 }} animate={{ opacity: 1, scale: 1 }} exit={{ opacity: 0, scale: 0.95, y: -4 }} transition={{ duration: 0.18 }} role="button" tabIndex={0} className={[
2049
- 'group w-full cursor-pointer rounded-2xl border bg-card p-3 text-left shadow-xs transition',
2050
- isDragging
2051
- ? 'opacity-0'
2052
- : 'hover:border-primary/40 hover:shadow-lg',
2053
- ].join(' ')} onClick={() => setSelectedTask(Object.assign(Object.assign({}, task), { projectName: project === null || project === void 0 ? void 0 : project.name, projectCode: project === null || project === void 0 ? void 0 : project.code }))} onKeyDown={(event) => {
2054
- if (event.key === 'Enter' ||
2055
- event.key === ' ') {
2056
- event.preventDefault();
2057
- setSelectedTask(Object.assign(Object.assign({}, task), { projectName: project === null || project === void 0 ? void 0 : project.name, projectCode: project === null || project === void 0 ? void 0 : project.code }));
2058
- }
2059
- }}>
2060
- <div className="mb-3 flex items-start justify-between gap-2">
2061
- <div className="min-w-0 space-y-1">
2062
- <p className="line-clamp-2 text-sm font-semibold leading-snug">
2063
- {task.name}
2064
- </p>
2065
- {task.description ? (<p className="line-clamp-2 text-xs leading-5 text-muted-foreground">
2066
- {task.description.replace(/<[^>]*>/g, '')}
2067
- </p>) : null}
2068
- </div>
2069
- <div className="flex items-start gap-2">
2070
- <span className={[
2071
- 'shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide',
2072
- getPriorityClassName(task.priority),
2073
- ].join(' ')}>
2074
- {getTaskPriorityLabel(task.priority)}
2075
- </span>
2076
- <button_1.Button type="button" variant="ghost" size="icon" className="size-7 shrink-0 rounded-full opacity-0 transition group-hover:opacity-100" onPointerDown={(event) => event.stopPropagation()} onClick={(event) => {
2077
- event.stopPropagation();
2078
- openEditTaskForm(task);
2079
- }}>
2080
- <lucide_react_1.Pencil className="size-3.5"/>
2081
- </button_1.Button>
2082
- </div>
2083
- </div>
2084
-
2085
- {tags.length > 0 ? (<div className="mb-3 flex flex-wrap gap-1">
2086
- {tags.slice(0, 4).map((tag) => (<span key={`${task.id}-${tag}`} className="rounded-full border bg-muted/60 px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
2087
- {tag}
2088
- </span>))}
2089
- {tags.length > 4 ? (<span className="rounded-full border bg-muted/60 px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
2090
- +{tags.length - 4}
2091
- </span>) : null}
2092
- </div>) : null}
2093
-
2094
- <div className="grid grid-cols-2 gap-2 text-xs">
2095
- <div className={[
2096
- 'rounded-xl border bg-muted/20 px-2 py-1.5',
2097
- isPastDue(task.dueDate) &&
2098
- task.status !== 'done'
2099
- ? 'border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-300'
2100
- : 'text-muted-foreground',
2101
- ].join(' ')}>
2102
- <span className="flex items-center gap-1">
2103
- <lucide_react_1.AlarmClock className="size-3.5"/>
2104
- {(0, format_1.formatDate)(task.dueDate, getSettingValue, currentLocaleCode)}
2105
- </span>
2106
- </div>
2107
- <div className="rounded-xl border bg-muted/20 px-2 py-1.5 text-muted-foreground">
2108
- <span className="flex items-center gap-1">
2109
- <lucide_react_1.Timer className="size-3.5"/>
2110
- {task.estimateHours != null
2111
- ? `${task.estimateHours}h`
2112
- : t('kanban.noEstimate')}
2113
- </span>
2114
- </div>
2115
- </div>
2116
-
2117
- <div className="mt-3 space-y-1.5">
2118
- <div className="flex items-center justify-between text-[11px] text-muted-foreground">
2119
- <span>{t('kanban.progress')}</span>
2120
- <span>
2121
- {getTaskProgress(task.status)}%
2122
- </span>
2123
- </div>
2124
- <progress_1.Progress value={getTaskProgress(task.status)} className="h-1.5"/>
2125
- </div>
2126
-
2127
- <div className="mt-3 flex items-center justify-between gap-3 border-t pt-3">
2128
- <div className="flex min-w-0 items-center gap-2">
2129
- <div className="flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted text-[10px] font-semibold uppercase text-muted-foreground ring-1 ring-border">
2130
- {(() => {
2131
- const photoUrl = getUserPhotoUrl(task.assigneeUserPhotoId);
2132
- const avatarUrl = task.assigneePersonAvatarId
2133
- ? getPersonAvatarUrl(task.assigneePersonAvatarId)
2134
- : null;
2135
- const imgSrc = photoUrl !== null && photoUrl !== void 0 ? photoUrl : avatarUrl;
2136
- return imgSrc ? (
2137
- // eslint-disable-next-line @next/next/no-img-element
2138
- <img src={imgSrc} alt={task.assigneeName ||
2139
- commonT('labels.notAssigned')} className="size-full object-cover"/>) : (getInitials(task.assigneeName));
2140
- })()}
2141
- </div>
2142
- <span className="truncate text-[11px] text-muted-foreground">
2143
- {task.assigneeName ||
2144
- commonT('labels.notAssigned')}
2145
- </span>
2146
- </div>
2147
- <div className="flex shrink-0 items-center gap-2 text-[11px] text-muted-foreground">
2148
- <span className="inline-flex items-center gap-1">
2149
- <lucide_react_1.MessageSquare className="size-3.5"/>
2150
- {comments}
2151
- </span>
2152
- <span className="inline-flex items-center gap-1">
2153
- <lucide_react_1.Paperclip className="size-3.5"/>
2154
- {attachments}
2155
- </span>
2156
- </div>
2157
- </div>
2158
- </framer_motion_1.motion.div>)}
2159
- </DraggableTaskCard>);
2160
- })}
2161
- </framer_motion_1.AnimatePresence>
2162
- {filteredTaskColumns[column.id].length === 0 ? (<div className="rounded-2xl border border-dashed bg-background/70 p-4 text-center text-xs text-muted-foreground">
2163
- {boardSearch || boardPriorityFilter !== 'all'
2164
- ? t('kanban.noFilteredTasks')
2165
- : t('kanban.emptyColumn')}
2166
- </div>) : null}
2167
- {!isLimitedView && inlineCreateColumn === column.id ? (<div className="space-y-1.5 rounded-2xl border bg-card p-2 shadow-sm">
2168
- <input_1.Input autoFocus placeholder={t('taskForm.namePlaceholder')} value={inlineCreateName} onChange={(e) => setInlineCreateName(e.target.value)} onKeyDown={(e) => {
2169
- if (e.key === 'Enter') {
2170
- e.preventDefault();
2171
- void handleInlineCreateTask(column.id, inlineCreateName);
2172
- }
2173
- else if (e.key === 'Escape') {
2174
- setInlineCreateColumn(null);
2175
- setInlineCreateName('');
2176
- }
2177
- }} onBlur={() => {
2178
- if (!inlineCreateName.trim()) {
2179
- setInlineCreateColumn(null);
2180
- setInlineCreateName('');
2181
- }
2182
- }} disabled={inlineCreateLoading} className="h-8 text-sm"/>
2183
- <div className="flex gap-1">
2184
- <button_1.Button type="button" size="sm" className="h-7 px-2 text-xs" disabled={!inlineCreateName.trim() ||
2185
- inlineCreateLoading} onMouseDown={(e) => e.preventDefault()} onClick={() => void handleInlineCreateTask(column.id, inlineCreateName)}>
2186
- {t('taskForm.titleNew')}
2187
- </button_1.Button>
2188
- <button_1.Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" onMouseDown={(e) => e.preventDefault()} onClick={() => {
2189
- setInlineCreateColumn(null);
2190
- setInlineCreateName('');
2191
- }}>
2192
- {commonT('actions.cancel')}
2193
- </button_1.Button>
2194
- </div>
2195
- </div>) : !isLimitedView ? (<button type="button" className="mt-auto flex w-full cursor-pointer items-center justify-center gap-1 rounded-2xl border border-dashed bg-background/70 px-3 py-2 text-xs text-muted-foreground transition hover:border-primary/40 hover:bg-primary/5 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50" onClick={() => {
2196
- setInlineCreateColumn(column.id);
2197
- setInlineCreateName('');
2198
- }}>
2199
- <lucide_react_1.Plus className="size-3"/>
2200
- {t('taskForm.titleNew')}
2201
- </button>) : null}
2202
- </div>
2203
- </div>)}
2204
- </DroppableColumn>))}
2205
- </div>
2206
- {/* Scroll fade overlay — visible only on mobile/tablet */}
2207
- <div aria-hidden className="pointer-events-none absolute inset-y-0 right-0 w-16 bg-linear-to-l from-background/80 to-transparent xl:hidden"/>
2208
- </div>
2209
- {/* DragOverlay renders the floating card following the pointer */}
2210
- <core_1.DragOverlay dropAnimation={{ duration: 160, easing: 'ease' }}>
2211
- {activeDragTask
2212
- ? (() => {
2213
- const overlayTask = activeDragTask;
2214
- const overlayTags = getTaskTags(overlayTask);
2215
- const overlayComments = getTaskCommentCount(overlayTask);
2216
- const overlayAttachments = getTaskAttachmentCount(overlayTask);
2217
- return (<div className="w-76 cursor-grabbing rounded-2xl border border-primary/60 bg-card p-3 shadow-2xl ring-2 ring-primary/20 opacity-95">
2218
- <div className="mb-3 flex items-start justify-between gap-2">
2219
- <div className="min-w-0 space-y-1">
2220
- <p className="line-clamp-2 text-sm font-semibold leading-snug">
2221
- {overlayTask.name}
2222
- </p>
2223
- {overlayTask.description ? (<p className="line-clamp-2 text-xs leading-5 text-muted-foreground">
2224
- {overlayTask.description.replace(/<[^>]*>/g, '')}
2225
- </p>) : null}
2226
- </div>
2227
- <span className={[
2228
- 'shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide',
2229
- getPriorityClassName(overlayTask.priority),
2230
- ].join(' ')}>
2231
- {getTaskPriorityLabel(overlayTask.priority)}
2232
- </span>
2233
- </div>
2234
-
2235
- {overlayTags.length > 0 ? (<div className="mb-3 flex flex-wrap gap-1">
2236
- {overlayTags.slice(0, 4).map((tag) => (<span key={tag} className="rounded-full border bg-muted/60 px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
2237
- {tag}
2238
- </span>))}
2239
- {overlayTags.length > 4 ? (<span className="rounded-full border bg-muted/60 px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
2240
- +{overlayTags.length - 4}
2241
- </span>) : null}
2242
- </div>) : null}
2243
-
2244
- <div className="grid grid-cols-2 gap-2 text-xs">
2245
- <div className={[
2246
- 'rounded-xl border bg-muted/20 px-2 py-1.5',
2247
- isPastDue(overlayTask.dueDate) &&
2248
- overlayTask.status !== 'done'
2249
- ? 'border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-300'
2250
- : 'text-muted-foreground',
2251
- ].join(' ')}>
2252
- <span className="flex items-center gap-1">
2253
- <lucide_react_1.AlarmClock className="size-3.5"/>
2254
- {(0, format_1.formatDate)(overlayTask.dueDate, getSettingValue, currentLocaleCode)}
2255
- </span>
2256
- </div>
2257
- <div className="rounded-xl border bg-muted/20 px-2 py-1.5 text-muted-foreground">
2258
- <span className="flex items-center gap-1">
2259
- <lucide_react_1.Timer className="size-3.5"/>
2260
- {overlayTask.estimateHours != null
2261
- ? `${overlayTask.estimateHours}h`
2262
- : t('kanban.noEstimate')}
2263
- </span>
2264
- </div>
2265
- </div>
2266
-
2267
- <div className="mt-3 space-y-1.5">
2268
- <div className="flex items-center justify-between text-[11px] text-muted-foreground">
2269
- <span>{t('kanban.progress')}</span>
2270
- <span>{getTaskProgress(overlayTask.status)}%</span>
2271
- </div>
2272
- <progress_1.Progress value={getTaskProgress(overlayTask.status)} className="h-1.5"/>
2273
- </div>
2274
-
2275
- <div className="mt-3 flex items-center justify-between gap-3 border-t pt-3">
2276
- <div className="flex min-w-0 items-center gap-2">
2277
- <div className="flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted text-[10px] font-semibold uppercase text-muted-foreground ring-1 ring-border">
2278
- {(() => {
2279
- const photoUrl = getUserPhotoUrl(overlayTask.assigneeUserPhotoId);
2280
- const avatarUrl = overlayTask.assigneePersonAvatarId
2281
- ? getPersonAvatarUrl(overlayTask.assigneePersonAvatarId)
2282
- : null;
2283
- const imgSrc = photoUrl !== null && photoUrl !== void 0 ? photoUrl : avatarUrl;
2284
- return imgSrc ? (
2285
- // eslint-disable-next-line @next/next/no-img-element
2286
- <img src={imgSrc} alt={overlayTask.assigneeName ||
2287
- commonT('labels.notAssigned')} className="size-full object-cover"/>) : (getInitials(overlayTask.assigneeName));
2288
- })()}
2289
- </div>
2290
- <span className="truncate text-[11px] text-muted-foreground">
2291
- {overlayTask.assigneeName ||
2292
- commonT('labels.notAssigned')}
2293
- </span>
2294
- </div>
2295
- <div className="flex shrink-0 items-center gap-2 text-[11px] text-muted-foreground">
2296
- <span className="inline-flex items-center gap-1">
2297
- <lucide_react_1.MessageSquare className="size-3.5"/>
2298
- {overlayComments}
2299
- </span>
2300
- <span className="inline-flex items-center gap-1">
2301
- <lucide_react_1.Paperclip className="size-3.5"/>
2302
- {overlayAttachments}
2303
- </span>
2304
- </div>
2305
- </div>
2306
- </div>);
2307
- })()
2308
- : null}
2309
- </core_1.DragOverlay>
2310
- </core_1.DndContext>
2311
- </section_card_1.SectionCard>
2312
-
2313
- <section_card_1.SectionCard title={t('sections.timeline')} description={t('sections.timelineDescription')} className="rounded-3xl border bg-card p-4 shadow-sm" actions={<div className="flex flex-wrap items-center gap-2">
2314
- <select_1.Select value={timelineTypeFilter} onValueChange={(value) => {
2315
- setTimelineTypeFilter(value);
2316
- setTimelineVisibleCount(8);
2317
- }}>
2318
- <select_1.SelectTrigger className="h-9 w-44 bg-background">
2319
- <select_1.SelectValue />
2320
- </select_1.SelectTrigger>
2321
- <select_1.SelectContent>
2322
- <select_1.SelectItem value="all">{t('timeline.filters.all')}</select_1.SelectItem>
2323
- <select_1.SelectItem value="task">
2324
- {t('timeline.filters.task')}
2325
- </select_1.SelectItem>
2326
- <select_1.SelectItem value="status">
2327
- {t('timeline.filters.status')}
2328
- </select_1.SelectItem>
2329
- <select_1.SelectItem value="timesheet">
2330
- {t('timeline.filters.timesheet')}
2331
- </select_1.SelectItem>
2332
- <select_1.SelectItem value="approval">
2333
- {t('timeline.filters.approval')}
2334
- </select_1.SelectItem>
2335
- <select_1.SelectItem value="comment">
2336
- {t('timeline.filters.comment')}
2337
- </select_1.SelectItem>
2338
- </select_1.SelectContent>
2339
- </select_1.Select>
2340
- </div>}>
2341
- <div className="rounded-3xl border bg-linear-to-b from-muted/30 to-background p-4">
2342
- {groupedTimelineEvents.length > 0 ? (<div className="space-y-6">
2343
- {groupedTimelineEvents.map((group) => (<div key={group.dayKey} className="space-y-3">
2344
- <div className="sticky top-0 z-10 w-fit rounded-full border bg-background px-3 py-1 text-xs font-medium text-muted-foreground shadow-xs">
2345
- {(0, format_1.formatDate)(group.dayKey, getSettingValue, currentLocaleCode)}
2346
- </div>
2347
- <div className="space-y-0">
2348
- {group.events.map((event, index) => {
2349
- const Icon = event.icon;
2350
- return (<framer_motion_1.motion.div key={event.id} initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.18 }} className="grid grid-cols-[2rem_1fr] gap-3">
2351
- <div className="flex flex-col items-center">
2352
- <div className={[
2353
- 'flex size-8 items-center justify-center rounded-full shadow-sm',
2354
- event.toneClassName,
2355
- ].join(' ')}>
2356
- <Icon className="size-4"/>
2357
- </div>
2358
- {index < group.events.length - 1 ? (<div className="w-px flex-1 bg-border"/>) : null}
2359
- </div>
2360
- <div className="pb-5">
2361
- <div className="rounded-2xl border bg-card p-4 shadow-xs transition hover:shadow-sm">
2362
- <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
2363
- <div className="min-w-0">
2364
- <div className="flex flex-wrap items-center gap-2">
2365
- <span className="text-sm font-semibold">
2366
- {event.title}
2367
- </span>
2368
- <span className="rounded-full border bg-muted/40 px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
2369
- {t(`timeline.types.${event.type}`)}
2370
- </span>
2371
- </div>
2372
- <p className="mt-1 line-clamp-2 text-sm text-muted-foreground">
2373
- {event.description}
2374
- </p>
2375
- </div>
2376
- <div className="shrink-0 text-xs text-muted-foreground">
2377
- {formatRelativeTime(event.timestamp, currentLocaleCode)}
2378
- </div>
2379
- </div>
2380
- <div className="mt-3 flex items-center gap-2 border-t pt-3">
2381
- <avatar_1.Avatar className="size-7 border bg-muted">
2382
- <avatar_1.AvatarImage src={getUserPhotoUrl(event.actorUserPhotoId) ||
2383
- getPersonAvatarUrl(event.actorAvatarId)} alt={event.actorName ||
2384
- commonT('labels.notAssigned')}/>
2385
- <avatar_1.AvatarFallback className="text-[10px]">
2386
- {getInitials(event.actorName)}
2387
- </avatar_1.AvatarFallback>
2388
- </avatar_1.Avatar>
2389
- <span className="truncate text-xs text-muted-foreground">
2390
- {event.actorName ||
2391
- commonT('labels.notAssigned')}
2392
- </span>
2393
- </div>
2394
- </div>
2395
- </div>
2396
- </framer_motion_1.motion.div>);
2397
- })}
2398
- </div>
2399
- </div>))}
2400
- {visibleTimelineEvents.length < filteredTimelineEvents.length ? (<div className="flex justify-center">
2401
- <button_1.Button type="button" variant="outline" size="sm" onClick={() => setTimelineVisibleCount((current) => current + 8)}>
2402
- {t('timeline.loadMore')}
2403
- </button_1.Button>
2404
- </div>) : null}
2405
- </div>) : (<div className="flex min-h-56 flex-col items-center justify-center rounded-2xl border border-dashed bg-background p-6 text-center">
2406
- <div className="flex size-12 items-center justify-center rounded-2xl bg-muted text-muted-foreground">
2407
- <lucide_react_1.GitCommitHorizontal className="size-6"/>
2408
- </div>
2409
- <div className="mt-3 text-sm font-medium">
2410
- {t('timeline.emptyTitle')}
2411
- </div>
2412
- <p className="mt-1 max-w-sm text-xs leading-5 text-muted-foreground">
2413
- {t('timeline.empty')}
2414
- </p>
2415
- </div>)}
2416
- </div>
2417
- </section_card_1.SectionCard>
2418
-
2419
- <section_card_1.SectionCard title={t('sections.archivedTasks')} description={t('sections.archivedTasksDescription')} className="rounded-xl border bg-card p-4 shadow-sm">
2420
- {archivedTasks.length > 0 ? (<div className="overflow-x-auto rounded-lg border bg-muted/10">
2421
- <table_1.Table>
2422
- <table_1.TableHeader>
2423
- <table_1.TableRow>
2424
- <table_1.TableHead>{commonT('labels.task')}</table_1.TableHead>
2425
- <table_1.TableHead>{commonT('labels.status')}</table_1.TableHead>
2426
- <table_1.TableHead>{t('taskForm.deadlineLabel')}</table_1.TableHead>
2427
- <table_1.TableHead className="text-right">
2428
- {commonT('labels.actions')}
2429
- </table_1.TableHead>
2430
- </table_1.TableRow>
2431
- </table_1.TableHeader>
2432
- <table_1.TableBody>
2433
- {archivedTasks.map((task) => {
2434
- var _a, _b;
2435
- return (<table_1.TableRow key={task.id} className="cursor-pointer hover:bg-muted/30" onClick={() => setSelectedTask(task)}>
2436
- <table_1.TableCell>
2437
- <div className="min-w-0">
2438
- <div className="truncate font-medium">{task.name}</div>
2439
- {task.description ? (<div className="truncate text-xs text-muted-foreground">
2440
- {task.description}
2441
- </div>) : null}
2442
- </div>
2443
- </table_1.TableCell>
2444
- <table_1.TableCell>
2445
- <status_badge_1.StatusBadge label={(_b = (_a = KANBAN_COLUMNS.find((column) => column.id === task.status)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : (0, format_1.formatEnumLabel)(task.status)} className={(0, format_1.getStatusBadgeClass)(task.status)}/>
2446
- </table_1.TableCell>
2447
- <table_1.TableCell>
2448
- {(0, format_1.formatDate)(task.dueDate, getSettingValue, currentLocaleCode)}
2449
- </table_1.TableCell>
2450
- <table_1.TableCell>
2451
- <div className="flex justify-end gap-2">
2452
- <button_1.Button variant="outline" size="sm" className="gap-2" disabled={restoringTaskId === task.id} onClick={(event) => {
2453
- event.stopPropagation();
2454
- void handleRestoreTask(task.id);
2455
- }}>
2456
- {restoringTaskId === task.id ? (<lucide_react_1.Loader2 className="size-4 animate-spin"/>) : (<lucide_react_1.ArchiveRestore className="size-4"/>)}
2457
- {commonT('actions.unarchive')}
2458
- </button_1.Button>
2459
- <button_1.Button variant="destructive" size="sm" className="gap-2" onClick={(event) => {
2460
- event.stopPropagation();
2461
- setDeletePromptTask(task);
2462
- }}>
2463
- <lucide_react_1.Trash2 className="size-4"/>
2464
- {commonT('actions.delete')}
2465
- </button_1.Button>
2466
- </div>
2467
- </table_1.TableCell>
2468
- </table_1.TableRow>);
2469
- })}
2470
- </table_1.TableBody>
2471
- </table_1.Table>
2472
- </div>) : (<ChartEmptyState icon={lucide_react_1.Archive} title={commonT('states.emptyTitle')} description={t('emptyArchivedDescription')}/>)}
2473
- </section_card_1.SectionCard>
2474
-
2475
- <div className="grid gap-4 xl:grid-cols-12">
2476
- <section_card_1.SectionCard title={t('sections.team')} description={t('sections.teamDescription')} className={[
2477
- 'rounded-2xl border bg-card p-4 shadow-sm',
2478
- isLimitedView ? 'xl:col-span-12' : 'xl:col-span-8',
2479
- ].join(' ')}>
2480
- {project.assignments.length > 0 ? (<div className="space-y-4">
2481
- <div className="grid gap-3 sm:grid-cols-3">
2482
- <div className="rounded-2xl border bg-emerald-500/10 p-3">
2483
- <div className="text-xs text-muted-foreground">
2484
- {t('teamPanel.available')}
2485
- </div>
2486
- <div className="mt-1 text-2xl font-semibold text-emerald-700 dark:text-emerald-300">
2487
- {availableAssignments}
2488
- </div>
2489
- </div>
2490
- <div className="rounded-2xl border bg-amber-500/10 p-3">
2491
- <div className="text-xs text-muted-foreground">
2492
- {t('teamPanel.highAllocation')}
2493
- </div>
2494
- <div className="mt-1 text-2xl font-semibold text-amber-700 dark:text-amber-300">
2495
- {highAllocationAssignments}
2496
- </div>
2497
- </div>
2498
- <div className="rounded-2xl border bg-rose-500/10 p-3">
2499
- <div className="text-xs text-muted-foreground">
2500
- {t('teamPanel.overload')}
2501
- </div>
2502
- <div className="mt-1 text-2xl font-semibold text-rose-700 dark:text-rose-300">
2503
- {overloadedAssignments}
2504
- </div>
2505
- </div>
2506
- </div>
2507
-
2508
- <div className="grid gap-3 md:grid-cols-2">
2509
- {project.assignments.map((assignment) => {
2510
- var _a;
2511
- const allocationValue = typeof assignment.allocationPercent === 'number'
2512
- ? Math.round(assignment.allocationPercent)
2513
- : 0;
2514
- const allocation = clampPercent(allocationValue);
2515
- const weeklyHours = (_a = assignment.weeklyHours) !== null && _a !== void 0 ? _a : 0;
2516
- const usedHours = weeklyHours > 0
2517
- ? (weeklyHours * Math.max(allocationValue, 0)) / 100
2518
- : 0;
2519
- const availablePercent = Math.max(0, 100 - allocationValue);
2520
- const availabilityHours = weeklyHours > 0 ? Math.max(0, weeklyHours - usedHours) : 0;
2521
- const tone = getAllocationTone(allocationValue);
2522
- const ToneIcon = tone.icon;
2523
- return (<framer_motion_1.motion.div key={assignment.id} whileHover={{ y: -2 }} className={[
2524
- 'overflow-hidden rounded-2xl border bg-background shadow-xs transition hover:shadow-md',
2525
- tone.border,
2526
- ].join(' ')}>
2527
- <div className="border-b bg-linear-to-br from-muted/50 to-background p-4">
2528
- <div className="flex items-start justify-between gap-3">
2529
- <div className="flex min-w-0 items-center gap-3">
2530
- <avatar_1.Avatar className="size-12 border bg-muted">
2531
- <avatar_1.AvatarImage src={getUserPhotoUrl(assignment.userPhotoId) ||
2532
- getPersonAvatarUrl(assignment.personAvatarId)} alt={assignment.collaboratorName}/>
2533
- <avatar_1.AvatarFallback className="text-xs font-semibold">
2534
- {getInitials(assignment.collaboratorName)}
2535
- </avatar_1.AvatarFallback>
2536
- </avatar_1.Avatar>
2537
- <div className="min-w-0">
2538
- <div className="truncate text-sm font-semibold">
2539
- {assignment.collaboratorName}
2540
- </div>
2541
- <div className="truncate text-xs text-muted-foreground">
2542
- {assignment.roleLabel ||
2543
- commonT('labels.notAssigned')}
2544
- </div>
2545
- </div>
2546
- </div>
2547
- <div className="flex shrink-0 flex-col items-end gap-2">
2548
- <status_badge_1.StatusBadge label={(0, format_1.formatEnumLabel)(assignment.status)} className={(0, format_1.getStatusBadgeClass)(assignment.status)}/>
2549
- <span className={[
2550
- 'inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] font-semibold',
2551
- tone.border,
2552
- tone.bg,
2553
- tone.text,
2554
- ].join(' ')}>
2555
- <ToneIcon className="size-3"/>
2556
- {t(`teamPanel.status.${tone.labelKey}`)}
2557
- </span>
2558
- </div>
2559
- </div>
2560
- </div>
2561
-
2562
- <div className="space-y-4 p-4">
2563
- <div className="space-y-2">
2564
- <div className="flex items-center justify-between text-xs">
2565
- <span className="text-muted-foreground">
2566
- {commonT('labels.allocationPercent')}
2567
- </span>
2568
- <span className={['font-semibold', tone.text].join(' ')}>
2569
- {(0, format_1.formatPercent)(assignment.allocationPercent)}
2570
- </span>
2571
- </div>
2572
- <progress_1.Progress value={allocation} className={['h-2.5', tone.progress].join(' ')}/>
2573
- {allocationValue > 100 ? (<div className="flex items-center gap-1 text-xs text-rose-700 dark:text-rose-300">
2574
- <lucide_react_1.AlertTriangle className="size-3.5"/>
2575
- {t('teamPanel.overloadWarning', {
2576
- value: allocationValue - 100,
2577
- })}
2578
- </div>) : null}
2579
- </div>
2580
-
2581
- <div className="grid grid-cols-2 gap-3 text-xs xl:grid-cols-4">
2582
- <div className="rounded-xl border bg-muted/20 p-2">
2583
- <div className="text-muted-foreground">
2584
- {commonT('labels.weeklyCapacity')}
2585
- </div>
2586
- <div className="mt-1 font-semibold">
2587
- {weeklyHours
2588
- ? (0, format_1.formatHours)(weeklyHours)
2589
- : commonT('labels.notAvailable')}
2590
- </div>
2591
- </div>
2592
- <div className="rounded-xl border bg-muted/20 p-2">
2593
- <div className="text-muted-foreground">
2594
- {t('teamPanel.usedHours')}
2595
- </div>
2596
- <div className="mt-1 font-semibold">
2597
- {weeklyHours
2598
- ? (0, format_1.formatHours)(usedHours)
2599
- : commonT('labels.notAvailable')}
2600
- </div>
2601
- </div>
2602
- <div className="rounded-xl border bg-muted/20 p-2">
2603
- <div className="text-muted-foreground">
2604
- {t('teamPanel.availability')}
2605
- </div>
2606
- <div className="mt-1 font-semibold">
2607
- {weeklyHours
2608
- ? (0, format_1.formatHours)(availabilityHours)
2609
- : `${clampPercent(availablePercent)}%`}
2610
- </div>
2611
- </div>
2612
- <div className="rounded-xl border bg-muted/20 p-2">
2613
- <div className="text-muted-foreground">
2614
- {commonT('labels.timeline')}
2615
- </div>
2616
- <div className="mt-1 truncate font-semibold">
2617
- {(0, format_1.formatDateRange)(assignment.startDate, assignment.endDate, getSettingValue, currentLocaleCode)}
2618
- </div>
2619
- </div>
2620
- </div>
2621
- </div>
2622
- </framer_motion_1.motion.div>);
2623
- })}
2624
- </div>
2625
- </div>) : (<ChartEmptyState icon={lucide_react_1.Users} title={commonT('states.emptyTitle')} description={t('noAssignments')}/>)}
2626
- </section_card_1.SectionCard>
2627
-
2628
- {!isLimitedView ? (<section_card_1.SectionCard title={t('sections.indicators')} description={t('sections.indicatorsDescription')} className="rounded-xl border bg-card p-4 shadow-sm xl:col-span-4">
2629
- <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-1">
2630
- {[
2631
- {
2632
- icon: lucide_react_1.Users,
2633
- label: t('indicators.activeAssignments'),
2634
- value: project.operationalIndicators.activeAssignments,
2635
- tone: 'text-sky-700 dark:text-sky-300',
2636
- bg: 'bg-sky-500/10',
2637
- },
2638
- {
2639
- icon: lucide_react_1.CheckCircle2,
2640
- label: t('indicators.completedAssignments'),
2641
- value: project.operationalIndicators.completedAssignments,
2642
- tone: 'text-emerald-700 dark:text-emerald-300',
2643
- bg: 'bg-emerald-500/10',
2644
- },
2645
- {
2646
- icon: lucide_react_1.Gauge,
2647
- label: t('indicators.averageAllocation'),
2648
- value: (0, format_1.formatPercent)(project.operationalIndicators.averageAllocation),
2649
- tone: averageAllocation > 100
2650
- ? 'text-rose-700 dark:text-rose-300'
2651
- : averageAllocation > 85
2652
- ? 'text-amber-700 dark:text-amber-300'
2653
- : 'text-emerald-700 dark:text-emerald-300',
2654
- bg: averageAllocation > 100
2655
- ? 'bg-rose-500/10'
2656
- : averageAllocation > 85
2657
- ? 'bg-amber-500/10'
2658
- : 'bg-emerald-500/10',
2659
- },
2660
- {
2661
- icon: lucide_react_1.Timer,
2662
- label: t('indicators.totalWeeklyHours'),
2663
- value: (0, format_1.formatHours)(project.operationalIndicators.totalWeeklyHours),
2664
- tone: 'text-violet-700 dark:text-violet-300',
2665
- bg: 'bg-violet-500/10',
2666
- },
2667
- {
2668
- icon: lucide_react_1.ClipboardList,
2669
- label: t('cards.timesheets'),
2670
- value: project.timesheetSummary.totalTimesheets,
2671
- tone: 'text-foreground',
2672
- bg: 'bg-muted/40',
2673
- },
2674
- {
2675
- icon: lucide_react_1.AlarmClock,
2676
- label: commonT('labels.pending'),
2677
- value: project.timesheetSummary.pendingTimesheets,
2678
- tone: project.timesheetSummary.pendingTimesheets > 0
2679
- ? 'text-amber-700 dark:text-amber-300'
2680
- : 'text-foreground',
2681
- bg: project.timesheetSummary.pendingTimesheets > 0
2682
- ? 'bg-amber-500/10'
2683
- : 'bg-muted/40',
2684
- },
2685
- {
2686
- icon: lucide_react_1.BarChart2,
2687
- label: t('cards.loggedHours'),
2688
- value: (0, format_1.formatHours)(project.timesheetSummary.totalHours),
2689
- tone: 'text-sky-700 dark:text-sky-300',
2690
- bg: 'bg-sky-500/10',
2691
- },
2692
- ].map(({ icon: Icon, label, value, tone, bg }) => (<div key={label} className="flex items-center gap-3 rounded-xl border bg-card p-3 transition-shadow hover:shadow-sm">
2693
- <div className={[
2694
- 'flex size-9 shrink-0 items-center justify-center rounded-xl',
2695
- bg,
2696
- ].join(' ')}>
2697
- <Icon className={['size-4', tone].join(' ')}/>
2698
- </div>
2699
- <div className="min-w-0 flex-1">
2700
- <div className="truncate text-xs text-muted-foreground">
2701
- {label}
2702
- </div>
2703
- <div className={[
2704
- 'mt-0.5 text-sm font-semibold tabular-nums',
2705
- tone,
2706
- ].join(' ')}>
2707
- {value}
2708
- </div>
2709
- </div>
2710
- </div>))}
2711
- </div>
2712
- </section_card_1.SectionCard>) : null}
2713
- </div>
2714
-
2715
- <section_card_1.SectionCard title={t('sections.costs')} description={t('sections.costsDescription')} className="rounded-2xl border bg-card p-4 shadow-sm">
2716
- <project_costs_section_1.ProjectCostsSection projectId={projectId}/>
2717
- </section_card_1.SectionCard>
2718
-
2719
- <task_detail_sheet_1.TaskDetailSheet task={selectedTask} open={selectedTask !== null} onOpenChange={(open) => {
2720
- if (!open) {
2721
- setSelectedTask(null);
2722
- }
2723
- }} statusLabel={(status) => { var _a, _b; return (_b = (_a = KANBAN_COLUMNS.find((column) => column.id === status)) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : status; }} footer={selectedTask && !isLimitedView ? (<div className="grid grid-cols-2 gap-3">
2724
- {archivedTasks.some((task) => task.id === selectedTask.id) ? (<>
2725
- <button_1.Button variant="outline" size="sm" className="h-10 gap-2" disabled={restoringTaskId === selectedTask.id} onClick={() => void handleRestoreTask(selectedTask.id)}>
2726
- {restoringTaskId === selectedTask.id ? (<lucide_react_1.Loader2 className="size-3.5 animate-spin"/>) : (<lucide_react_1.ArchiveRestore className="size-3.5"/>)}
2727
- {commonT('actions.unarchive')}
2728
- </button_1.Button>
2729
- <button_1.Button variant="destructive" size="sm" className="h-10 gap-2" onClick={() => setDeletePromptTask(selectedTask)}>
2730
- <lucide_react_1.Trash2 className="size-3.5"/>
2731
- {commonT('actions.delete')}
2732
- </button_1.Button>
2733
- </>) : (<button_1.Button variant="outline" size="sm" className="col-span-2 h-10 gap-2" disabled={archivingTaskId === selectedTask.id} onClick={() => void handleArchiveTask(selectedTask.id)}>
2734
- {archivingTaskId === selectedTask.id ? (<lucide_react_1.Loader2 className="size-3.5 animate-spin"/>) : (<lucide_react_1.Archive className="size-3.5"/>)}
2735
- {commonT('actions.archive')}
2736
- </button_1.Button>)}
2737
- </div>) : null}/>
2738
-
2739
- {!isLimitedView ? (<sheet_1.Sheet open={isEditSheetOpen} onOpenChange={(open) => {
2740
- if (!open) {
2741
- closeEditSheet();
2742
- }
2743
- }}>
2744
- <sheet_1.SheetContent className="w-full overflow-x-hidden overflow-y-auto sm:max-w-[min(92vw,64rem)]">
2745
- <sheet_1.SheetHeader>
2746
- <sheet_1.SheetTitle>{formT('editTitle')}</sheet_1.SheetTitle>
2747
- <sheet_1.SheetDescription>{formT('description')}</sheet_1.SheetDescription>
2748
- </sheet_1.SheetHeader>
2749
-
2750
- <project_form_screen_1.ProjectFormScreen projectId={projectId} onCancel={closeEditSheet} onSaved={async () => {
2751
- closeEditSheet();
2752
- await refetch();
2753
- }}/>
2754
- </sheet_1.SheetContent>
2755
- </sheet_1.Sheet>) : null}
2756
-
2757
- {!isLimitedView ? (<sheet_1.Sheet open={taskFormOpen} onOpenChange={(open) => {
2758
- if (!open) {
2759
- setTaskFormOpen(false);
2760
- setEditingTaskId(null);
2761
- setTaskFormData(EMPTY_TASK_FORM);
2762
- }
2763
- }}>
2764
- <sheet_1.SheetContent className="flex w-full flex-col overflow-hidden sm:max-w-xl">
2765
- <sheet_1.SheetHeader>
2766
- <sheet_1.SheetTitle>
2767
- {editingTaskId
2768
- ? t('taskForm.titleEdit')
2769
- : t('taskForm.titleNew')}
2770
- </sheet_1.SheetTitle>
2771
- </sheet_1.SheetHeader>
2772
-
2773
- <div className="flex-1 space-y-4 overflow-y-auto px-4 py-2">
2774
- <div className="space-y-1.5">
2775
- <label_1.Label htmlFor="task-name">{t('taskForm.nameLabel')} *</label_1.Label>
2776
- <input_1.Input id="task-name" placeholder={t('taskForm.namePlaceholder')} value={taskFormData.name} onChange={(e) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { name: e.target.value })))}/>
2777
- </div>
2778
-
2779
- <div className="space-y-1.5">
2780
- <label_1.Label htmlFor="task-description">
2781
- {t('taskForm.descriptionLabel')}
2782
- </label_1.Label>
2783
- <rich_text_editor_1.RichTextEditor value={taskFormData.description} onChange={(val) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { description: val })))}/>
2784
- </div>
2785
-
2786
- <div className="grid grid-cols-2 gap-3">
2787
- <div className="space-y-1.5">
2788
- <label_1.Label>{t('taskForm.priorityLabel')}</label_1.Label>
2789
- <select_1.Select value={taskFormData.priority} onValueChange={(v) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { priority: v })))}>
2790
- <select_1.SelectTrigger className="w-full">
2791
- <select_1.SelectValue />
2792
- </select_1.SelectTrigger>
2793
- <select_1.SelectContent>
2794
- <select_1.SelectItem value="low">
2795
- {getTaskPriorityLabel('low')}
2796
- </select_1.SelectItem>
2797
- <select_1.SelectItem value="medium">
2798
- {getTaskPriorityLabel('medium')}
2799
- </select_1.SelectItem>
2800
- <select_1.SelectItem value="high">
2801
- {getTaskPriorityLabel('high')}
2802
- </select_1.SelectItem>
2803
- </select_1.SelectContent>
2804
- </select_1.Select>
2805
- </div>
2806
-
2807
- <div className="space-y-1.5">
2808
- <label_1.Label>{t('taskForm.columnLabel')}</label_1.Label>
2809
- <select_1.Select value={taskFormData.status} onValueChange={(v) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { status: v })))}>
2810
- <select_1.SelectTrigger className="w-full">
2811
- <select_1.SelectValue />
2812
- </select_1.SelectTrigger>
2813
- <select_1.SelectContent>
2814
- {KANBAN_COLUMNS.map((col) => (<select_1.SelectItem key={col.id} value={col.id}>
2815
- {col.label}
2816
- </select_1.SelectItem>))}
2817
- </select_1.SelectContent>
2818
- </select_1.Select>
2819
- </div>
2820
- </div>
2821
-
2822
- <div className="space-y-1.5">
2823
- <label_1.Label>Responsável</label_1.Label>
2824
- <select_1.Select value={taskFormData.assigneeCollaboratorId} onValueChange={(value) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { assigneeCollaboratorId: value })))}>
2825
- <select_1.SelectTrigger className="w-full">
2826
- <select_1.SelectValue placeholder={commonT('labels.notAssigned')}/>
2827
- </select_1.SelectTrigger>
2828
- <select_1.SelectContent>
2829
- <select_1.SelectItem value="none">
2830
- {commonT('labels.notAssigned')}
2831
- </select_1.SelectItem>
2832
- {taskAssigneeOptions.map((option) => (<select_1.SelectItem key={option.id} value={option.id}>
2833
- {option.label}
2834
- </select_1.SelectItem>))}
2835
- </select_1.SelectContent>
2836
- </select_1.Select>
2837
- </div>
2838
-
2839
- <div className="grid grid-cols-2 gap-3">
2840
- <div className="space-y-1.5">
2841
- <label_1.Label htmlFor="task-due-date">
2842
- {t('taskForm.deadlineLabel')}
2843
- </label_1.Label>
2844
- <input_1.Input id="task-due-date" type="date" value={taskFormData.dueDate} onChange={(e) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { dueDate: e.target.value })))}/>
2845
- </div>
2846
-
2847
- <div className="space-y-1.5">
2848
- <label_1.Label htmlFor="task-estimate">
2849
- {t('taskForm.estimateLabel')}
2850
- </label_1.Label>
2851
- <input_1.Input id="task-estimate" type="number" min="0" step="0.5" placeholder="0" value={taskFormData.estimateHours} onChange={(e) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { estimateHours: e.target.value })))}/>
2852
- </div>
2853
- </div>
2854
-
2855
- <div className="space-y-1.5">
2856
- <label_1.Label htmlFor="task-tags">{t('taskForm.tagsLabel')}</label_1.Label>
2857
- <input_1.Input id="task-tags" placeholder={t('taskForm.tagsPlaceholder')} value={taskFormData.tags} onChange={(e) => setTaskFormData((prev) => (Object.assign(Object.assign({}, prev), { tags: e.target.value })))}/>
2858
- </div>
2859
-
2860
- {editingTaskId ? (<div className="space-y-1.5">
2861
- <label_1.Label className="flex items-center gap-1.5">
2862
- <lucide_react_1.Paperclip className="size-3.5"/>
2863
- {t('taskForm.attachmentsLabel')}
2864
- </label_1.Label>
2865
- <task_file_attachments_1.TaskFileAttachments taskId={editingTaskId}/>
2866
- </div>) : null}
2867
- </div>
2868
-
2869
- <div className="mt-4 flex flex-wrap items-center justify-between gap-2 border-t px-4 pb-4 pt-4">
2870
- <div className="flex gap-2">
2871
- {editingTaskId ? (<button_1.Button type="button" variant="outline" disabled={taskFormLoading || archivingTaskId === editingTaskId} onClick={() => {
2872
- if (!editingTaskId)
2873
- return;
2874
- const id = editingTaskId;
2875
- setTaskFormOpen(false);
2876
- setEditingTaskId(null);
2877
- setTaskFormData(EMPTY_TASK_FORM);
2878
- void handleArchiveTask(id);
2879
- }}>
2880
- {archivingTaskId === editingTaskId ? (<lucide_react_1.Loader2 className="mr-2 size-4 animate-spin"/>) : (<lucide_react_1.Archive className="mr-2 size-4"/>)}
2881
- {commonT('actions.archive')}
2882
- </button_1.Button>) : null}
2883
- </div>
2884
- <div className="flex gap-2">
2885
- <button_1.Button variant="outline" onClick={() => {
2886
- setTaskFormOpen(false);
2887
- setEditingTaskId(null);
2888
- setTaskFormData(EMPTY_TASK_FORM);
2889
- }} disabled={taskFormLoading}>
2890
- {commonT('actions.cancel')}
2891
- </button_1.Button>
2892
- <button_1.Button onClick={() => void handleTaskFormSubmit()} disabled={taskFormLoading || !taskFormData.name.trim()}>
2893
- {taskFormLoading
2894
- ? t('taskForm.saving')
2895
- : editingTaskId
2896
- ? commonT('actions.save')
2897
- : commonT('actions.create')}
2898
- </button_1.Button>
2899
- </div>
2900
- </div>
2901
- </sheet_1.SheetContent>
2902
- </sheet_1.Sheet>) : null}
2903
-
2904
- {!isLimitedView ? (<>
2905
- <dialog_1.Dialog open={deletePromptTask !== null} onOpenChange={(open) => {
2906
- if (!open)
2907
- setDeletePromptTask(null);
2908
- }}>
2909
- <dialog_1.DialogContent className="sm:max-w-sm">
2910
- <dialog_1.DialogHeader>
2911
- <dialog_1.DialogTitle>{t('dialogs.deleteTitle')}</dialog_1.DialogTitle>
2912
- </dialog_1.DialogHeader>
2913
- <p className="text-sm text-muted-foreground">
2914
- {t('dialogs.deleteDescription')}
2915
- </p>
2916
- <dialog_1.DialogFooter className="mt-4">
2917
- <button_1.Button variant="outline" onClick={() => setDeletePromptTask(null)}>
2918
- {commonT('actions.cancel')}
2919
- </button_1.Button>
2920
- {deletePromptTask ? (<button_1.Button variant="destructive" disabled={deletingTaskId === deletePromptTask.id} onClick={() => void handleDeleteTask(deletePromptTask.id)}>
2921
- {deletingTaskId === deletePromptTask.id ? (<lucide_react_1.Loader2 className="mr-2 size-3.5 animate-spin"/>) : null}
2922
- {commonT('actions.delete')}
2923
- </button_1.Button>) : null}
2924
- </dialog_1.DialogFooter>
2925
- </dialog_1.DialogContent>
2926
- </dialog_1.Dialog>
2927
- </>) : null}
2928
- </entity_list_1.Page>);
2929
- }
2930
- //# sourceMappingURL=project-details-screen.js.map