@hed-hog/operations 0.0.322 → 0.0.325

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 (689) hide show
  1. package/dist/controllers/operations-collaborators.controller.d.ts +9 -0
  2. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
  3. package/dist/controllers/operations-collaborators.controller.js +25 -0
  4. package/dist/controllers/operations-collaborators.controller.js.map +1 -1
  5. package/dist/controllers/operations-project-costs.controller.d.ts +422 -0
  6. package/dist/controllers/operations-project-costs.controller.d.ts.map +1 -0
  7. package/dist/controllers/operations-project-costs.controller.js +250 -0
  8. package/dist/controllers/operations-project-costs.controller.js.map +1 -0
  9. package/dist/controllers/operations-reports.controller.d.ts +9 -0
  10. package/dist/controllers/operations-reports.controller.d.ts.map +1 -1
  11. package/dist/controllers/operations-tasks.controller.d.ts +42 -0
  12. package/dist/controllers/operations-tasks.controller.d.ts.map +1 -1
  13. package/dist/controllers/operations-tasks.controller.js +48 -0
  14. package/dist/controllers/operations-tasks.controller.js.map +1 -1
  15. package/dist/controllers/operations-timesheets.controller.d.ts +1 -0
  16. package/dist/controllers/operations-timesheets.controller.d.ts.map +1 -1
  17. package/dist/dto/create-collaborator-project-assignment.dto.d.ts +5 -0
  18. package/dist/dto/create-collaborator-project-assignment.dto.d.ts.map +1 -0
  19. package/dist/dto/create-collaborator-project-assignment.dto.js +30 -0
  20. package/dist/dto/create-collaborator-project-assignment.dto.js.map +1 -0
  21. package/dist/dto/create-project-cost-category.dto.d.ts +10 -0
  22. package/dist/dto/create-project-cost-category.dto.d.ts.map +1 -0
  23. package/dist/dto/create-project-cost-category.dto.js +59 -0
  24. package/dist/dto/create-project-cost-category.dto.js.map +1 -0
  25. package/dist/dto/create-project-cost-type.dto.d.ts +14 -0
  26. package/dist/dto/create-project-cost-type.dto.d.ts.map +1 -0
  27. package/dist/dto/create-project-cost-type.dto.js +87 -0
  28. package/dist/dto/create-project-cost-type.dto.js.map +1 -0
  29. package/dist/dto/create-project-cost.dto.d.ts +22 -0
  30. package/dist/dto/create-project-cost.dto.d.ts.map +1 -0
  31. package/dist/dto/create-project-cost.dto.js +135 -0
  32. package/dist/dto/create-project-cost.dto.js.map +1 -0
  33. package/dist/dto/get-project-cost-report.dto.d.ts +10 -0
  34. package/dist/dto/get-project-cost-report.dto.d.ts.map +1 -0
  35. package/dist/dto/get-project-cost-report.dto.js +65 -0
  36. package/dist/dto/get-project-cost-report.dto.js.map +1 -0
  37. package/dist/dto/list-project-cost-categories.dto.d.ts +6 -0
  38. package/dist/dto/list-project-cost-categories.dto.d.ts.map +1 -0
  39. package/dist/dto/list-project-cost-categories.dto.js +34 -0
  40. package/dist/dto/list-project-cost-categories.dto.js.map +1 -0
  41. package/dist/dto/list-project-cost-types.dto.d.ts +8 -0
  42. package/dist/dto/list-project-cost-types.dto.d.ts.map +1 -0
  43. package/dist/dto/list-project-cost-types.dto.js +45 -0
  44. package/dist/dto/list-project-cost-types.dto.js.map +1 -0
  45. package/dist/dto/list-project-costs.dto.d.ts +14 -0
  46. package/dist/dto/list-project-costs.dto.d.ts.map +1 -0
  47. package/dist/dto/list-project-costs.dto.js +81 -0
  48. package/dist/dto/list-project-costs.dto.js.map +1 -0
  49. package/dist/dto/list-tasks.dto.d.ts +1 -0
  50. package/dist/dto/list-tasks.dto.d.ts.map +1 -1
  51. package/dist/dto/list-tasks.dto.js +6 -0
  52. package/dist/dto/list-tasks.dto.js.map +1 -1
  53. package/dist/dto/list-timesheets.dto.d.ts +1 -0
  54. package/dist/dto/list-timesheets.dto.d.ts.map +1 -1
  55. package/dist/dto/list-timesheets.dto.js +7 -0
  56. package/dist/dto/list-timesheets.dto.js.map +1 -1
  57. package/dist/dto/update-collaborator-project-assignment.dto.d.ts +11 -0
  58. package/dist/dto/update-collaborator-project-assignment.dto.d.ts.map +1 -0
  59. package/dist/dto/update-collaborator-project-assignment.dto.js +65 -0
  60. package/dist/dto/update-collaborator-project-assignment.dto.js.map +1 -0
  61. package/dist/dto/update-project-cost-category.dto.d.ts +6 -0
  62. package/dist/dto/update-project-cost-category.dto.d.ts.map +1 -0
  63. package/dist/dto/update-project-cost-category.dto.js +9 -0
  64. package/dist/dto/update-project-cost-category.dto.js.map +1 -0
  65. package/dist/dto/update-project-cost-type.dto.d.ts +6 -0
  66. package/dist/dto/update-project-cost-type.dto.d.ts.map +1 -0
  67. package/dist/dto/update-project-cost-type.dto.js +9 -0
  68. package/dist/dto/update-project-cost-type.dto.js.map +1 -0
  69. package/dist/dto/update-project-cost.dto.d.ts +6 -0
  70. package/dist/dto/update-project-cost.dto.d.ts.map +1 -0
  71. package/dist/dto/update-project-cost.dto.js +9 -0
  72. package/dist/dto/update-project-cost.dto.js.map +1 -0
  73. package/dist/operations.module.d.ts.map +1 -1
  74. package/dist/operations.module.js +2 -0
  75. package/dist/operations.module.js.map +1 -1
  76. package/dist/operations.service.d.ts +562 -0
  77. package/dist/operations.service.d.ts.map +1 -1
  78. package/dist/operations.service.js +1657 -47
  79. package/dist/operations.service.js.map +1 -1
  80. package/hedhog/data/menu.yaml +52 -0
  81. package/hedhog/data/operations_project_cost_category.yaml +80 -0
  82. package/hedhog/data/operations_project_cost_type.yaml +503 -0
  83. package/hedhog/data/route.yaml +274 -0
  84. package/hedhog/frontend/app/_components/collaborator-costs-section.tsx.ejs +2 -18
  85. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +185 -276
  86. package/hedhog/frontend/app/_components/collaborator-tasks-tab.tsx.ejs +358 -0
  87. package/hedhog/frontend/app/_components/collaborator-timesheets-tab.tsx.ejs +242 -0
  88. package/hedhog/frontend/app/_components/my-project-summary-screen.tsx.ejs +167 -59
  89. package/hedhog/frontend/app/_components/person-select-with-create.tsx.ejs +1 -853
  90. package/hedhog/frontend/app/_components/project-assignments-tab.tsx.ejs +450 -0
  91. package/hedhog/frontend/app/_components/project-cost-report-screen.tsx.ejs +602 -0
  92. package/hedhog/frontend/app/_components/project-costs-section.tsx.ejs +1401 -0
  93. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +2003 -1846
  94. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +56 -11
  95. package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +297 -2
  96. package/hedhog/frontend/app/_components/task-form-sheet.tsx.ejs +530 -0
  97. package/hedhog/frontend/app/_lib/api.ts.ejs +247 -0
  98. package/hedhog/frontend/app/_lib/types.ts.ejs +196 -7
  99. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +9 -3
  100. package/hedhog/frontend/app/collaborators/page.tsx.ejs +18 -7
  101. package/hedhog/frontend/app/my-tasks/page.tsx.ejs +219 -122
  102. package/hedhog/frontend/app/project-cost-categories/page.tsx.ejs +674 -0
  103. package/hedhog/frontend/app/project-cost-types/page.tsx.ejs +845 -0
  104. package/hedhog/frontend/app/projects/[id]/costs-report/page.tsx.ejs +10 -0
  105. package/hedhog/frontend/app/reports/collaborators/page.tsx.ejs +20 -349
  106. package/hedhog/frontend/app/reports/projects/page.tsx.ejs +192 -484
  107. package/hedhog/frontend/messages/en.json +279 -10
  108. package/hedhog/frontend/messages/en.json.ejs +2043 -0
  109. package/hedhog/frontend/messages/operations/en.json +2068 -0
  110. package/hedhog/frontend/messages/operations/operations/en.json +2102 -0
  111. package/hedhog/frontend/messages/operations/operations/pt.json +2111 -0
  112. package/hedhog/frontend/messages/operations/pt.json +2072 -0
  113. package/hedhog/frontend/messages/pt.json +284 -13
  114. package/hedhog/frontend/messages/pt.json.ejs +2056 -0
  115. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.d.ts +29 -0
  116. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.d.ts.map +1 -0
  117. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.js +95 -0
  118. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.js.map +1 -0
  119. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.tsx +233 -0
  120. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.d.ts +10 -0
  121. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.d.ts.map +1 -0
  122. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.js +577 -0
  123. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.js.map +1 -0
  124. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.tsx +868 -0
  125. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.d.ts +4 -0
  126. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.d.ts.map +1 -0
  127. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.js +337 -0
  128. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.js.map +1 -0
  129. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.tsx +476 -0
  130. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.d.ts +9 -0
  131. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.d.ts.map +1 -0
  132. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.js +1348 -0
  133. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.js.map +1 -0
  134. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.tsx +2233 -0
  135. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.d.ts +12 -0
  136. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.d.ts.map +1 -0
  137. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.js +162 -0
  138. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.js.map +1 -0
  139. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.tsx +261 -0
  140. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.d.ts +18 -0
  141. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.d.ts.map +1 -0
  142. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.js +145 -0
  143. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.js.map +1 -0
  144. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.tsx +258 -0
  145. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.d.ts +4 -0
  146. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.d.ts.map +1 -0
  147. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.js +223 -0
  148. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.js.map +1 -0
  149. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.tsx +342 -0
  150. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.d.ts +58 -0
  151. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.d.ts.map +1 -0
  152. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.js +438 -0
  153. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.js.map +1 -0
  154. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.tsx +698 -0
  155. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.d.ts +20 -0
  156. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.d.ts.map +1 -0
  157. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.js +233 -0
  158. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.js.map +1 -0
  159. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.tsx +392 -0
  160. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.d.ts +4 -0
  161. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.d.ts.map +1 -0
  162. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.js +814 -0
  163. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.js.map +1 -0
  164. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.tsx +1288 -0
  165. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.d.ts +21 -0
  166. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.d.ts.map +1 -0
  167. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.js +174 -0
  168. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.js.map +1 -0
  169. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.tsx +306 -0
  170. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.d.ts +10 -0
  171. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.d.ts.map +1 -0
  172. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.js +12 -0
  173. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.js.map +1 -0
  174. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.tsx +29 -0
  175. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.d.ts +15 -0
  176. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.d.ts.map +1 -0
  177. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.js +501 -0
  178. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.js.map +1 -0
  179. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.tsx +853 -0
  180. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.d.ts +6 -0
  181. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.d.ts.map +1 -0
  182. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.js +847 -0
  183. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.js.map +1 -0
  184. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.tsx +1340 -0
  185. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.d.ts +4 -0
  186. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.d.ts.map +1 -0
  187. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.js +2930 -0
  188. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.js.map +1 -0
  189. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.tsx +4378 -0
  190. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.d.ts +9 -0
  191. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.d.ts.map +1 -0
  192. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.js +1013 -0
  193. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.js.map +1 -0
  194. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.tsx +1745 -0
  195. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.d.ts +13 -0
  196. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.d.ts.map +1 -0
  197. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.js +38 -0
  198. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.js.map +1 -0
  199. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.tsx +74 -0
  200. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.d.ts +7 -0
  201. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.d.ts.map +1 -0
  202. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.js +11 -0
  203. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.js.map +1 -0
  204. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.tsx +15 -0
  205. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.d.ts +18 -0
  206. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.d.ts.map +1 -0
  207. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.js +406 -0
  208. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.js.map +1 -0
  209. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.tsx +660 -0
  210. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.d.ts +26 -0
  211. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.d.ts.map +1 -0
  212. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.js +332 -0
  213. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.js.map +1 -0
  214. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.tsx +518 -0
  215. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.d.ts +6 -0
  216. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.d.ts.map +1 -0
  217. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.js +255 -0
  218. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.js.map +1 -0
  219. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.tsx +388 -0
  220. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.d.ts +10 -0
  221. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.d.ts.map +1 -0
  222. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.js +131 -0
  223. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.js.map +1 -0
  224. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.tsx +214 -0
  225. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.d.ts +108 -0
  226. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.d.ts.map +1 -0
  227. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.js +162 -0
  228. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.js.map +1 -0
  229. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.ts +428 -0
  230. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.d.ts +8 -0
  231. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.d.ts.map +1 -0
  232. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.js +36 -0
  233. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.js.map +1 -0
  234. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.ts +44 -0
  235. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts +836 -0
  236. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts.map +1 -0
  237. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.js +3 -0
  238. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.js.map +1 -0
  239. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.ts +860 -0
  240. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.d.ts +16 -0
  241. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.d.ts.map +1 -0
  242. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.js +182 -0
  243. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.js.map +1 -0
  244. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.ts +250 -0
  245. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.d.ts +4 -0
  246. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.d.ts.map +1 -0
  247. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.js +51 -0
  248. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.js.map +1 -0
  249. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.ts +61 -0
  250. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.d.ts +2 -0
  251. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.d.ts.map +1 -0
  252. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.js +954 -0
  253. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.js.map +1 -0
  254. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.tsx +1277 -0
  255. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.d.ts +2 -0
  256. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.d.ts.map +1 -0
  257. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.js +488 -0
  258. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.js.map +1 -0
  259. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.tsx +805 -0
  260. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.d.ts +6 -0
  261. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.d.ts.map +1 -0
  262. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.js +9 -0
  263. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.js.map +1 -0
  264. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.tsx +11 -0
  265. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.d.ts +6 -0
  266. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.d.ts.map +1 -0
  267. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.js +9 -0
  268. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.js.map +1 -0
  269. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.tsx +11 -0
  270. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.d.ts +2 -0
  271. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.d.ts.map +1 -0
  272. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.js +8 -0
  273. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.js.map +1 -0
  274. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.tsx +5 -0
  275. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.d.ts +2 -0
  276. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.d.ts.map +1 -0
  277. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.js +612 -0
  278. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.js.map +1 -0
  279. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.tsx +939 -0
  280. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.d.ts +6 -0
  281. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.d.ts.map +1 -0
  282. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.js +9 -0
  283. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.js.map +1 -0
  284. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.tsx +11 -0
  285. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.d.ts +6 -0
  286. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.d.ts.map +1 -0
  287. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.js +9 -0
  288. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.js.map +1 -0
  289. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.tsx +11 -0
  290. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.d.ts +6 -0
  291. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.d.ts.map +1 -0
  292. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.js +9 -0
  293. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.js.map +1 -0
  294. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.tsx +17 -0
  295. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.d.ts +2 -0
  296. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.d.ts.map +1 -0
  297. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.js +348 -0
  298. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.js.map +1 -0
  299. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.tsx +536 -0
  300. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.d.ts +2 -0
  301. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.d.ts.map +1 -0
  302. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.js +401 -0
  303. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.js.map +1 -0
  304. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.tsx +607 -0
  305. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.d.ts +5 -0
  306. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.d.ts.map +1 -0
  307. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.js +7 -0
  308. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.js.map +1 -0
  309. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.tsx +9 -0
  310. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.d.ts +6 -0
  311. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.d.ts.map +1 -0
  312. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.js +9 -0
  313. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.js.map +1 -0
  314. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.tsx +11 -0
  315. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.d.ts +2 -0
  316. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.d.ts.map +1 -0
  317. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.js +321 -0
  318. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.js.map +1 -0
  319. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.tsx +440 -0
  320. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.d.ts +2 -0
  321. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.d.ts.map +1 -0
  322. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.js +939 -0
  323. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.js.map +1 -0
  324. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.tsx +1499 -0
  325. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.d.ts +29 -0
  326. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.d.ts.map +1 -0
  327. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.js +95 -0
  328. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.js.map +1 -0
  329. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.tsx +233 -0
  330. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.d.ts +10 -0
  331. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.d.ts.map +1 -0
  332. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.js +577 -0
  333. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.js.map +1 -0
  334. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.tsx +868 -0
  335. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.d.ts +4 -0
  336. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.d.ts.map +1 -0
  337. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.js +337 -0
  338. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.js.map +1 -0
  339. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.tsx +476 -0
  340. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.d.ts +9 -0
  341. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.d.ts.map +1 -0
  342. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.js +1348 -0
  343. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.js.map +1 -0
  344. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.tsx +2233 -0
  345. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.d.ts +12 -0
  346. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.d.ts.map +1 -0
  347. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.js +162 -0
  348. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.js.map +1 -0
  349. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.tsx +261 -0
  350. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.d.ts +18 -0
  351. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.d.ts.map +1 -0
  352. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.js +145 -0
  353. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.js.map +1 -0
  354. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.tsx +258 -0
  355. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.d.ts +4 -0
  356. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.d.ts.map +1 -0
  357. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.js +223 -0
  358. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.js.map +1 -0
  359. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.tsx +342 -0
  360. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.d.ts +58 -0
  361. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.d.ts.map +1 -0
  362. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.js +438 -0
  363. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.js.map +1 -0
  364. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.tsx +698 -0
  365. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.d.ts +20 -0
  366. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.d.ts.map +1 -0
  367. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.js +233 -0
  368. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.js.map +1 -0
  369. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.tsx +392 -0
  370. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.d.ts +4 -0
  371. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.d.ts.map +1 -0
  372. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.js +814 -0
  373. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.js.map +1 -0
  374. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.tsx +1288 -0
  375. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.d.ts +21 -0
  376. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.d.ts.map +1 -0
  377. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.js +174 -0
  378. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.js.map +1 -0
  379. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.tsx +306 -0
  380. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.d.ts +10 -0
  381. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.d.ts.map +1 -0
  382. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.js +12 -0
  383. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.js.map +1 -0
  384. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.tsx +29 -0
  385. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.d.ts +15 -0
  386. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.d.ts.map +1 -0
  387. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.js +501 -0
  388. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.js.map +1 -0
  389. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.tsx +853 -0
  390. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.d.ts +6 -0
  391. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.d.ts.map +1 -0
  392. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.js +459 -0
  393. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.js.map +1 -0
  394. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.tsx +598 -0
  395. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.d.ts +6 -0
  396. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.d.ts.map +1 -0
  397. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.js +876 -0
  398. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.js.map +1 -0
  399. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.tsx +1368 -0
  400. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.d.ts +4 -0
  401. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.d.ts.map +1 -0
  402. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.js +2930 -0
  403. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.js.map +1 -0
  404. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.tsx +4378 -0
  405. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.d.ts +9 -0
  406. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.d.ts.map +1 -0
  407. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.js +1013 -0
  408. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.js.map +1 -0
  409. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.tsx +1745 -0
  410. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.d.ts +13 -0
  411. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.d.ts.map +1 -0
  412. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.js +38 -0
  413. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.js.map +1 -0
  414. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.tsx +74 -0
  415. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.d.ts +7 -0
  416. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.d.ts.map +1 -0
  417. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.js +11 -0
  418. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.js.map +1 -0
  419. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.tsx +15 -0
  420. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.d.ts +18 -0
  421. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.d.ts.map +1 -0
  422. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.js +406 -0
  423. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.js.map +1 -0
  424. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.tsx +660 -0
  425. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.d.ts +26 -0
  426. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.d.ts.map +1 -0
  427. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.js +332 -0
  428. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.js.map +1 -0
  429. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.tsx +518 -0
  430. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.d.ts +6 -0
  431. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.d.ts.map +1 -0
  432. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.js +255 -0
  433. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.js.map +1 -0
  434. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.tsx +388 -0
  435. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.d.ts +10 -0
  436. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.d.ts.map +1 -0
  437. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.js +131 -0
  438. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.js.map +1 -0
  439. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.tsx +214 -0
  440. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.d.ts +108 -0
  441. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.d.ts.map +1 -0
  442. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.js +162 -0
  443. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.js.map +1 -0
  444. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.ts +428 -0
  445. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.d.ts +8 -0
  446. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.d.ts.map +1 -0
  447. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.js +36 -0
  448. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.js.map +1 -0
  449. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.ts +44 -0
  450. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts +836 -0
  451. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts.map +1 -0
  452. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.js +3 -0
  453. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.js.map +1 -0
  454. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.ts +860 -0
  455. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.d.ts +16 -0
  456. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.d.ts.map +1 -0
  457. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.js +182 -0
  458. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.js.map +1 -0
  459. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.ts +250 -0
  460. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.d.ts +4 -0
  461. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.d.ts.map +1 -0
  462. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.js +51 -0
  463. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.js.map +1 -0
  464. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.ts +61 -0
  465. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.d.ts +2 -0
  466. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.d.ts.map +1 -0
  467. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.js +954 -0
  468. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.js.map +1 -0
  469. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.tsx +1277 -0
  470. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.d.ts +2 -0
  471. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.d.ts.map +1 -0
  472. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.js +488 -0
  473. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.js.map +1 -0
  474. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.tsx +805 -0
  475. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.d.ts +6 -0
  476. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.d.ts.map +1 -0
  477. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.js +9 -0
  478. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.js.map +1 -0
  479. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.tsx +11 -0
  480. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.d.ts +6 -0
  481. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.d.ts.map +1 -0
  482. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.js +9 -0
  483. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.js.map +1 -0
  484. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.tsx +11 -0
  485. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.d.ts +2 -0
  486. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.d.ts.map +1 -0
  487. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.js +8 -0
  488. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.js.map +1 -0
  489. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.tsx +5 -0
  490. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.d.ts +2 -0
  491. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.d.ts.map +1 -0
  492. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.js +612 -0
  493. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.js.map +1 -0
  494. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.tsx +939 -0
  495. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.d.ts +6 -0
  496. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.d.ts.map +1 -0
  497. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.js +9 -0
  498. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.js.map +1 -0
  499. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.tsx +11 -0
  500. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.d.ts +6 -0
  501. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.d.ts.map +1 -0
  502. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.js +9 -0
  503. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.js.map +1 -0
  504. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.tsx +11 -0
  505. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.d.ts +6 -0
  506. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.d.ts.map +1 -0
  507. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.js +9 -0
  508. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.js.map +1 -0
  509. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.tsx +17 -0
  510. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.d.ts +2 -0
  511. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.d.ts.map +1 -0
  512. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.js +348 -0
  513. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.js.map +1 -0
  514. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.tsx +536 -0
  515. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.d.ts +2 -0
  516. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.d.ts.map +1 -0
  517. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.js +401 -0
  518. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.js.map +1 -0
  519. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.tsx +607 -0
  520. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.d.ts +5 -0
  521. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.d.ts.map +1 -0
  522. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.js +7 -0
  523. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.js.map +1 -0
  524. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.tsx +9 -0
  525. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.d.ts +6 -0
  526. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.d.ts.map +1 -0
  527. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.js +9 -0
  528. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.js.map +1 -0
  529. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.tsx +11 -0
  530. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.d.ts +2 -0
  531. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.d.ts.map +1 -0
  532. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.js +321 -0
  533. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.js.map +1 -0
  534. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.tsx +440 -0
  535. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.d.ts +2 -0
  536. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.d.ts.map +1 -0
  537. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.js +939 -0
  538. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.js.map +1 -0
  539. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.tsx +1499 -0
  540. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.d.ts +2 -0
  541. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.d.ts.map +1 -0
  542. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.js +8 -0
  543. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.js.map +1 -0
  544. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.tsx +5 -0
  545. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.d.ts +2 -0
  546. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.d.ts.map +1 -0
  547. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.js +436 -0
  548. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.js.map +1 -0
  549. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.tsx +675 -0
  550. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.d.ts +2 -0
  551. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.d.ts.map +1 -0
  552. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.js +563 -0
  553. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.js.map +1 -0
  554. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.tsx +846 -0
  555. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.d.ts +6 -0
  556. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.d.ts.map +1 -0
  557. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.js +9 -0
  558. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.js.map +1 -0
  559. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.tsx +10 -0
  560. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.d.ts +6 -0
  561. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.d.ts.map +1 -0
  562. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.js +9 -0
  563. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.js.map +1 -0
  564. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.tsx +11 -0
  565. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.d.ts +6 -0
  566. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.d.ts.map +1 -0
  567. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.js +9 -0
  568. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.js.map +1 -0
  569. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.tsx +11 -0
  570. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.d.ts +2 -0
  571. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.d.ts.map +1 -0
  572. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.js +8 -0
  573. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.js.map +1 -0
  574. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.tsx +5 -0
  575. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.d.ts +2 -0
  576. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.d.ts.map +1 -0
  577. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.js +492 -0
  578. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.js.map +1 -0
  579. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.tsx +757 -0
  580. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.d.ts +2 -0
  581. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.d.ts.map +1 -0
  582. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.js +342 -0
  583. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.js.map +1 -0
  584. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.tsx +430 -0
  585. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.d.ts +2 -0
  586. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.d.ts.map +1 -0
  587. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.js +338 -0
  588. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.js.map +1 -0
  589. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.tsx +428 -0
  590. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.d.ts +2 -0
  591. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.d.ts.map +1 -0
  592. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.js +660 -0
  593. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.js.map +1 -0
  594. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.tsx +992 -0
  595. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.d.ts +2 -0
  596. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.d.ts.map +1 -0
  597. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.js +515 -0
  598. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.js.map +1 -0
  599. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.tsx +707 -0
  600. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.d.ts +2 -0
  601. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.d.ts.map +1 -0
  602. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.js +1141 -0
  603. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.js.map +1 -0
  604. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.tsx +1705 -0
  605. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.d.ts +2 -0
  606. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.d.ts.map +1 -0
  607. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.js +8 -0
  608. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.js.map +1 -0
  609. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.tsx +5 -0
  610. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.d.ts +2 -0
  611. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.d.ts.map +1 -0
  612. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.js +436 -0
  613. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.js.map +1 -0
  614. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.tsx +675 -0
  615. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.d.ts +2 -0
  616. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.d.ts.map +1 -0
  617. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.js +563 -0
  618. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.js.map +1 -0
  619. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.tsx +846 -0
  620. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.d.ts +6 -0
  621. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.d.ts.map +1 -0
  622. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.js +9 -0
  623. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.js.map +1 -0
  624. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.tsx +11 -0
  625. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.d.ts +6 -0
  626. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.d.ts.map +1 -0
  627. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.js +9 -0
  628. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.js.map +1 -0
  629. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.tsx +11 -0
  630. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.d.ts +2 -0
  631. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.d.ts.map +1 -0
  632. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.js +8 -0
  633. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.js.map +1 -0
  634. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.tsx +5 -0
  635. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.d.ts +2 -0
  636. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.d.ts.map +1 -0
  637. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.js +492 -0
  638. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.js.map +1 -0
  639. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.tsx +757 -0
  640. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.d.ts +2 -0
  641. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.d.ts.map +1 -0
  642. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.js +342 -0
  643. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.js.map +1 -0
  644. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.tsx +430 -0
  645. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.d.ts +2 -0
  646. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.d.ts.map +1 -0
  647. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.js +338 -0
  648. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.js.map +1 -0
  649. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.tsx +428 -0
  650. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.d.ts +2 -0
  651. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.d.ts.map +1 -0
  652. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.js +660 -0
  653. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.js.map +1 -0
  654. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.tsx +992 -0
  655. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.d.ts +2 -0
  656. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.d.ts.map +1 -0
  657. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.js +515 -0
  658. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.js.map +1 -0
  659. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.tsx +707 -0
  660. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.d.ts +2 -0
  661. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.d.ts.map +1 -0
  662. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.js +1141 -0
  663. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.js.map +1 -0
  664. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.tsx +1705 -0
  665. package/hedhog/table/operations_project_assignment.yaml +1 -0
  666. package/hedhog/table/operations_project_cost.yaml +93 -0
  667. package/hedhog/table/operations_project_cost_category.yaml +37 -0
  668. package/hedhog/table/operations_project_cost_type.yaml +55 -0
  669. package/hedhog/table/operations_task_comment.yaml +26 -0
  670. package/package.json +6 -6
  671. package/src/controllers/operations-collaborators.controller.ts +26 -0
  672. package/src/controllers/operations-project-costs.controller.ts +249 -0
  673. package/src/controllers/operations-tasks.controller.ts +49 -0
  674. package/src/dto/create-collaborator-project-assignment.dto.ts +14 -0
  675. package/src/dto/create-project-cost-category.dto.ts +37 -0
  676. package/src/dto/create-project-cost-type.dto.ts +64 -0
  677. package/src/dto/create-project-cost.dto.ts +126 -0
  678. package/src/dto/get-project-cost-report.dto.ts +46 -0
  679. package/src/dto/list-project-cost-categories.dto.ts +17 -0
  680. package/src/dto/list-project-cost-types.dto.ts +28 -0
  681. package/src/dto/list-project-costs.dto.ts +59 -0
  682. package/src/dto/list-tasks.dto.ts +7 -0
  683. package/src/dto/list-timesheets.dto.ts +7 -1
  684. package/src/dto/update-collaborator-project-assignment.dto.ts +58 -0
  685. package/src/dto/update-project-cost-category.dto.ts +4 -0
  686. package/src/dto/update-project-cost-type.dto.ts +4 -0
  687. package/src/dto/update-project-cost.dto.ts +4 -0
  688. package/src/operations.module.ts +2 -0
  689. package/src/operations.service.ts +2274 -39
@@ -0,0 +1,1745 @@
1
+ 'use client';
2
+
3
+ import { EmptyState, Page } from '@/components/entity-list';
4
+ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
5
+ import { Button } from '@/components/ui/button';
6
+ import { Checkbox } from '@/components/ui/checkbox';
7
+ import {
8
+ Command,
9
+ CommandEmpty,
10
+ CommandGroup,
11
+ CommandInput,
12
+ CommandItem,
13
+ CommandList,
14
+ } from '@/components/ui/command';
15
+ import {
16
+ Form,
17
+ FormControl,
18
+ FormField,
19
+ FormItem,
20
+ FormLabel,
21
+ FormMessage,
22
+ } from '@/components/ui/form';
23
+ import { FormActions } from '@/components/ui/form-actions';
24
+ import { Input } from '@/components/ui/input';
25
+ import { InputMoney } from '@/components/ui/input-money';
26
+ import { Label } from '@/components/ui/label';
27
+ import {
28
+ Popover,
29
+ PopoverContent,
30
+ PopoverTrigger,
31
+ } from '@/components/ui/popover';
32
+ import {
33
+ Select,
34
+ SelectContent,
35
+ SelectItem,
36
+ SelectTrigger,
37
+ SelectValue,
38
+ } from '@/components/ui/select';
39
+ import {
40
+ Sheet,
41
+ SheetContent,
42
+ SheetDescription,
43
+ SheetHeader,
44
+ SheetTitle,
45
+ } from '@/components/ui/sheet';
46
+ import { Textarea } from '@/components/ui/textarea';
47
+ import {
48
+ Tooltip,
49
+ TooltipContent,
50
+ TooltipTrigger,
51
+ } from '@/components/ui/tooltip';
52
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
53
+ import { zodResolver } from '@hookform/resolvers/zod';
54
+ import {
55
+ ArrowLeft,
56
+ Check,
57
+ ChevronsUpDown,
58
+ FileText,
59
+ FolderKanban,
60
+ Info,
61
+ Plus,
62
+ Save,
63
+ Search,
64
+ X,
65
+ } from 'lucide-react';
66
+ import { useTranslations } from 'next-intl';
67
+ import Link from 'next/link';
68
+ import { useRouter } from 'next/navigation';
69
+ import { useEffect, useMemo, useState } from 'react';
70
+ import { useForm } from 'react-hook-form';
71
+ import { z } from 'zod';
72
+ import {
73
+ fetchOperations,
74
+ getOperationsErrorMessage,
75
+ mutateOperations,
76
+ } from '../_lib/api';
77
+ import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
78
+ import type {
79
+ OperationsCollaborator,
80
+ OperationsContract,
81
+ OperationsProjectDetails,
82
+ OperationsProjectRole,
83
+ } from '../_lib/types';
84
+ import { formatEnumLabel } from '../_lib/utils/format';
85
+ import {
86
+ normalizePercentInput,
87
+ parseNumberInput,
88
+ trimToNull,
89
+ } from '../_lib/utils/forms';
90
+ import { ContractFormScreen } from './contract-form-screen';
91
+ import { DepartmentSelectWithCreate } from './department-select-with-create';
92
+ import { OperationsHeader } from './operations-header';
93
+ import { PersonSelectWithCreate } from './person-select-with-create';
94
+
95
+ const OPTION_PAGE_SIZE = 12;
96
+
97
+ type TeamAssignmentState = {
98
+ collaboratorId: number;
99
+ selected: boolean;
100
+ projectRoleId: string;
101
+ roleLabel: string;
102
+ weeklyHours: string;
103
+ allocationPercent: string;
104
+ status: string;
105
+ startDate: string;
106
+ endDate: string;
107
+ };
108
+
109
+ type ProjectFormState = {
110
+ contractId: string;
111
+ managerCollaboratorId: string;
112
+ code: string;
113
+ name: string;
114
+ clientName: string;
115
+ summary: string;
116
+ status: string;
117
+ progressPercent: string;
118
+ deliveryModel: string;
119
+ budgetAmount: string;
120
+ startDate: string;
121
+ endDate: string;
122
+ billingModel: string;
123
+ monthlyHourCap: string;
124
+ contractCode: string;
125
+ contractName: string;
126
+ contractDescription: string;
127
+ teamAssignments: TeamAssignmentState[];
128
+ };
129
+
130
+ type ProjectFormValues = ProjectFormState;
131
+
132
+ function generateProjectCode(name: string): string {
133
+ const words = name.trim().split(/\s+/).filter(Boolean);
134
+ if (words.length === 0) return '';
135
+ if (words.length === 1) return words[0]!.slice(0, 5).toUpperCase();
136
+ return words
137
+ .map((w) => w[0]!.toUpperCase())
138
+ .join('')
139
+ .slice(0, 6);
140
+ }
141
+
142
+ function normalizeDateInputValue(value?: string | null) {
143
+ if (!value) {
144
+ return '';
145
+ }
146
+
147
+ const normalizedValue = String(value).trim();
148
+
149
+ if (!normalizedValue) {
150
+ return '';
151
+ }
152
+
153
+ const directMatch = normalizedValue.match(/^\d{4}-\d{2}-\d{2}/);
154
+
155
+ if (directMatch?.[0]) {
156
+ return directMatch[0];
157
+ }
158
+
159
+ const parsedDate = new Date(normalizedValue);
160
+
161
+ if (Number.isNaN(parsedDate.getTime())) {
162
+ return normalizedValue;
163
+ }
164
+
165
+ return parsedDate.toISOString().slice(0, 10);
166
+ }
167
+
168
+ function buildEmptyForm(
169
+ collaborators: OperationsCollaborator[] = []
170
+ ): ProjectFormState {
171
+ return {
172
+ contractId: 'none',
173
+ managerCollaboratorId: 'none',
174
+ code: '',
175
+ name: '',
176
+ clientName: '',
177
+ summary: '',
178
+ status: 'planning',
179
+ progressPercent: '',
180
+ deliveryModel: 'project_delivery',
181
+ budgetAmount: '',
182
+ startDate: '',
183
+ endDate: '',
184
+ billingModel: 'time_and_material',
185
+ monthlyHourCap: '',
186
+ contractCode: '',
187
+ contractName: '',
188
+ contractDescription: '',
189
+ teamAssignments: collaborators.map((collaborator) => ({
190
+ collaboratorId: collaborator.id,
191
+ selected: false,
192
+ projectRoleId: 'none',
193
+ roleLabel: '',
194
+ weeklyHours: '',
195
+ allocationPercent: '',
196
+ status: 'active',
197
+ startDate: new Date().toISOString().split('T')[0],
198
+ endDate: '',
199
+ })),
200
+ };
201
+ }
202
+
203
+ function toFormState(
204
+ project: OperationsProjectDetails,
205
+ collaborators: OperationsCollaborator[]
206
+ ): ProjectFormState {
207
+ const collaboratorOptions =
208
+ collaborators.length > 0
209
+ ? collaborators
210
+ : (project.assignments ?? []).map((assignment) => ({
211
+ id: assignment.collaboratorId,
212
+ code: '',
213
+ displayName: assignment.collaboratorName,
214
+ department: null,
215
+ title: null,
216
+ status: 'active',
217
+ }));
218
+
219
+ const assignments = new Map(
220
+ (project.assignments ?? []).map((assignment) => [
221
+ assignment.collaboratorId,
222
+ assignment,
223
+ ])
224
+ );
225
+
226
+ return {
227
+ contractId: project.relatedContract?.id
228
+ ? String(project.relatedContract.id)
229
+ : 'none',
230
+ managerCollaboratorId: project.managerCollaboratorId
231
+ ? String(project.managerCollaboratorId)
232
+ : 'none',
233
+ code: project.code ?? '',
234
+ name: project.name ?? '',
235
+ clientName: project.clientName ?? '',
236
+ summary: project.summary ?? '',
237
+ status: project.status ?? 'planning',
238
+ progressPercent:
239
+ project.progressPercent !== null && project.progressPercent !== undefined
240
+ ? String(project.progressPercent)
241
+ : '',
242
+ deliveryModel: project.deliveryModel ?? 'project_delivery',
243
+ budgetAmount:
244
+ project.budgetAmount !== null && project.budgetAmount !== undefined
245
+ ? String(project.budgetAmount)
246
+ : '',
247
+ startDate: normalizeDateInputValue(project.startDate),
248
+ endDate: normalizeDateInputValue(project.endDate),
249
+ billingModel: project.relatedContract?.billingModel ?? 'time_and_material',
250
+ monthlyHourCap:
251
+ project.relatedContract?.monthlyHourCap !== null &&
252
+ project.relatedContract?.monthlyHourCap !== undefined
253
+ ? String(project.relatedContract.monthlyHourCap)
254
+ : '',
255
+ contractCode: project.relatedContract?.code ?? '',
256
+ contractName: project.relatedContract?.name ?? '',
257
+ contractDescription: project.relatedContract?.description ?? '',
258
+ teamAssignments: collaboratorOptions.map((collaborator) => {
259
+ const assignment = assignments.get(collaborator.id);
260
+ return {
261
+ collaboratorId: collaborator.id,
262
+ selected: Boolean(assignment),
263
+ projectRoleId: assignment?.projectRoleId
264
+ ? String(assignment.projectRoleId)
265
+ : 'none',
266
+ roleLabel: assignment?.roleLabel ?? '',
267
+ weeklyHours:
268
+ assignment?.weeklyHours !== null &&
269
+ assignment?.weeklyHours !== undefined
270
+ ? String(assignment.weeklyHours)
271
+ : '',
272
+ allocationPercent:
273
+ assignment?.allocationPercent !== null &&
274
+ assignment?.allocationPercent !== undefined
275
+ ? String(assignment.allocationPercent)
276
+ : '',
277
+ status: assignment?.status ?? 'active',
278
+ startDate: normalizeDateInputValue(assignment?.startDate) || new Date().toISOString().split('T')[0],
279
+ endDate: normalizeDateInputValue(assignment?.endDate),
280
+ };
281
+ }),
282
+ };
283
+ }
284
+
285
+ type SearchableSelectProps = {
286
+ label: string;
287
+ value: string;
288
+ options: Array<{
289
+ id: number;
290
+ title: string;
291
+ description?: string | null;
292
+ avatarUrl?: string | null;
293
+ }>;
294
+ placeholder: string;
295
+ searchPlaceholder: string;
296
+ emptyLabel: string;
297
+ onChange: (value: string) => void;
298
+ };
299
+
300
+ function SearchableSelect({
301
+ label,
302
+ value,
303
+ options,
304
+ placeholder,
305
+ searchPlaceholder,
306
+ emptyLabel,
307
+ onChange,
308
+ }: SearchableSelectProps) {
309
+ const commonT = useTranslations('operations.Common');
310
+ const [open, setOpen] = useState(false);
311
+ const [search, setSearch] = useState('');
312
+ const [visibleCount, setVisibleCount] = useState(OPTION_PAGE_SIZE);
313
+
314
+ const filteredOptions = useMemo(() => {
315
+ const normalizedSearch = search.trim().toLowerCase();
316
+
317
+ if (!normalizedSearch) {
318
+ return options;
319
+ }
320
+
321
+ return options.filter((option) =>
322
+ [option.title, option.description]
323
+ .filter(Boolean)
324
+ .some((field) => String(field).toLowerCase().includes(normalizedSearch))
325
+ );
326
+ }, [options, search]);
327
+
328
+ const selectedOption = options.find((option) => String(option.id) === value);
329
+ const visibleOptions = filteredOptions.slice(0, visibleCount);
330
+
331
+ return (
332
+ <div className="grid gap-2">
333
+ {label ? <Label>{label}</Label> : null}
334
+
335
+ <Popover
336
+ open={open}
337
+ onOpenChange={(nextOpen) => {
338
+ setOpen(nextOpen);
339
+ setVisibleCount(OPTION_PAGE_SIZE);
340
+
341
+ if (!nextOpen) {
342
+ setSearch('');
343
+ }
344
+ }}
345
+ >
346
+ <PopoverTrigger asChild>
347
+ <Button
348
+ type="button"
349
+ variant="outline"
350
+ role="combobox"
351
+ className="w-full justify-between overflow-hidden"
352
+ >
353
+ <span className="truncate text-left">
354
+ {selectedOption?.title ?? emptyLabel}
355
+ </span>
356
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
357
+ </Button>
358
+ </PopoverTrigger>
359
+ <PopoverContent
360
+ className="p-0"
361
+ style={{ width: 'var(--radix-popover-trigger-width)' }}
362
+ >
363
+ <Command shouldFilter={false}>
364
+ <CommandInput
365
+ placeholder={searchPlaceholder}
366
+ value={search}
367
+ onValueChange={(nextValue) => {
368
+ setSearch(nextValue);
369
+ setVisibleCount(OPTION_PAGE_SIZE);
370
+ }}
371
+ />
372
+ <CommandList>
373
+ <CommandEmpty>
374
+ <div className="p-2 text-sm text-muted-foreground">
375
+ {commonT('states.emptyDescription')}
376
+ </div>
377
+ </CommandEmpty>
378
+
379
+ <CommandGroup>
380
+ <CommandItem
381
+ value="none"
382
+ onSelect={() => {
383
+ onChange('none');
384
+ setOpen(false);
385
+ }}
386
+ >
387
+ {value === 'none' ? (
388
+ <Check className="mr-2 h-4 w-4" />
389
+ ) : (
390
+ <span className="mr-2 h-4 w-4" />
391
+ )}
392
+ {placeholder}
393
+ </CommandItem>
394
+
395
+ {visibleOptions.map((option) => (
396
+ <CommandItem
397
+ key={option.id}
398
+ value={`${option.title} ${option.description ?? ''}`}
399
+ onSelect={() => {
400
+ onChange(String(option.id));
401
+ setOpen(false);
402
+ }}
403
+ >
404
+ {String(option.id) === value ? (
405
+ <Check className="mr-2 h-4 w-4" />
406
+ ) : (
407
+ <span className="mr-2 h-4 w-4" />
408
+ )}
409
+ {option.avatarUrl !== undefined ? (
410
+ <Avatar className="mr-2 h-6 w-6 shrink-0">
411
+ {option.avatarUrl ? (
412
+ <AvatarImage
413
+ src={option.avatarUrl}
414
+ alt={option.title}
415
+ />
416
+ ) : null}
417
+ <AvatarFallback className="text-[9px] font-medium">
418
+ {option.title
419
+ .trim()
420
+ .split(' ')
421
+ .filter(Boolean)
422
+ .slice(0, 2)
423
+ .map((w) => w[0]!.toUpperCase())
424
+ .join('')}
425
+ </AvatarFallback>
426
+ </Avatar>
427
+ ) : null}
428
+ <div className="min-w-0">
429
+ <div className="truncate">{option.title}</div>
430
+ {option.description ? (
431
+ <div className="truncate text-xs text-muted-foreground">
432
+ {option.description}
433
+ </div>
434
+ ) : null}
435
+ </div>
436
+ </CommandItem>
437
+ ))}
438
+ </CommandGroup>
439
+
440
+ {filteredOptions.length > visibleCount ? (
441
+ <div className="border-t p-2">
442
+ <Button
443
+ type="button"
444
+ variant="ghost"
445
+ className="w-full"
446
+ onClick={() =>
447
+ setVisibleCount((current) => current + OPTION_PAGE_SIZE)
448
+ }
449
+ >
450
+ {commonT('actions.loadMore')}
451
+ </Button>
452
+ </div>
453
+ ) : null}
454
+ </CommandList>
455
+ </Command>
456
+ </PopoverContent>
457
+ </Popover>
458
+ </div>
459
+ );
460
+ }
461
+
462
+ type ProjectFormScreenProps = {
463
+ projectId?: number;
464
+ onSaved?: (project: OperationsProjectDetails) => void | Promise<void>;
465
+ onCancel?: () => void;
466
+ };
467
+
468
+ function FieldLabel({ label, hint }: { label: string; hint?: string }) {
469
+ return (
470
+ <div className="flex items-center gap-1.5">
471
+ <Label>{label}</Label>
472
+ {hint ? (
473
+ <Tooltip>
474
+ <TooltipTrigger asChild>
475
+ <span className="inline-flex cursor-help text-muted-foreground">
476
+ <Info className="h-3.5 w-3.5" />
477
+ </span>
478
+ </TooltipTrigger>
479
+ <TooltipContent>
480
+ <p>{hint}</p>
481
+ </TooltipContent>
482
+ </Tooltip>
483
+ ) : null}
484
+ </div>
485
+ );
486
+ }
487
+
488
+ type ContractSelectWithCreateProps = {
489
+ value: string;
490
+ contracts: OperationsContract[];
491
+ label: string;
492
+ selectPlaceholder: string;
493
+ searchPlaceholder: string;
494
+ onChange: (value: string) => void;
495
+ onCreated?: (
496
+ contract: OperationsProjectDetails['relatedContract']
497
+ ) => void | Promise<void>;
498
+ initialValues?: {
499
+ code?: string;
500
+ name?: string;
501
+ clientName?: string;
502
+ contractCategory?: string;
503
+ contractType?: string;
504
+ signatureStatus?: string;
505
+ billingModel?: string;
506
+ budgetAmount?: string;
507
+ monthlyHourCap?: string;
508
+ startDate?: string;
509
+ endDate?: string;
510
+ description?: string;
511
+ contentHtml?: string;
512
+ };
513
+ };
514
+
515
+ function ContractSelectWithCreate({
516
+ value,
517
+ contracts,
518
+ label,
519
+ selectPlaceholder,
520
+ searchPlaceholder,
521
+ onChange,
522
+ onCreated,
523
+ initialValues,
524
+ }: ContractSelectWithCreateProps) {
525
+ const commonT = useTranslations('operations.Common');
526
+ const contractT = useTranslations('operations.ContractFormPage');
527
+ const selectedContract = contracts.find((item) => String(item.id) === value);
528
+ const hasSelection = value !== 'none';
529
+ const [isCreateSheetOpen, setIsCreateSheetOpen] = useState(false);
530
+
531
+ return (
532
+ <>
533
+ <div className="space-y-2">
534
+ <div className="grid min-w-0 grid-cols-[minmax(0,1fr)_auto] gap-2 sm:grid-cols-[minmax(0,1fr)_auto_auto]">
535
+ <SearchableSelect
536
+ label={label}
537
+ value={value}
538
+ options={contracts.map((contract) => ({
539
+ id: contract.id,
540
+ title:
541
+ contract.name ||
542
+ contract.code ||
543
+ commonT('labels.notAvailable'),
544
+ description: [
545
+ contract.code,
546
+ contract.clientName,
547
+ contractT.has(`options.contractTypes.${contract.contractType}`)
548
+ ? contractT(`options.contractTypes.${contract.contractType}`)
549
+ : formatEnumLabel(contract.contractType),
550
+ ]
551
+ .filter(Boolean)
552
+ .join(' • '),
553
+ }))}
554
+ placeholder={selectPlaceholder}
555
+ searchPlaceholder={searchPlaceholder}
556
+ emptyLabel={commonT('labels.notAssigned')}
557
+ onChange={onChange}
558
+ />
559
+
560
+ {hasSelection ? (
561
+ <Button
562
+ type="button"
563
+ variant="outline"
564
+ size="icon"
565
+ className="shrink-0"
566
+ onClick={() => onChange('none')}
567
+ aria-label={commonT('actions.clearSelection')}
568
+ >
569
+ <X className="size-4" />
570
+ </Button>
571
+ ) : null}
572
+
573
+ <Button
574
+ type="button"
575
+ variant="outline"
576
+ size="icon"
577
+ className="shrink-0"
578
+ onClick={() => setIsCreateSheetOpen(true)}
579
+ aria-label={commonT('actions.create')}
580
+ >
581
+ <Plus className="size-4" />
582
+ </Button>
583
+ </div>
584
+
585
+ {selectedContract ? (
586
+ <Button
587
+ type="button"
588
+ variant="outline"
589
+ size="sm"
590
+ asChild
591
+ className="w-fit"
592
+ >
593
+ <Link href={`/operations/contracts?edit=${selectedContract.id}`}>
594
+ <FileText className="size-4" />
595
+ {commonT('actions.openContract')}
596
+ </Link>
597
+ </Button>
598
+ ) : null}
599
+ </div>
600
+
601
+ <Sheet open={isCreateSheetOpen} onOpenChange={setIsCreateSheetOpen}>
602
+ <SheetContent className="w-full overflow-y-auto sm:max-w-7xl">
603
+ <SheetHeader>
604
+ <SheetTitle>{contractT('newTitle')}</SheetTitle>
605
+ <SheetDescription>{contractT('description')}</SheetDescription>
606
+ </SheetHeader>
607
+
608
+ <ContractFormScreen
609
+ initialValues={initialValues}
610
+ onCancel={() => setIsCreateSheetOpen(false)}
611
+ onSaved={async (contract) => {
612
+ const createdContractId = contract?.id
613
+ ? String(contract.id)
614
+ : value;
615
+ onChange(createdContractId);
616
+ await onCreated?.(
617
+ contract as OperationsProjectDetails['relatedContract']
618
+ );
619
+ setIsCreateSheetOpen(false);
620
+ }}
621
+ />
622
+ </SheetContent>
623
+ </Sheet>
624
+ </>
625
+ );
626
+ }
627
+
628
+ export function ProjectFormScreen({
629
+ projectId,
630
+ onSaved,
631
+ onCancel,
632
+ }: ProjectFormScreenProps) {
633
+ const t = useTranslations('operations.ProjectFormPage');
634
+ const commonT = useTranslations('operations.Common');
635
+ const contractT = useTranslations('operations.ContractFormPage');
636
+ const { request, showToastHandler, currentLocaleCode } = useApp();
637
+ const access = useOperationsAccess();
638
+ const router = useRouter();
639
+ const [assignmentSearch, setAssignmentSearch] = useState('');
640
+ const isSheetMode = Boolean(onCancel);
641
+ const isCreateMode = !projectId;
642
+ const [codeAutoMode, setCodeAutoMode] = useState(isCreateMode);
643
+
644
+ const projectFormSchema = useMemo(
645
+ () =>
646
+ z.object({
647
+ contractId: z.string(),
648
+ managerCollaboratorId: z.string(),
649
+ code: z.string().trim().min(1, t('messages.requiredFields')),
650
+ name: z.string().trim().min(1, t('messages.requiredFields')),
651
+ clientName: z.string().trim().min(1, t('messages.requiredFields')),
652
+ summary: z.string(),
653
+ status: z.string(),
654
+ progressPercent: z
655
+ .string()
656
+ .refine(
657
+ (value) =>
658
+ !value ||
659
+ (!Number.isNaN(Number(value)) &&
660
+ Number(value) >= 0 &&
661
+ Number(value) <= 100),
662
+ t('hints.progressPercent')
663
+ ),
664
+ deliveryModel: z.string(),
665
+ budgetAmount: z.string(),
666
+ startDate: z.string(),
667
+ endDate: z.string(),
668
+ billingModel: z.string(),
669
+ monthlyHourCap: z.string(),
670
+ contractCode: z.string(),
671
+ contractName: z.string(),
672
+ contractDescription: z.string(),
673
+ teamAssignments: z
674
+ .array(
675
+ z.object({
676
+ collaboratorId: z.number(),
677
+ selected: z.boolean(),
678
+ projectRoleId: z.string(),
679
+ roleLabel: z.string(),
680
+ weeklyHours: z.string(),
681
+ allocationPercent: z.string(),
682
+ status: z.string(),
683
+ startDate: z.string(),
684
+ endDate: z.string(),
685
+ })
686
+ )
687
+ .superRefine((assignments, ctx) => {
688
+ assignments.forEach((assignment, index) => {
689
+ if (assignment.selected && !assignment.roleLabel.trim()) {
690
+ ctx.addIssue({
691
+ code: z.ZodIssueCode.custom,
692
+ message: t('messages.roleRequired'),
693
+ path: [index, 'roleLabel'],
694
+ });
695
+ }
696
+ });
697
+ }),
698
+ }),
699
+ [t]
700
+ );
701
+
702
+ const formMethods = useForm<ProjectFormValues>({
703
+ resolver: zodResolver(projectFormSchema),
704
+ defaultValues: buildEmptyForm(),
705
+ mode: 'onSubmit',
706
+ reValidateMode: 'onChange',
707
+ });
708
+
709
+ const form = formMethods.watch();
710
+ const setForm = (
711
+ updater:
712
+ | ProjectFormState
713
+ | ((current: ProjectFormState) => ProjectFormState)
714
+ ) => {
715
+ const current = formMethods.getValues();
716
+ const next = typeof updater === 'function' ? updater(current) : updater;
717
+
718
+ formMethods.reset(next, {
719
+ keepErrors: true,
720
+ keepDirty: true,
721
+ keepTouched: true,
722
+ });
723
+ };
724
+
725
+ const { data: rawCollaborators } = useQuery<OperationsCollaborator[]>({
726
+ queryKey: ['operations-project-form-collaborators', currentLocaleCode],
727
+ enabled: access.isDirector,
728
+ queryFn: () =>
729
+ fetchOperations<OperationsCollaborator[]>(
730
+ request,
731
+ '/operations/collaborators'
732
+ ),
733
+ });
734
+ // Stable reference prevents the useEffect(reset, [collaborators, project]) from
735
+ // re-running on every render while the query is still loading (undefined → [] new ref).
736
+ const collaborators = useMemo(
737
+ () => rawCollaborators ?? [],
738
+ [rawCollaborators]
739
+ );
740
+
741
+ const { data: contracts = [], refetch: refetchContracts } = useQuery<
742
+ OperationsContract[]
743
+ >({
744
+ queryKey: ['operations-project-form-contracts', currentLocaleCode],
745
+ enabled: access.isDirector,
746
+ queryFn: () =>
747
+ fetchOperations<OperationsContract[]>(request, '/operations/contracts'),
748
+ });
749
+
750
+ const { data: projectRoles = [], refetch: refetchProjectRoles } = useQuery<
751
+ OperationsProjectRole[]
752
+ >({
753
+ queryKey: ['operations-project-form-project-roles', currentLocaleCode],
754
+ enabled: access.isDirector,
755
+ staleTime: 0,
756
+ refetchOnMount: 'always',
757
+ queryFn: () =>
758
+ fetchOperations<OperationsProjectRole[]>(
759
+ request,
760
+ '/operations/project-roles'
761
+ ),
762
+ });
763
+
764
+ const { data: project, isLoading: isLoadingProject } =
765
+ useQuery<OperationsProjectDetails>({
766
+ queryKey: ['operations-project-form', currentLocaleCode, projectId],
767
+ enabled: Boolean(projectId),
768
+ staleTime: 0,
769
+ refetchOnMount: 'always',
770
+ queryFn: () =>
771
+ fetchOperations<OperationsProjectDetails>(
772
+ request,
773
+ `/operations/projects/${projectId}`
774
+ ),
775
+ });
776
+
777
+ useEffect(() => {
778
+ if (project) {
779
+ formMethods.reset(toFormState(project, collaborators));
780
+ return;
781
+ }
782
+
783
+ if (!collaborators.length) {
784
+ return;
785
+ }
786
+
787
+ const currentValues = formMethods.getValues();
788
+ if (!currentValues.teamAssignments.length) {
789
+ formMethods.reset(buildEmptyForm(collaborators));
790
+ }
791
+ }, [collaborators, formMethods, project]);
792
+
793
+ const availableCollaborators = useMemo(() => {
794
+ const byId = new Map<number, OperationsCollaborator>();
795
+
796
+ for (const collaborator of collaborators) {
797
+ byId.set(collaborator.id, collaborator);
798
+ }
799
+
800
+ if (
801
+ project?.managerCollaboratorId &&
802
+ !byId.has(project.managerCollaboratorId)
803
+ ) {
804
+ byId.set(project.managerCollaboratorId, {
805
+ id: project.managerCollaboratorId,
806
+ code: '',
807
+ displayName: project.managerName ?? `#${project.managerCollaboratorId}`,
808
+ department: null,
809
+ title: null,
810
+ status: 'active',
811
+ });
812
+ }
813
+
814
+ for (const assignment of project?.assignments ?? []) {
815
+ if (!byId.has(assignment.collaboratorId)) {
816
+ byId.set(assignment.collaboratorId, {
817
+ id: assignment.collaboratorId,
818
+ code: '',
819
+ displayName: assignment.collaboratorName,
820
+ department: null,
821
+ title: null,
822
+ status: 'active',
823
+ });
824
+ }
825
+ }
826
+
827
+ return Array.from(byId.values());
828
+ }, [collaborators, project]);
829
+
830
+ const availableContracts = useMemo(() => {
831
+ if (!project?.relatedContract) {
832
+ return contracts;
833
+ }
834
+
835
+ const hasSelectedContract = contracts.some(
836
+ (contract) => contract.id === project.relatedContract?.id
837
+ );
838
+
839
+ return hasSelectedContract
840
+ ? contracts
841
+ : [project.relatedContract, ...contracts];
842
+ }, [contracts, project]);
843
+
844
+ const selectedContract = useMemo(
845
+ () =>
846
+ availableContracts.find(
847
+ (contract) => String(contract.id) === form.contractId
848
+ ) ?? null,
849
+ [availableContracts, form.contractId]
850
+ );
851
+
852
+ const managerOptions = useMemo(
853
+ () =>
854
+ availableCollaborators.map((collaborator) => ({
855
+ id: collaborator.id,
856
+ title: collaborator.displayName,
857
+ description: [collaborator.department, collaborator.title]
858
+ .filter(Boolean)
859
+ .join(' • '),
860
+ avatarUrl:
861
+ typeof collaborator.personAvatarId === 'number' &&
862
+ collaborator.personAvatarId > 0
863
+ ? `${process.env.NEXT_PUBLIC_API_BASE_URL}/person/avatar/${collaborator.personAvatarId}`
864
+ : null,
865
+ })),
866
+ [availableCollaborators]
867
+ );
868
+
869
+ const projectRoleOptions = useMemo(
870
+ () =>
871
+ projectRoles.map((role) => ({
872
+ id: role.id,
873
+ name: role.name,
874
+ code: role.code ?? null,
875
+ description: role.description ?? null,
876
+ })),
877
+ [projectRoles]
878
+ );
879
+
880
+ const createProjectRole = async (projectRoleName: string) => {
881
+ try {
882
+ const createdRole = await mutateOperations<OperationsProjectRole>(
883
+ request,
884
+ '/operations/project-roles',
885
+ 'POST',
886
+ {
887
+ name: projectRoleName,
888
+ }
889
+ );
890
+
891
+ await refetchProjectRoles();
892
+ return createdRole;
893
+ } catch (error) {
894
+ showToastHandler?.(
895
+ 'error',
896
+ getOperationsErrorMessage(error, t('messages.projectRoleSaveError'))
897
+ );
898
+ return null;
899
+ }
900
+ };
901
+
902
+ const selectedAssignmentsCount = useMemo(
903
+ () =>
904
+ form.teamAssignments.filter((assignment) => assignment.selected).length,
905
+ [form.teamAssignments]
906
+ );
907
+
908
+ const filteredAssignments = useMemo(() => {
909
+ const normalizedSearch = assignmentSearch.trim().toLowerCase();
910
+
911
+ return form.teamAssignments.filter((assignment) => {
912
+ const collaborator = availableCollaborators.find(
913
+ (item) => item.id === assignment.collaboratorId
914
+ );
915
+
916
+ if (!collaborator) {
917
+ return false;
918
+ }
919
+
920
+ if (!normalizedSearch) {
921
+ return true;
922
+ }
923
+
924
+ return [
925
+ collaborator.displayName,
926
+ collaborator.department,
927
+ collaborator.title,
928
+ collaborator.code,
929
+ ]
930
+ .filter(Boolean)
931
+ .some((value) =>
932
+ String(value).toLowerCase().includes(normalizedSearch)
933
+ );
934
+ });
935
+ }, [assignmentSearch, availableCollaborators, form.teamAssignments]);
936
+
937
+ const updateAssignment = (
938
+ collaboratorId: number,
939
+ patch: Partial<TeamAssignmentState>
940
+ ) => {
941
+ const nextAssignments = formMethods
942
+ .getValues('teamAssignments')
943
+ .map((assignment) =>
944
+ assignment.collaboratorId === collaboratorId
945
+ ? { ...assignment, ...patch }
946
+ : assignment
947
+ );
948
+
949
+ formMethods.setValue('teamAssignments', nextAssignments, {
950
+ shouldDirty: true,
951
+ shouldValidate: true,
952
+ });
953
+ };
954
+
955
+ const onSubmit = async (values: ProjectFormValues) => {
956
+ const payload = {
957
+ contractId:
958
+ values.contractId === 'none'
959
+ ? null
960
+ : parseNumberInput(values.contractId),
961
+ managerCollaboratorId:
962
+ values.managerCollaboratorId === 'none'
963
+ ? null
964
+ : parseNumberInput(values.managerCollaboratorId),
965
+ code: values.code.trim(),
966
+ name: values.name.trim(),
967
+ clientName: trimToNull(values.clientName),
968
+ summary: trimToNull(values.summary),
969
+ status: values.status,
970
+ progressPercent: parseNumberInput(values.progressPercent),
971
+ deliveryModel: trimToNull(values.deliveryModel) ?? 'project_delivery',
972
+ budgetAmount: parseNumberInput(values.budgetAmount),
973
+ startDate: trimToNull(values.startDate),
974
+ endDate: trimToNull(values.endDate),
975
+ billingModel: values.billingModel,
976
+ monthlyHourCap: parseNumberInput(values.monthlyHourCap),
977
+ contractCode: trimToNull(values.contractCode),
978
+ contractName: trimToNull(values.contractName),
979
+ contractDescription: trimToNull(values.contractDescription),
980
+ teamAssignments: values.teamAssignments
981
+ .filter((assignment) => assignment.selected)
982
+ .map((assignment) => ({
983
+ collaboratorId: assignment.collaboratorId,
984
+ projectRoleId:
985
+ assignment.projectRoleId === 'none'
986
+ ? null
987
+ : parseNumberInput(assignment.projectRoleId),
988
+ roleLabel: trimToNull(assignment.roleLabel),
989
+ weeklyHours: parseNumberInput(assignment.weeklyHours),
990
+ allocationPercent: parseNumberInput(assignment.allocationPercent),
991
+ status: assignment.status,
992
+ startDate: trimToNull(assignment.startDate),
993
+ endDate: trimToNull(assignment.endDate),
994
+ })),
995
+ };
996
+
997
+ try {
998
+ const response = projectId
999
+ ? await mutateOperations<OperationsProjectDetails>(
1000
+ request,
1001
+ `/operations/projects/${projectId}`,
1002
+ 'PATCH',
1003
+ payload
1004
+ )
1005
+ : await mutateOperations<OperationsProjectDetails>(
1006
+ request,
1007
+ '/operations/projects',
1008
+ 'POST',
1009
+ payload
1010
+ );
1011
+
1012
+ showToastHandler?.(
1013
+ 'success',
1014
+ projectId ? t('messages.updateSuccess') : t('messages.createSuccess')
1015
+ );
1016
+
1017
+ if (onSaved) {
1018
+ await onSaved(response);
1019
+ return;
1020
+ }
1021
+
1022
+ router.push(`/operations/projects/${response.id}`);
1023
+ } catch (error) {
1024
+ showToastHandler?.(
1025
+ 'error',
1026
+ getOperationsErrorMessage(
1027
+ error,
1028
+ projectId ? t('messages.updateError') : t('messages.createError')
1029
+ )
1030
+ );
1031
+ }
1032
+ };
1033
+
1034
+ const handleInvalidSubmit = () => {
1035
+ showToastHandler?.('error', t('messages.requiredFields'));
1036
+ };
1037
+
1038
+ const noAccessState = (
1039
+ <EmptyState
1040
+ icon={<FolderKanban className="size-12" />}
1041
+ title={commonT('states.noAccessTitle')}
1042
+ description={t('noAccessDescription')}
1043
+ actionLabel={commonT('actions.refresh')}
1044
+ onAction={() => router.refresh()}
1045
+ />
1046
+ );
1047
+
1048
+ if (!access.isDirector && !access.isLoading) {
1049
+ if (isSheetMode) {
1050
+ return <div className="pt-4">{noAccessState}</div>;
1051
+ }
1052
+
1053
+ return (
1054
+ <Page>
1055
+ <OperationsHeader
1056
+ title={t(projectId ? 'editTitle' : 'newTitle')}
1057
+ description={t('description')}
1058
+ current={t('breadcrumb')}
1059
+ />
1060
+ {noAccessState}
1061
+ </Page>
1062
+ );
1063
+ }
1064
+
1065
+ const formContent = (
1066
+ <Form {...formMethods}>
1067
+ <form
1068
+ onSubmit={formMethods.handleSubmit(onSubmit, handleInvalidSubmit)}
1069
+ className="min-w-0 space-y-5 overflow-x-hidden px-4"
1070
+ >
1071
+ <section className="space-y-3">
1072
+ <div className="space-y-0.5">
1073
+ <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
1074
+ {t('sections.basicInfo')}
1075
+ </h3>
1076
+ <p className="text-[11px] text-muted-foreground/80">
1077
+ {t(
1078
+ isCreateMode
1079
+ ? 'sections.basicInfoCreateDescription'
1080
+ : 'sections.basicInfoDescription'
1081
+ )}
1082
+ </p>
1083
+ </div>
1084
+ <FormField
1085
+ control={formMethods.control}
1086
+ name="name"
1087
+ render={({ field }) => (
1088
+ <FormItem className="min-w-0">
1089
+ <FormLabel>{t('fields.name')}</FormLabel>
1090
+ <FormControl>
1091
+ <Input
1092
+ {...field}
1093
+ placeholder={t('placeholders.name')}
1094
+ autoFocus
1095
+ onChange={(e) => {
1096
+ field.onChange(e);
1097
+ if (codeAutoMode) {
1098
+ formMethods.setValue(
1099
+ 'code',
1100
+ generateProjectCode(e.target.value)
1101
+ );
1102
+ }
1103
+ }}
1104
+ />
1105
+ </FormControl>
1106
+ <FormMessage />
1107
+ </FormItem>
1108
+ )}
1109
+ />
1110
+ <div className="grid min-w-0 gap-3 lg:grid-cols-6">
1111
+ <FormField
1112
+ control={formMethods.control}
1113
+ name="code"
1114
+ render={({ field }) => (
1115
+ <FormItem className="min-w-0 lg:col-span-1">
1116
+ <FormLabel>{t('fields.code')}</FormLabel>
1117
+ <FormControl>
1118
+ <Input
1119
+ {...field}
1120
+ placeholder={t('placeholders.code')}
1121
+ onChange={(e) => {
1122
+ setCodeAutoMode(false);
1123
+ field.onChange(e);
1124
+ }}
1125
+ />
1126
+ </FormControl>
1127
+ <FormMessage />
1128
+ </FormItem>
1129
+ )}
1130
+ />
1131
+ <FormField
1132
+ control={formMethods.control}
1133
+ name="clientName"
1134
+ render={({ field, fieldState }) => (
1135
+ <FormItem className="min-w-0 lg:col-span-3">
1136
+ <FormLabel>{t('fields.clientName')}</FormLabel>
1137
+ <FormControl>
1138
+ <div
1139
+ className={
1140
+ fieldState.error
1141
+ ? 'rounded-md border border-destructive p-1'
1142
+ : ''
1143
+ }
1144
+ >
1145
+ <PersonSelectWithCreate
1146
+ label=""
1147
+ entityLabel={t('fields.clientName')}
1148
+ value={null}
1149
+ initialSelectedLabel={field.value}
1150
+ selectPlaceholder={t('placeholders.clientName')}
1151
+ onChange={(_, personName) =>
1152
+ field.onChange(personName ?? '')
1153
+ }
1154
+ personTypeFilter="all"
1155
+ createType="company"
1156
+ />
1157
+ </div>
1158
+ </FormControl>
1159
+ <FormMessage />
1160
+ </FormItem>
1161
+ )}
1162
+ />
1163
+
1164
+ <FormField
1165
+ control={formMethods.control}
1166
+ name="deliveryModel"
1167
+ render={({ field }) => (
1168
+ <FormItem className="min-w-0 lg:col-span-2">
1169
+ <FormLabel>{t('fields.deliveryModel')}</FormLabel>
1170
+ <Select value={field.value} onValueChange={field.onChange}>
1171
+ <FormControl>
1172
+ <SelectTrigger className="w-full">
1173
+ <SelectValue />
1174
+ </SelectTrigger>
1175
+ </FormControl>
1176
+ <SelectContent>
1177
+ <SelectItem value="project_delivery">
1178
+ {t('options.deliveryModels.project_delivery')}
1179
+ </SelectItem>
1180
+ <SelectItem value="dedicated_team">
1181
+ {t('options.deliveryModels.dedicated_team')}
1182
+ </SelectItem>
1183
+ <SelectItem value="shared_team">
1184
+ {t('options.deliveryModels.shared_team')}
1185
+ </SelectItem>
1186
+ <SelectItem value="support">
1187
+ {t('options.deliveryModels.support')}
1188
+ </SelectItem>
1189
+ </SelectContent>
1190
+ </Select>
1191
+ <FormMessage />
1192
+ </FormItem>
1193
+ )}
1194
+ />
1195
+ <FormField
1196
+ control={formMethods.control}
1197
+ name="summary"
1198
+ render={({ field }) => (
1199
+ <FormItem className="min-w-0 lg:col-span-6">
1200
+ <FormLabel>{t('fields.summary')}</FormLabel>
1201
+ <FormControl>
1202
+ <Textarea
1203
+ {...field}
1204
+ rows={3}
1205
+ placeholder={t('placeholders.summary')}
1206
+ />
1207
+ </FormControl>
1208
+ <FormMessage />
1209
+ </FormItem>
1210
+ )}
1211
+ />
1212
+ </div>
1213
+ </section>
1214
+
1215
+ <section className="space-y-3">
1216
+ <div className="space-y-0.5">
1217
+ <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
1218
+ {t('sections.governance')}
1219
+ </h3>
1220
+ <p className="text-[11px] text-muted-foreground/80">
1221
+ {t(
1222
+ isCreateMode
1223
+ ? 'sections.governanceCreateDescription'
1224
+ : 'sections.governanceDescription'
1225
+ )}
1226
+ </p>
1227
+ </div>
1228
+ <div className="grid min-w-0 gap-3 md:grid-cols-2 xl:grid-cols-5">
1229
+ <div className="min-w-0 space-y-2">
1230
+ <FieldLabel label={commonT('labels.manager')} />
1231
+ <SearchableSelect
1232
+ label=""
1233
+ value={form.managerCollaboratorId}
1234
+ options={managerOptions}
1235
+ placeholder={commonT('labels.notAssigned')}
1236
+ searchPlaceholder={t('placeholders.managerSearch')}
1237
+ emptyLabel={commonT('labels.notAssigned')}
1238
+ onChange={(value) =>
1239
+ setForm((current) => ({
1240
+ ...current,
1241
+ managerCollaboratorId: value,
1242
+ }))
1243
+ }
1244
+ />
1245
+ </div>
1246
+ <div className="min-w-0 space-y-2">
1247
+ <FieldLabel label={commonT('labels.startDate')} />
1248
+ <Input
1249
+ type="date"
1250
+ value={form.startDate}
1251
+ onChange={(event) =>
1252
+ setForm((current) => ({
1253
+ ...current,
1254
+ startDate: event.target.value,
1255
+ }))
1256
+ }
1257
+ />
1258
+ </div>
1259
+ {!isCreateMode ? (
1260
+ <>
1261
+ <div className="min-w-0 space-y-2">
1262
+ <FieldLabel label={commonT('labels.status')} />
1263
+ <Select
1264
+ value={form.status}
1265
+ onValueChange={(value) =>
1266
+ setForm((current) => ({ ...current, status: value }))
1267
+ }
1268
+ >
1269
+ <SelectTrigger className="w-full">
1270
+ <SelectValue />
1271
+ </SelectTrigger>
1272
+ <SelectContent>
1273
+ <SelectItem value="planning">
1274
+ {t('options.statuses.planning')}
1275
+ </SelectItem>
1276
+ <SelectItem value="active">
1277
+ {t('options.statuses.active')}
1278
+ </SelectItem>
1279
+ <SelectItem value="at_risk">
1280
+ {t('options.statuses.at_risk')}
1281
+ </SelectItem>
1282
+ <SelectItem value="paused">
1283
+ {t('options.statuses.paused')}
1284
+ </SelectItem>
1285
+ <SelectItem value="completed">
1286
+ {t('options.statuses.completed')}
1287
+ </SelectItem>
1288
+ <SelectItem value="archived">
1289
+ {t('options.statuses.archived')}
1290
+ </SelectItem>
1291
+ </SelectContent>
1292
+ </Select>
1293
+ </div>
1294
+ <div className="min-w-0 space-y-2">
1295
+ <FieldLabel label={commonT('labels.endDate')} />
1296
+ <Input
1297
+ type="date"
1298
+ value={form.endDate}
1299
+ onChange={(event) =>
1300
+ setForm((current) => ({
1301
+ ...current,
1302
+ endDate: event.target.value,
1303
+ }))
1304
+ }
1305
+ />
1306
+ </div>
1307
+ <FormField
1308
+ control={formMethods.control}
1309
+ name="progressPercent"
1310
+ render={({ field }) => (
1311
+ <FormItem className="min-w-0 gap-0">
1312
+ <FormLabel>{t('fields.progressPercent')}</FormLabel>
1313
+ <FormControl>
1314
+ <Input
1315
+ {...field}
1316
+ type="text"
1317
+ inputMode="decimal"
1318
+ placeholder={t('placeholders.progressPercent')}
1319
+ value={field.value ?? ''}
1320
+ onChange={(event) =>
1321
+ field.onChange(
1322
+ normalizePercentInput(event.target.value)
1323
+ )
1324
+ }
1325
+ />
1326
+ </FormControl>
1327
+ <FormMessage />
1328
+ </FormItem>
1329
+ )}
1330
+ />
1331
+ </>
1332
+ ) : null}
1333
+ </div>
1334
+ </section>
1335
+
1336
+ {!isCreateMode ? (
1337
+ <>
1338
+ <section className="space-y-3">
1339
+ <div className="space-y-0.5">
1340
+ <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
1341
+ {t('sections.financials')}
1342
+ </h3>
1343
+ <p className="text-[11px] text-muted-foreground/80">
1344
+ {t('sections.financialsDescription')}
1345
+ </p>
1346
+ </div>
1347
+ <div className="grid min-w-0 gap-3 md:grid-cols-2 xl:grid-cols-4">
1348
+ <div className="min-w-0 space-y-2">
1349
+ <FieldLabel label={commonT('labels.budget')} />
1350
+ <InputMoney
1351
+ value={
1352
+ form.budgetAmount === '' ? '' : Number(form.budgetAmount)
1353
+ }
1354
+ onValueChange={(value) =>
1355
+ setForm((current) => ({
1356
+ ...current,
1357
+ budgetAmount: value !== null ? String(value) : '',
1358
+ }))
1359
+ }
1360
+ />
1361
+ </div>
1362
+ <div className="min-w-0 space-y-2">
1363
+ <FieldLabel
1364
+ label={commonT('labels.monthlyHourCap')}
1365
+ hint={t('hints.monthlyHourCap')}
1366
+ />
1367
+ <Input
1368
+ type="text"
1369
+ inputMode="numeric"
1370
+ placeholder={t('placeholders.monthlyHourCap')}
1371
+ value={form.monthlyHourCap}
1372
+ onChange={(event) => {
1373
+ const raw = event.target.value.replace(/[^0-9]/g, '');
1374
+ setForm((current) => ({
1375
+ ...current,
1376
+ monthlyHourCap: raw,
1377
+ }));
1378
+ }}
1379
+ />
1380
+ </div>
1381
+ <div className="min-w-0 space-y-2">
1382
+ <FieldLabel label={commonT('labels.billingModel')} />
1383
+ <Select
1384
+ value={form.billingModel}
1385
+ onValueChange={(value) =>
1386
+ setForm((current) => ({
1387
+ ...current,
1388
+ billingModel: value,
1389
+ }))
1390
+ }
1391
+ >
1392
+ <SelectTrigger className="w-full">
1393
+ <SelectValue />
1394
+ </SelectTrigger>
1395
+ <SelectContent>
1396
+ <SelectItem value="time_and_material">
1397
+ {t('options.billingModels.time_and_material')}
1398
+ </SelectItem>
1399
+ <SelectItem value="monthly_retainer">
1400
+ {t('options.billingModels.monthly_retainer')}
1401
+ </SelectItem>
1402
+ <SelectItem value="fixed_price">
1403
+ {t('options.billingModels.fixed_price')}
1404
+ </SelectItem>
1405
+ </SelectContent>
1406
+ </Select>
1407
+ </div>
1408
+ <div className="min-w-0 space-y-2">
1409
+ <FieldLabel
1410
+ label={commonT('labels.contract')}
1411
+ hint={t('hints.contract')}
1412
+ />
1413
+ <ContractSelectWithCreate
1414
+ label=""
1415
+ value={form.contractId}
1416
+ contracts={availableContracts}
1417
+ selectPlaceholder={commonT('labels.notAssigned')}
1418
+ searchPlaceholder={t('placeholders.contractSearch')}
1419
+ onChange={(value) =>
1420
+ setForm((current) => ({ ...current, contractId: value }))
1421
+ }
1422
+ onCreated={async (contract) => {
1423
+ await refetchContracts();
1424
+ setForm((current) => ({
1425
+ ...current,
1426
+ contractId: contract?.id
1427
+ ? String(contract.id)
1428
+ : current.contractId,
1429
+ billingModel:
1430
+ contract?.billingModel ?? current.billingModel,
1431
+ monthlyHourCap:
1432
+ contract?.monthlyHourCap !== null &&
1433
+ contract?.monthlyHourCap !== undefined
1434
+ ? String(contract.monthlyHourCap)
1435
+ : current.monthlyHourCap,
1436
+ }));
1437
+ }}
1438
+ initialValues={{
1439
+ code: form.code ? `PRJ-${form.code}` : '',
1440
+ name: form.name ? `${form.name} Service Agreement` : '',
1441
+ clientName: form.clientName,
1442
+ contractCategory: 'client',
1443
+ contractType: 'service_agreement',
1444
+ signatureStatus: 'not_started',
1445
+ billingModel: form.billingModel,
1446
+ budgetAmount: form.budgetAmount,
1447
+ monthlyHourCap: form.monthlyHourCap,
1448
+ startDate: form.startDate,
1449
+ endDate: form.endDate,
1450
+ description: form.summary,
1451
+ contentHtml: '',
1452
+ }}
1453
+ />
1454
+ </div>
1455
+ </div>
1456
+ </section>
1457
+
1458
+ <section className="space-y-3">
1459
+ <div className="space-y-0.5">
1460
+ <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
1461
+ {t('sections.team')}
1462
+ </h3>
1463
+ <p className="text-[11px] text-muted-foreground/80">
1464
+ {t('sections.teamDescription', {
1465
+ count: selectedAssignmentsCount,
1466
+ })}
1467
+ </p>
1468
+ </div>
1469
+ <div className="space-y-3">
1470
+ <div className="relative">
1471
+ <Search className="pointer-events-none absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
1472
+ <Input
1473
+ className="pl-9"
1474
+ value={assignmentSearch}
1475
+ placeholder={t('placeholders.assignmentSearch')}
1476
+ onChange={(event) =>
1477
+ setAssignmentSearch(event.target.value)
1478
+ }
1479
+ />
1480
+ </div>
1481
+
1482
+ <div className="space-y-2">
1483
+ {filteredAssignments.map((assignment) => {
1484
+ const collaborator = availableCollaborators.find(
1485
+ (item) => item.id === assignment.collaboratorId
1486
+ );
1487
+ const assignmentIndex = form.teamAssignments.findIndex(
1488
+ (item) =>
1489
+ item.collaboratorId === assignment.collaboratorId
1490
+ );
1491
+ const roleError =
1492
+ assignmentIndex >= 0
1493
+ ? formMethods.formState.errors.teamAssignments?.[
1494
+ assignmentIndex
1495
+ ]?.roleLabel
1496
+ : undefined;
1497
+
1498
+ if (!collaborator) {
1499
+ return null;
1500
+ }
1501
+
1502
+ return (
1503
+ <div
1504
+ key={assignment.collaboratorId}
1505
+ className="grid min-w-0 gap-2 rounded-lg border px-3 py-2 xl:grid-cols-[minmax(0,1.25fr)_minmax(0,1.2fr)_110px_110px]"
1506
+ >
1507
+ <label className="flex cursor-pointer items-start gap-3 py-1">
1508
+ <Checkbox
1509
+ checked={assignment.selected}
1510
+ onCheckedChange={(checked) =>
1511
+ updateAssignment(assignment.collaboratorId, {
1512
+ selected: checked === true,
1513
+ })
1514
+ }
1515
+ />
1516
+ <div className="min-w-0">
1517
+ <div className="truncate font-medium">
1518
+ {collaborator.displayName}
1519
+ </div>
1520
+ <div className="truncate text-xs text-muted-foreground">
1521
+ {[
1522
+ collaborator.department,
1523
+ collaborator.title,
1524
+ collaborator.code,
1525
+ ]
1526
+ .filter(Boolean)
1527
+ .join(' • ') || commonT('labels.notAvailable')}
1528
+ </div>
1529
+ </div>
1530
+ </label>
1531
+ <div className="space-y-1">
1532
+ <DepartmentSelectWithCreate
1533
+ label=""
1534
+ value={assignment.roleLabel}
1535
+ options={projectRoleOptions}
1536
+ disabled={!assignment.selected}
1537
+ selectPlaceholder={t('placeholders.roleLabel')}
1538
+ createDescription={t('fields.roleLabel')}
1539
+ createPlaceholder={t(
1540
+ 'placeholders.roleLabelCreate'
1541
+ )}
1542
+ onChange={(role) =>
1543
+ updateAssignment(assignment.collaboratorId, {
1544
+ projectRoleId: role.id
1545
+ ? String(role.id)
1546
+ : 'none',
1547
+ roleLabel: role.name,
1548
+ })
1549
+ }
1550
+ onCreate={createProjectRole}
1551
+ />
1552
+ {roleError?.message ? (
1553
+ <p className="text-sm text-destructive">
1554
+ {String(roleError.message)}
1555
+ </p>
1556
+ ) : null}
1557
+ </div>
1558
+ <Input
1559
+ className="h-9 mt-2 self-start"
1560
+ type="number"
1561
+ min="0"
1562
+ step="0.5"
1563
+ placeholder={t('fields.weeklyHours')}
1564
+ value={assignment.weeklyHours}
1565
+ disabled={!assignment.selected}
1566
+ onChange={(event) => {
1567
+ const hours = event.target.value;
1568
+ const updates: Partial<TeamAssignmentState> = {
1569
+ weeklyHours: hours,
1570
+ };
1571
+ const cap = collaborator.weeklyCapacityHours;
1572
+ if (cap && hours && Number(hours) > 0) {
1573
+ const pct = Math.round(
1574
+ (Number(hours) / cap) * 100
1575
+ );
1576
+ updates.allocationPercent = String(
1577
+ Math.min(pct, 100)
1578
+ );
1579
+ }
1580
+ updateAssignment(
1581
+ assignment.collaboratorId,
1582
+ updates
1583
+ );
1584
+ }}
1585
+ />
1586
+ <Input
1587
+ className="h-9 mt-2 self-start"
1588
+ type="text"
1589
+ inputMode="decimal"
1590
+ placeholder={t('fields.allocationPercent')}
1591
+ value={assignment.allocationPercent}
1592
+ disabled={!assignment.selected}
1593
+ onChange={(event) => {
1594
+ const pct = normalizePercentInput(
1595
+ event.target.value
1596
+ );
1597
+ const updates: Partial<TeamAssignmentState> = {
1598
+ allocationPercent: pct,
1599
+ };
1600
+ const cap = collaborator.weeklyCapacityHours;
1601
+ if (cap && pct && Number(pct) > 0) {
1602
+ const hours = Math.round(
1603
+ (Number(pct) / 100) * cap
1604
+ );
1605
+ updates.weeklyHours = String(hours);
1606
+ }
1607
+ updateAssignment(
1608
+ assignment.collaboratorId,
1609
+ updates
1610
+ );
1611
+ }}
1612
+ />
1613
+ <div className="flex items-center gap-2 xl:col-span-4">
1614
+ <div className="flex-1">
1615
+ <label className="text-xs text-muted-foreground">{t('fields.assignmentStartDate')}</label>
1616
+ <Input
1617
+ className="h-9"
1618
+ type="date"
1619
+ value={assignment.startDate}
1620
+ disabled={!assignment.selected}
1621
+ onChange={(event) =>
1622
+ updateAssignment(assignment.collaboratorId, {
1623
+ startDate: event.target.value,
1624
+ })
1625
+ }
1626
+ />
1627
+ </div>
1628
+ <div className="flex-1">
1629
+ <label className="text-xs text-muted-foreground">{t('fields.assignmentEndDate')}</label>
1630
+ <Input
1631
+ className="h-9"
1632
+ type="date"
1633
+ value={assignment.endDate}
1634
+ disabled={!assignment.selected}
1635
+ onChange={(event) =>
1636
+ updateAssignment(assignment.collaboratorId, {
1637
+ endDate: event.target.value,
1638
+ })
1639
+ }
1640
+ />
1641
+ </div>
1642
+ </div>
1643
+ </div>
1644
+ );
1645
+ })}
1646
+ </div>
1647
+ </div>
1648
+ </section>
1649
+ </>
1650
+ ) : (
1651
+ <section className="space-y-3 rounded-lg border border-dashed bg-muted/20 px-4 py-4">
1652
+ <div className="space-y-0.5">
1653
+ <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
1654
+ {t('sections.nextSteps')}
1655
+ </h3>
1656
+ <p className="text-[11px] text-muted-foreground/80">
1657
+ {t('sections.nextStepsDescription')}
1658
+ </p>
1659
+ </div>
1660
+ </section>
1661
+ )}
1662
+ </form>
1663
+ </Form>
1664
+ );
1665
+ const loadingState =
1666
+ projectId && isLoadingProject ? (
1667
+ <div className="text-sm text-muted-foreground">{t('loading')}</div>
1668
+ ) : null;
1669
+
1670
+ const contractStatusState = project ? (
1671
+ <div className="text-xs text-muted-foreground">
1672
+ {t('messages.currentContractStatus', {
1673
+ status: project.contractStatus
1674
+ ? project.contractStatus
1675
+ : commonT('labels.notAssigned'),
1676
+ })}
1677
+ </div>
1678
+ ) : null;
1679
+
1680
+ if (isSheetMode) {
1681
+ return (
1682
+ <div className="mt-6 space-y-4 pb-6">
1683
+ {formContent}
1684
+ <div className="space-y-2 px-4">
1685
+ {loadingState}
1686
+ {contractStatusState}
1687
+ </div>
1688
+
1689
+ <FormActions
1690
+ sheet
1691
+ cancelLabel={commonT('actions.cancel')}
1692
+ onCancel={onCancel}
1693
+ onSubmit={() =>
1694
+ void formMethods.handleSubmit(onSubmit, handleInvalidSubmit)()
1695
+ }
1696
+ submitIcon={<Save className="size-4" />}
1697
+ submitLabel={commonT('actions.save')}
1698
+ submitSize="lg"
1699
+ />
1700
+ </div>
1701
+ );
1702
+ }
1703
+
1704
+ return (
1705
+ <Page>
1706
+ <OperationsHeader
1707
+ title={t(projectId ? 'editTitle' : 'newTitle')}
1708
+ description={t('description')}
1709
+ current={t('breadcrumb')}
1710
+ actions={
1711
+ <div className="flex gap-2">
1712
+ <Button variant="outline" size="sm" asChild>
1713
+ <Link
1714
+ href={
1715
+ projectId
1716
+ ? `/operations/projects/${projectId}`
1717
+ : '/operations/projects'
1718
+ }
1719
+ >
1720
+ <ArrowLeft className="size-4" />
1721
+ {commonT('actions.back')}
1722
+ </Link>
1723
+ </Button>
1724
+ <Button
1725
+ size="sm"
1726
+ type="button"
1727
+ onClick={() =>
1728
+ void formMethods.handleSubmit(onSubmit, handleInvalidSubmit)()
1729
+ }
1730
+ >
1731
+ <Save className="size-4" />
1732
+ {commonT('actions.save')}
1733
+ </Button>
1734
+ </div>
1735
+ }
1736
+ />
1737
+
1738
+ {formContent}
1739
+ <div className="space-y-2">
1740
+ {loadingState}
1741
+ {contractStatusState}
1742
+ </div>
1743
+ </Page>
1744
+ );
1745
+ }