@hed-hog/operations 0.0.322 → 0.0.326

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 (694) hide show
  1. package/dist/controllers/operations-collaborators.controller.d.ts +14 -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 +571 -1
  77. package/dist/operations.service.d.ts.map +1 -1
  78. package/dist/operations.service.js +1793 -69
  79. package/dist/operations.service.js.map +1 -1
  80. package/hedhog/data/integration_event_catalog.yaml +313 -0
  81. package/hedhog/data/menu.yaml +52 -0
  82. package/hedhog/data/operations_project_cost_category.yaml +80 -0
  83. package/hedhog/data/operations_project_cost_type.yaml +503 -0
  84. package/hedhog/data/route.yaml +274 -0
  85. package/hedhog/data/setting_group.yaml +21 -0
  86. package/hedhog/frontend/app/_components/collaborator-costs-section.tsx.ejs +2 -18
  87. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +593 -297
  88. package/hedhog/frontend/app/_components/collaborator-tasks-tab.tsx.ejs +358 -0
  89. package/hedhog/frontend/app/_components/collaborator-timesheets-tab.tsx.ejs +242 -0
  90. package/hedhog/frontend/app/_components/my-project-summary-screen.tsx.ejs +533 -296
  91. package/hedhog/frontend/app/_components/person-select-with-create.tsx.ejs +1 -853
  92. package/hedhog/frontend/app/_components/project-assignments-tab.tsx.ejs +450 -0
  93. package/hedhog/frontend/app/_components/project-cost-report-screen.tsx.ejs +602 -0
  94. package/hedhog/frontend/app/_components/project-costs-section.tsx.ejs +1401 -0
  95. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +2248 -2063
  96. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +56 -11
  97. package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +454 -96
  98. package/hedhog/frontend/app/_components/task-form-sheet.tsx.ejs +784 -0
  99. package/hedhog/frontend/app/_lib/api.ts.ejs +256 -0
  100. package/hedhog/frontend/app/_lib/hooks/use-mention-items.ts.ejs +28 -0
  101. package/hedhog/frontend/app/_lib/types.ts.ejs +190 -0
  102. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +9 -3
  103. package/hedhog/frontend/app/collaborators/page.tsx.ejs +18 -7
  104. package/hedhog/frontend/app/my-tasks/page.tsx.ejs +536 -328
  105. package/hedhog/frontend/app/project-cost-categories/page.tsx.ejs +674 -0
  106. package/hedhog/frontend/app/project-cost-types/page.tsx.ejs +845 -0
  107. package/hedhog/frontend/app/projects/[id]/costs-report/page.tsx.ejs +10 -0
  108. package/hedhog/frontend/app/reports/collaborators/page.tsx.ejs +20 -349
  109. package/hedhog/frontend/app/reports/projects/page.tsx.ejs +217 -485
  110. package/hedhog/frontend/messages/en.json +257 -5
  111. package/hedhog/frontend/messages/en.json.ejs +2060 -0
  112. package/hedhog/frontend/messages/operations/en.json +2068 -0
  113. package/hedhog/frontend/messages/operations/operations/en.json +2102 -0
  114. package/hedhog/frontend/messages/operations/operations/pt.json +2111 -0
  115. package/hedhog/frontend/messages/operations/pt.json +2072 -0
  116. package/hedhog/frontend/messages/pt.json +256 -4
  117. package/hedhog/frontend/messages/pt.json.ejs +2067 -0
  118. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.d.ts +29 -0
  119. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.d.ts.map +1 -0
  120. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.js +95 -0
  121. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.js.map +1 -0
  122. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/async-options-combobox.tsx +233 -0
  123. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.d.ts +10 -0
  124. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.d.ts.map +1 -0
  125. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.js +577 -0
  126. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.js.map +1 -0
  127. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-costs-section.tsx +868 -0
  128. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.d.ts +4 -0
  129. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.d.ts.map +1 -0
  130. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.js +337 -0
  131. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.js.map +1 -0
  132. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-details-screen.tsx +476 -0
  133. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.d.ts +9 -0
  134. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.d.ts.map +1 -0
  135. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.js +1348 -0
  136. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.js.map +1 -0
  137. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-form-screen.tsx +2233 -0
  138. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.d.ts +12 -0
  139. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.d.ts.map +1 -0
  140. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.js +162 -0
  141. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.js.map +1 -0
  142. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/collaborator-select-with-create.tsx +261 -0
  143. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.d.ts +18 -0
  144. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.d.ts.map +1 -0
  145. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.js +145 -0
  146. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.js.map +1 -0
  147. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-content-editor.tsx +258 -0
  148. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.d.ts +4 -0
  149. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.d.ts.map +1 -0
  150. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.js +223 -0
  151. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.js.map +1 -0
  152. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-details-screen.tsx +342 -0
  153. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.d.ts +58 -0
  154. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.d.ts.map +1 -0
  155. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.js +438 -0
  156. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.js.map +1 -0
  157. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/contract-form-screen.tsx +698 -0
  158. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.d.ts +20 -0
  159. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.d.ts.map +1 -0
  160. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.js +233 -0
  161. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.js.map +1 -0
  162. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/department-select-with-create.tsx +392 -0
  163. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.d.ts +4 -0
  164. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.d.ts.map +1 -0
  165. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.js +814 -0
  166. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.js.map +1 -0
  167. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/my-project-summary-screen.tsx +1288 -0
  168. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.d.ts +21 -0
  169. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.d.ts.map +1 -0
  170. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.js +174 -0
  171. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.js.map +1 -0
  172. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-calendar-view.tsx +306 -0
  173. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.d.ts +10 -0
  174. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.d.ts.map +1 -0
  175. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.js +12 -0
  176. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.js.map +1 -0
  177. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/operations-header.tsx +29 -0
  178. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.d.ts +15 -0
  179. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.d.ts.map +1 -0
  180. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.js +501 -0
  181. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.js.map +1 -0
  182. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/person-select-with-create.tsx +853 -0
  183. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.d.ts +6 -0
  184. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.d.ts.map +1 -0
  185. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.js +847 -0
  186. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.js.map +1 -0
  187. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-costs-section.tsx +1340 -0
  188. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.d.ts +4 -0
  189. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.d.ts.map +1 -0
  190. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.js +2930 -0
  191. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.js.map +1 -0
  192. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-details-screen.tsx +4378 -0
  193. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.d.ts +9 -0
  194. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.d.ts.map +1 -0
  195. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.js +1013 -0
  196. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.js.map +1 -0
  197. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/project-form-screen.tsx +1745 -0
  198. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.d.ts +13 -0
  199. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.d.ts.map +1 -0
  200. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.js +38 -0
  201. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.js.map +1 -0
  202. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/section-card.tsx +74 -0
  203. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.d.ts +7 -0
  204. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.d.ts.map +1 -0
  205. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.js +11 -0
  206. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.js.map +1 -0
  207. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/status-badge.tsx +15 -0
  208. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.d.ts +18 -0
  209. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.d.ts.map +1 -0
  210. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.js +406 -0
  211. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.js.map +1 -0
  212. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/system-user-select-with-create.tsx +660 -0
  213. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.d.ts +26 -0
  214. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.d.ts.map +1 -0
  215. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.js +332 -0
  216. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.js.map +1 -0
  217. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-detail-sheet.tsx +518 -0
  218. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.d.ts +6 -0
  219. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.d.ts.map +1 -0
  220. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.js +255 -0
  221. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.js.map +1 -0
  222. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/task-file-attachments.tsx +388 -0
  223. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.d.ts +10 -0
  224. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.d.ts.map +1 -0
  225. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.js +131 -0
  226. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.js.map +1 -0
  227. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_components/timesheet-task-create-sheet.tsx +214 -0
  228. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.d.ts +108 -0
  229. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.d.ts.map +1 -0
  230. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.js +162 -0
  231. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.js.map +1 -0
  232. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/api.ts +428 -0
  233. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.d.ts +8 -0
  234. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.d.ts.map +1 -0
  235. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.js +36 -0
  236. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.js.map +1 -0
  237. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/hooks/use-operations-access.ts +44 -0
  238. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts +837 -0
  239. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts.map +1 -0
  240. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.js +3 -0
  241. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.js.map +1 -0
  242. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.ts +861 -0
  243. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.d.ts +16 -0
  244. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.d.ts.map +1 -0
  245. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.js +182 -0
  246. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.js.map +1 -0
  247. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/format.ts +250 -0
  248. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.d.ts +4 -0
  249. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.d.ts.map +1 -0
  250. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.js +51 -0
  251. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.js.map +1 -0
  252. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/utils/forms.ts +61 -0
  253. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.d.ts +2 -0
  254. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.d.ts.map +1 -0
  255. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.js +954 -0
  256. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.js.map +1 -0
  257. package/hedhog/frontend/src/app/(app)/(libraries)/operations/approvals/page.tsx +1277 -0
  258. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.d.ts +2 -0
  259. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.d.ts.map +1 -0
  260. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.js +488 -0
  261. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.js.map +1 -0
  262. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborator-types/page.tsx +805 -0
  263. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.d.ts +6 -0
  264. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.d.ts.map +1 -0
  265. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.js +9 -0
  266. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.js.map +1 -0
  267. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/edit/page.tsx +11 -0
  268. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.d.ts +6 -0
  269. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.d.ts.map +1 -0
  270. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.js +9 -0
  271. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.js.map +1 -0
  272. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/[id]/page.tsx +11 -0
  273. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.d.ts +2 -0
  274. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.d.ts.map +1 -0
  275. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.js +8 -0
  276. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.js.map +1 -0
  277. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/new/page.tsx +5 -0
  278. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.d.ts +2 -0
  279. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.d.ts.map +1 -0
  280. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.js +612 -0
  281. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.js.map +1 -0
  282. package/hedhog/frontend/src/app/(app)/(libraries)/operations/collaborators/page.tsx +939 -0
  283. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.d.ts +6 -0
  284. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.d.ts.map +1 -0
  285. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.js +9 -0
  286. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.js.map +1 -0
  287. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/edit/page.tsx +11 -0
  288. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.d.ts +6 -0
  289. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.d.ts.map +1 -0
  290. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.js +9 -0
  291. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.js.map +1 -0
  292. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/[id]/page.tsx +11 -0
  293. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.d.ts +6 -0
  294. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.d.ts.map +1 -0
  295. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.js +9 -0
  296. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.js.map +1 -0
  297. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/new/page.tsx +17 -0
  298. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.d.ts +2 -0
  299. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.d.ts.map +1 -0
  300. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.js +348 -0
  301. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.js.map +1 -0
  302. package/hedhog/frontend/src/app/(app)/(libraries)/operations/contracts/page.tsx +536 -0
  303. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.d.ts +2 -0
  304. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.d.ts.map +1 -0
  305. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.js +401 -0
  306. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.js.map +1 -0
  307. package/hedhog/frontend/src/app/(app)/(libraries)/operations/departments/page.tsx +607 -0
  308. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.d.ts +5 -0
  309. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.d.ts.map +1 -0
  310. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.js +7 -0
  311. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.js.map +1 -0
  312. package/hedhog/frontend/src/app/(app)/(libraries)/operations/layout.tsx +9 -0
  313. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.d.ts +6 -0
  314. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.d.ts.map +1 -0
  315. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.js +9 -0
  316. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.js.map +1 -0
  317. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/[id]/page.tsx +11 -0
  318. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.d.ts +2 -0
  319. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.d.ts.map +1 -0
  320. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.js +321 -0
  321. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.js.map +1 -0
  322. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-projects/page.tsx +440 -0
  323. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.d.ts +2 -0
  324. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.d.ts.map +1 -0
  325. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.js +939 -0
  326. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.js.map +1 -0
  327. package/hedhog/frontend/src/app/(app)/(libraries)/operations/my-tasks/page.tsx +1499 -0
  328. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.d.ts +29 -0
  329. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.d.ts.map +1 -0
  330. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.js +95 -0
  331. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.js.map +1 -0
  332. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/async-options-combobox.tsx +233 -0
  333. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.d.ts +10 -0
  334. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.d.ts.map +1 -0
  335. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.js +577 -0
  336. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.js.map +1 -0
  337. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-costs-section.tsx +868 -0
  338. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.d.ts +4 -0
  339. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.d.ts.map +1 -0
  340. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.js +337 -0
  341. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.js.map +1 -0
  342. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-details-screen.tsx +476 -0
  343. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.d.ts +9 -0
  344. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.d.ts.map +1 -0
  345. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.js +1348 -0
  346. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.js.map +1 -0
  347. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-form-screen.tsx +2233 -0
  348. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.d.ts +12 -0
  349. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.d.ts.map +1 -0
  350. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.js +162 -0
  351. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.js.map +1 -0
  352. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/collaborator-select-with-create.tsx +261 -0
  353. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.d.ts +18 -0
  354. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.d.ts.map +1 -0
  355. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.js +145 -0
  356. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.js.map +1 -0
  357. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-content-editor.tsx +258 -0
  358. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.d.ts +4 -0
  359. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.d.ts.map +1 -0
  360. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.js +223 -0
  361. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.js.map +1 -0
  362. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-details-screen.tsx +342 -0
  363. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.d.ts +58 -0
  364. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.d.ts.map +1 -0
  365. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.js +438 -0
  366. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.js.map +1 -0
  367. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/contract-form-screen.tsx +698 -0
  368. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.d.ts +20 -0
  369. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.d.ts.map +1 -0
  370. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.js +233 -0
  371. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.js.map +1 -0
  372. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/department-select-with-create.tsx +392 -0
  373. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.d.ts +4 -0
  374. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.d.ts.map +1 -0
  375. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.js +814 -0
  376. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.js.map +1 -0
  377. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/my-project-summary-screen.tsx +1288 -0
  378. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.d.ts +21 -0
  379. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.d.ts.map +1 -0
  380. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.js +174 -0
  381. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.js.map +1 -0
  382. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-calendar-view.tsx +306 -0
  383. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.d.ts +10 -0
  384. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.d.ts.map +1 -0
  385. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.js +12 -0
  386. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.js.map +1 -0
  387. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/operations-header.tsx +29 -0
  388. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.d.ts +15 -0
  389. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.d.ts.map +1 -0
  390. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.js +501 -0
  391. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.js.map +1 -0
  392. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/person-select-with-create.tsx +853 -0
  393. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.d.ts +6 -0
  394. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.d.ts.map +1 -0
  395. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.js +459 -0
  396. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.js.map +1 -0
  397. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-cost-report-screen.tsx +598 -0
  398. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.d.ts +6 -0
  399. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.d.ts.map +1 -0
  400. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.js +876 -0
  401. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.js.map +1 -0
  402. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-costs-section.tsx +1368 -0
  403. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.d.ts +4 -0
  404. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.d.ts.map +1 -0
  405. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.js +2930 -0
  406. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.js.map +1 -0
  407. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-details-screen.tsx +4378 -0
  408. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.d.ts +9 -0
  409. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.d.ts.map +1 -0
  410. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.js +1013 -0
  411. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.js.map +1 -0
  412. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/project-form-screen.tsx +1745 -0
  413. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.d.ts +13 -0
  414. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.d.ts.map +1 -0
  415. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.js +38 -0
  416. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.js.map +1 -0
  417. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/section-card.tsx +74 -0
  418. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.d.ts +7 -0
  419. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.d.ts.map +1 -0
  420. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.js +11 -0
  421. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.js.map +1 -0
  422. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/status-badge.tsx +15 -0
  423. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.d.ts +18 -0
  424. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.d.ts.map +1 -0
  425. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.js +406 -0
  426. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.js.map +1 -0
  427. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/system-user-select-with-create.tsx +660 -0
  428. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.d.ts +26 -0
  429. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.d.ts.map +1 -0
  430. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.js +332 -0
  431. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.js.map +1 -0
  432. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-detail-sheet.tsx +518 -0
  433. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.d.ts +6 -0
  434. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.d.ts.map +1 -0
  435. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.js +255 -0
  436. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.js.map +1 -0
  437. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/task-file-attachments.tsx +388 -0
  438. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.d.ts +10 -0
  439. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.d.ts.map +1 -0
  440. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.js +131 -0
  441. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.js.map +1 -0
  442. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_components/timesheet-task-create-sheet.tsx +214 -0
  443. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.d.ts +108 -0
  444. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.d.ts.map +1 -0
  445. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.js +162 -0
  446. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.js.map +1 -0
  447. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/api.ts +428 -0
  448. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.d.ts +8 -0
  449. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.d.ts.map +1 -0
  450. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.js +36 -0
  451. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.js.map +1 -0
  452. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/hooks/use-operations-access.ts +44 -0
  453. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts +837 -0
  454. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts.map +1 -0
  455. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.js +3 -0
  456. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.js.map +1 -0
  457. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.ts +861 -0
  458. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.d.ts +16 -0
  459. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.d.ts.map +1 -0
  460. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.js +182 -0
  461. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.js.map +1 -0
  462. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/format.ts +250 -0
  463. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.d.ts +4 -0
  464. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.d.ts.map +1 -0
  465. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.js +51 -0
  466. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.js.map +1 -0
  467. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/utils/forms.ts +61 -0
  468. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.d.ts +2 -0
  469. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.d.ts.map +1 -0
  470. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.js +954 -0
  471. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.js.map +1 -0
  472. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/approvals/page.tsx +1277 -0
  473. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.d.ts +2 -0
  474. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.d.ts.map +1 -0
  475. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.js +488 -0
  476. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.js.map +1 -0
  477. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborator-types/page.tsx +805 -0
  478. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.d.ts +6 -0
  479. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.d.ts.map +1 -0
  480. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.js +9 -0
  481. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.js.map +1 -0
  482. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/edit/page.tsx +11 -0
  483. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.d.ts +6 -0
  484. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.d.ts.map +1 -0
  485. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.js +9 -0
  486. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.js.map +1 -0
  487. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/[id]/page.tsx +11 -0
  488. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.d.ts +2 -0
  489. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.d.ts.map +1 -0
  490. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.js +8 -0
  491. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.js.map +1 -0
  492. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/new/page.tsx +5 -0
  493. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.d.ts +2 -0
  494. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.d.ts.map +1 -0
  495. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.js +612 -0
  496. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.js.map +1 -0
  497. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/collaborators/page.tsx +939 -0
  498. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.d.ts +6 -0
  499. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.d.ts.map +1 -0
  500. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.js +9 -0
  501. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.js.map +1 -0
  502. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/edit/page.tsx +11 -0
  503. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.d.ts +6 -0
  504. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.d.ts.map +1 -0
  505. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.js +9 -0
  506. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.js.map +1 -0
  507. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/[id]/page.tsx +11 -0
  508. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.d.ts +6 -0
  509. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.d.ts.map +1 -0
  510. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.js +9 -0
  511. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.js.map +1 -0
  512. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/new/page.tsx +17 -0
  513. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.d.ts +2 -0
  514. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.d.ts.map +1 -0
  515. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.js +348 -0
  516. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.js.map +1 -0
  517. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/contracts/page.tsx +536 -0
  518. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.d.ts +2 -0
  519. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.d.ts.map +1 -0
  520. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.js +401 -0
  521. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.js.map +1 -0
  522. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/departments/page.tsx +607 -0
  523. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.d.ts +5 -0
  524. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.d.ts.map +1 -0
  525. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.js +7 -0
  526. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.js.map +1 -0
  527. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/layout.tsx +9 -0
  528. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.d.ts +6 -0
  529. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.d.ts.map +1 -0
  530. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.js +9 -0
  531. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.js.map +1 -0
  532. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/[id]/page.tsx +11 -0
  533. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.d.ts +2 -0
  534. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.d.ts.map +1 -0
  535. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.js +321 -0
  536. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.js.map +1 -0
  537. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-projects/page.tsx +440 -0
  538. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.d.ts +2 -0
  539. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.d.ts.map +1 -0
  540. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.js +939 -0
  541. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.js.map +1 -0
  542. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/my-tasks/page.tsx +1499 -0
  543. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.d.ts +2 -0
  544. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.d.ts.map +1 -0
  545. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.js +8 -0
  546. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.js.map +1 -0
  547. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/page.tsx +5 -0
  548. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.d.ts +2 -0
  549. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.d.ts.map +1 -0
  550. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.js +436 -0
  551. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.js.map +1 -0
  552. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-categories/page.tsx +675 -0
  553. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.d.ts +2 -0
  554. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.d.ts.map +1 -0
  555. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.js +563 -0
  556. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.js.map +1 -0
  557. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/project-cost-types/page.tsx +846 -0
  558. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.d.ts +6 -0
  559. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.d.ts.map +1 -0
  560. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.js +9 -0
  561. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.js.map +1 -0
  562. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/costs-report/page.tsx +10 -0
  563. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.d.ts +6 -0
  564. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.d.ts.map +1 -0
  565. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.js +9 -0
  566. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.js.map +1 -0
  567. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/edit/page.tsx +11 -0
  568. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.d.ts +6 -0
  569. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.d.ts.map +1 -0
  570. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.js +9 -0
  571. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.js.map +1 -0
  572. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/[id]/page.tsx +11 -0
  573. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.d.ts +2 -0
  574. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.d.ts.map +1 -0
  575. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.js +8 -0
  576. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.js.map +1 -0
  577. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/new/page.tsx +5 -0
  578. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.d.ts +2 -0
  579. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.d.ts.map +1 -0
  580. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.js +492 -0
  581. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.js.map +1 -0
  582. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/projects/page.tsx +757 -0
  583. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.d.ts +2 -0
  584. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.d.ts.map +1 -0
  585. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.js +342 -0
  586. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.js.map +1 -0
  587. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/collaborators/page.tsx +430 -0
  588. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.d.ts +2 -0
  589. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.d.ts.map +1 -0
  590. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.js +338 -0
  591. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.js.map +1 -0
  592. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/reports/projects/page.tsx +428 -0
  593. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.d.ts +2 -0
  594. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.d.ts.map +1 -0
  595. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.js +660 -0
  596. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.js.map +1 -0
  597. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/schedule-adjustments/page.tsx +992 -0
  598. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.d.ts +2 -0
  599. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.d.ts.map +1 -0
  600. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.js +515 -0
  601. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.js.map +1 -0
  602. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/time-off/page.tsx +707 -0
  603. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.d.ts +2 -0
  604. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.d.ts.map +1 -0
  605. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.js +1141 -0
  606. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.js.map +1 -0
  607. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/timesheets/page.tsx +1705 -0
  608. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.d.ts +2 -0
  609. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.d.ts.map +1 -0
  610. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.js +8 -0
  611. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.js.map +1 -0
  612. package/hedhog/frontend/src/app/(app)/(libraries)/operations/page.tsx +5 -0
  613. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.d.ts +2 -0
  614. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.d.ts.map +1 -0
  615. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.js +436 -0
  616. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.js.map +1 -0
  617. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-categories/page.tsx +675 -0
  618. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.d.ts +2 -0
  619. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.d.ts.map +1 -0
  620. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.js +563 -0
  621. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.js.map +1 -0
  622. package/hedhog/frontend/src/app/(app)/(libraries)/operations/project-cost-types/page.tsx +846 -0
  623. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.d.ts +6 -0
  624. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.d.ts.map +1 -0
  625. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.js +9 -0
  626. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.js.map +1 -0
  627. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/edit/page.tsx +11 -0
  628. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.d.ts +6 -0
  629. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.d.ts.map +1 -0
  630. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.js +9 -0
  631. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.js.map +1 -0
  632. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/[id]/page.tsx +11 -0
  633. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.d.ts +2 -0
  634. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.d.ts.map +1 -0
  635. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.js +8 -0
  636. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.js.map +1 -0
  637. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/new/page.tsx +5 -0
  638. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.d.ts +2 -0
  639. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.d.ts.map +1 -0
  640. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.js +492 -0
  641. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.js.map +1 -0
  642. package/hedhog/frontend/src/app/(app)/(libraries)/operations/projects/page.tsx +757 -0
  643. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.d.ts +2 -0
  644. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.d.ts.map +1 -0
  645. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.js +342 -0
  646. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.js.map +1 -0
  647. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/collaborators/page.tsx +430 -0
  648. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.d.ts +2 -0
  649. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.d.ts.map +1 -0
  650. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.js +338 -0
  651. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.js.map +1 -0
  652. package/hedhog/frontend/src/app/(app)/(libraries)/operations/reports/projects/page.tsx +428 -0
  653. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.d.ts +2 -0
  654. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.d.ts.map +1 -0
  655. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.js +660 -0
  656. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.js.map +1 -0
  657. package/hedhog/frontend/src/app/(app)/(libraries)/operations/schedule-adjustments/page.tsx +992 -0
  658. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.d.ts +2 -0
  659. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.d.ts.map +1 -0
  660. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.js +515 -0
  661. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.js.map +1 -0
  662. package/hedhog/frontend/src/app/(app)/(libraries)/operations/time-off/page.tsx +707 -0
  663. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.d.ts +2 -0
  664. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.d.ts.map +1 -0
  665. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.js +1141 -0
  666. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.js.map +1 -0
  667. package/hedhog/frontend/src/app/(app)/(libraries)/operations/timesheets/page.tsx +1705 -0
  668. package/hedhog/table/operations_collaborator.yaml +5 -0
  669. package/hedhog/table/operations_collaborator_compensation_history.yaml +4 -0
  670. package/hedhog/table/operations_project_assignment.yaml +1 -0
  671. package/hedhog/table/operations_project_cost.yaml +93 -0
  672. package/hedhog/table/operations_project_cost_category.yaml +37 -0
  673. package/hedhog/table/operations_project_cost_type.yaml +55 -0
  674. package/hedhog/table/operations_task_comment.yaml +26 -0
  675. package/package.json +6 -6
  676. package/src/controllers/operations-collaborators.controller.ts +26 -0
  677. package/src/controllers/operations-project-costs.controller.ts +249 -0
  678. package/src/controllers/operations-tasks.controller.ts +49 -0
  679. package/src/dto/create-collaborator-project-assignment.dto.ts +14 -0
  680. package/src/dto/create-project-cost-category.dto.ts +37 -0
  681. package/src/dto/create-project-cost-type.dto.ts +64 -0
  682. package/src/dto/create-project-cost.dto.ts +126 -0
  683. package/src/dto/get-project-cost-report.dto.ts +46 -0
  684. package/src/dto/list-project-cost-categories.dto.ts +17 -0
  685. package/src/dto/list-project-cost-types.dto.ts +28 -0
  686. package/src/dto/list-project-costs.dto.ts +59 -0
  687. package/src/dto/list-tasks.dto.ts +7 -0
  688. package/src/dto/list-timesheets.dto.ts +7 -1
  689. package/src/dto/update-collaborator-project-assignment.dto.ts +58 -0
  690. package/src/dto/update-project-cost-category.dto.ts +4 -0
  691. package/src/dto/update-project-cost-type.dto.ts +4 -0
  692. package/src/dto/update-project-cost.dto.ts +4 -0
  693. package/src/operations.module.ts +2 -0
  694. package/src/operations.service.ts +2472 -61
@@ -0,0 +1,1705 @@
1
+ 'use client';
2
+
3
+ import {
4
+ EmptyState,
5
+ Page,
6
+ PaginationFooter,
7
+ SearchBar,
8
+ } from '@/components/entity-list';
9
+ import {
10
+ AlertDialog,
11
+ AlertDialogAction,
12
+ AlertDialogCancel,
13
+ AlertDialogContent,
14
+ AlertDialogDescription,
15
+ AlertDialogFooter,
16
+ AlertDialogHeader,
17
+ AlertDialogTitle,
18
+ } from '@/components/ui/alert-dialog';
19
+ import { Button } from '@/components/ui/button';
20
+ import {
21
+ Form,
22
+ FormControl,
23
+ FormField,
24
+ FormItem,
25
+ FormLabel,
26
+ FormMessage,
27
+ } from '@/components/ui/form';
28
+ import { FormActions } from '@/components/ui/form-actions';
29
+ import { Input } from '@/components/ui/input';
30
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
31
+ import {
32
+ Sheet,
33
+ SheetContent,
34
+ SheetDescription,
35
+ SheetHeader,
36
+ SheetTitle,
37
+ } from '@/components/ui/sheet';
38
+ import { Switch } from '@/components/ui/switch';
39
+ import {
40
+ Table,
41
+ TableBody,
42
+ TableCell,
43
+ TableHead,
44
+ TableHeader,
45
+ TableRow,
46
+ } from '@/components/ui/table';
47
+ import { Textarea } from '@/components/ui/textarea';
48
+ import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
49
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
50
+ import { zodResolver } from '@hookform/resolvers/zod';
51
+ import {
52
+ CalendarDays,
53
+ ClipboardList,
54
+ Clock3,
55
+ Eye,
56
+ LayoutGrid,
57
+ List,
58
+ Loader2,
59
+ Pencil,
60
+ Plus,
61
+ Send,
62
+ Trash2,
63
+ } from 'lucide-react';
64
+ import { useTranslations } from 'next-intl';
65
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
66
+ import { useForm, useWatch } from 'react-hook-form';
67
+ import { z } from 'zod';
68
+
69
+ import { AsyncOptionsCombobox } from '../_components/async-options-combobox';
70
+ import {
71
+ OperationsCalendarView,
72
+ type OperationsCalendarItem,
73
+ } from '../_components/operations-calendar-view';
74
+ import { OperationsHeader } from '../_components/operations-header';
75
+ import { StatusBadge } from '../_components/status-badge';
76
+ import { TimesheetTaskCreateSheet } from '../_components/timesheet-task-create-sheet';
77
+ import {
78
+ fetchOperations,
79
+ getOperationsErrorMessage,
80
+ mutateOperations,
81
+ } from '../_lib/api';
82
+ import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
83
+ import type {
84
+ OperationsCollaborator,
85
+ OperationsProjectOption,
86
+ OperationsTaskOption,
87
+ OperationsTimesheet,
88
+ OperationsTimesheetEntry,
89
+ PaginatedResponse,
90
+ } from '../_lib/types';
91
+ import {
92
+ formatDate,
93
+ formatEnumLabel,
94
+ formatHours,
95
+ getStatusBadgeClass,
96
+ } from '../_lib/utils/format';
97
+ import { trimToNull } from '../_lib/utils/forms';
98
+
99
+ type QuickEntryFormValues = {
100
+ projectId?: number;
101
+ taskId?: number;
102
+ workDate: string;
103
+ duration?: number;
104
+ unit: 'hours' | 'minutes';
105
+ description: string;
106
+ };
107
+
108
+ const getTodayDate = () => {
109
+ const now = new Date();
110
+ return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
111
+ };
112
+
113
+ const buildDefaultFormValues = (): QuickEntryFormValues => ({
114
+ projectId: undefined,
115
+ taskId: undefined,
116
+ workDate: getTodayDate(),
117
+ duration: undefined,
118
+ unit: 'hours',
119
+ description: '',
120
+ });
121
+
122
+ const positiveNumberField = (message: string) =>
123
+ z.preprocess(
124
+ (value) => {
125
+ if (value === '' || value === null || value === undefined) {
126
+ return undefined;
127
+ }
128
+
129
+ if (typeof value === 'number') {
130
+ return value;
131
+ }
132
+
133
+ const parsed = Number(value);
134
+ return Number.isNaN(parsed) ? value : parsed;
135
+ },
136
+ z.number({ required_error: message }).positive(message)
137
+ );
138
+
139
+ function appendUniqueById<T extends { id: number | string }>(
140
+ current: T[],
141
+ next: T[]
142
+ ) {
143
+ const unique = new Map<string, T>();
144
+
145
+ [...current, ...next].forEach((item) => {
146
+ unique.set(String(item.id), item);
147
+ });
148
+
149
+ return Array.from(unique.values());
150
+ }
151
+
152
+ function formatDateLabel(value?: string | null) {
153
+ if (!value) {
154
+ return '—';
155
+ }
156
+
157
+ // Always extract just the YYYY-MM-DD part to avoid UTC offset shifting the date
158
+ const match = String(value).match(/(\d{4}-\d{2}-\d{2})/);
159
+ if (!match) {
160
+ return value;
161
+ }
162
+
163
+ const date = new Date(`${match[1]}T12:00:00`);
164
+
165
+ if (Number.isNaN(date.getTime())) {
166
+ return value;
167
+ }
168
+
169
+ return new Intl.DateTimeFormat(undefined, {
170
+ day: '2-digit',
171
+ month: 'short',
172
+ year: 'numeric',
173
+ }).format(date);
174
+ }
175
+
176
+ function formatEntryDuration(minutes?: number | null, hours?: number | null) {
177
+ if (typeof minutes === 'number' && Number.isFinite(minutes) && minutes > 0) {
178
+ const wholeHours = Math.floor(minutes / 60);
179
+ const remainingMinutes = minutes % 60;
180
+
181
+ if (!wholeHours) {
182
+ return `${remainingMinutes}m`;
183
+ }
184
+
185
+ if (!remainingMinutes) {
186
+ return `${wholeHours}h`;
187
+ }
188
+
189
+ return `${wholeHours}h ${remainingMinutes}m`;
190
+ }
191
+
192
+ return formatHours(Number(hours ?? 0));
193
+ }
194
+
195
+ function buildFollowUpFormValues(
196
+ current: QuickEntryFormValues,
197
+ keepContextOnSave: boolean
198
+ ): QuickEntryFormValues {
199
+ if (!keepContextOnSave) {
200
+ return buildDefaultFormValues();
201
+ }
202
+
203
+ return {
204
+ projectId: current.projectId,
205
+ taskId: current.taskId,
206
+ workDate: current.workDate || getTodayDate(),
207
+ duration: 0,
208
+ unit: current.unit ?? 'hours',
209
+ description: '',
210
+ };
211
+ }
212
+
213
+ function buildEntryFormValues(
214
+ entry: OperationsTimesheetEntry
215
+ ): QuickEntryFormValues {
216
+ return {
217
+ projectId: entry.projectId ?? undefined,
218
+ taskId: entry.taskId ?? undefined,
219
+ workDate: String(entry.workDate).match(/(\d{4}-\d{2}-\d{2})/)?.[1] ?? '',
220
+ duration:
221
+ typeof entry.durationMinutes === 'number' && entry.durationMinutes > 0
222
+ ? Number((entry.durationMinutes / 60).toFixed(2))
223
+ : Number(entry.hours ?? 0),
224
+ unit: 'hours',
225
+ description: entry.description ?? '',
226
+ };
227
+ }
228
+
229
+ export default function OperationsTimesheetsPage() {
230
+ const t = useTranslations('operations.TimesheetsPage');
231
+ const commonT = useTranslations('operations.Common');
232
+ const { request, showToastHandler, currentLocaleCode } = useApp();
233
+ const access = useOperationsAccess();
234
+ const [search, setSearch] = useState('');
235
+ const [statusFilter, setStatusFilter] = useState('all');
236
+ const [dateFrom, setDateFrom] = useState('');
237
+ const [dateTo, setDateTo] = useState('');
238
+ const [calendarYear, setCalendarYear] = useState(() =>
239
+ new Date().getFullYear()
240
+ );
241
+ const [calendarMonth, setCalendarMonth] = useState(
242
+ () => new Date().getMonth() + 1
243
+ );
244
+ const [page, setPage] = useState(1);
245
+ const [pageSize, setPageSize] = useState(12);
246
+ const [viewMode, setViewMode] = useState<'table' | 'cards' | 'calendar'>(
247
+ () => {
248
+ if (typeof window === 'undefined') return 'table';
249
+ const saved = window.localStorage.getItem(
250
+ 'operations-timesheets-view-mode'
251
+ );
252
+ return saved === 'cards' || saved === 'calendar' ? saved : 'table';
253
+ }
254
+ );
255
+ const [isSheetOpen, setIsSheetOpen] = useState(false);
256
+ const [isDetailsOpen, setIsDetailsOpen] = useState(false);
257
+ const [isTaskCreateSheetOpen, setIsTaskCreateSheetOpen] = useState(false);
258
+ const [keepContextOnSave, setKeepContextOnSave] = useState(true);
259
+ const [editingEntry, setEditingEntry] =
260
+ useState<OperationsTimesheetEntry | null>(null);
261
+ const [entryToDelete, setEntryToDelete] =
262
+ useState<OperationsTimesheetEntry | null>(null);
263
+ const [selectedTimesheet, setSelectedTimesheet] =
264
+ useState<OperationsTimesheet | null>(null);
265
+ const [isDeletingEntry, setIsDeletingEntry] = useState(false);
266
+ const [projectQuery, setProjectQuery] = useState({ search: '', page: 1 });
267
+ const [projectOptions, setProjectOptions] = useState<
268
+ OperationsProjectOption[]
269
+ >([]);
270
+ const [taskQuery, setTaskQuery] = useState({ search: '', page: 1 });
271
+ const [taskRefreshKey, setTaskRefreshKey] = useState(0);
272
+ const [taskOptions, setTaskOptions] = useState<OperationsTaskOption[]>([]);
273
+ const previousProjectIdRef = useRef<number | undefined>(undefined);
274
+
275
+ const quickEntrySchema = useMemo(
276
+ () =>
277
+ z.object({
278
+ projectId: positiveNumberField(t('messages.selectProjectRequired')),
279
+ taskId: positiveNumberField(t('messages.selectTaskRequired')),
280
+ workDate: z.string().min(1, t('messages.requiredFields')),
281
+ duration: positiveNumberField(t('messages.entryValidation')),
282
+ unit: z.enum(['hours', 'minutes']),
283
+ description: z
284
+ .string()
285
+ .trim()
286
+ .max(500, t('sheet.validation.descriptionMaxLength'))
287
+ .optional()
288
+ .or(z.literal('')),
289
+ }),
290
+ [t]
291
+ );
292
+
293
+ const form = useForm<QuickEntryFormValues>({
294
+ resolver: zodResolver(quickEntrySchema),
295
+ defaultValues: buildDefaultFormValues(),
296
+ });
297
+
298
+ const selectedProjectId = useWatch({
299
+ control: form.control,
300
+ name: 'projectId',
301
+ });
302
+
303
+ const selectedTaskId = useWatch({
304
+ control: form.control,
305
+ name: 'taskId',
306
+ });
307
+
308
+ const unitValue = useWatch({
309
+ control: form.control,
310
+ name: 'unit',
311
+ });
312
+
313
+ const { data: timesheetsResponse, refetch } = useQuery<
314
+ PaginatedResponse<OperationsTimesheet>
315
+ >({
316
+ queryKey: [
317
+ 'operations-timesheets',
318
+ currentLocaleCode,
319
+ search,
320
+ statusFilter,
321
+ dateFrom,
322
+ dateTo,
323
+ page,
324
+ pageSize,
325
+ ],
326
+ queryFn: () => {
327
+ const params = new URLSearchParams({
328
+ page: String(page),
329
+ pageSize: String(pageSize),
330
+ });
331
+ if (search.trim()) params.set('search', search.trim());
332
+ if (statusFilter !== 'all') params.set('status', statusFilter);
333
+ if (dateFrom) params.set('dateFrom', dateFrom);
334
+ if (dateTo) params.set('dateTo', dateTo);
335
+ return fetchOperations<PaginatedResponse<OperationsTimesheet>>(
336
+ request,
337
+ `/operations/timesheets?${params.toString()}`
338
+ );
339
+ },
340
+ placeholderData: (previous) => previous,
341
+ });
342
+
343
+ const timesheets = timesheetsResponse?.data ?? [];
344
+
345
+ const calendarDateFrom = `${String(calendarYear)}-${String(calendarMonth).padStart(2, '0')}-01`;
346
+ const calendarDateTo = (() => {
347
+ const lastDay = new Date(calendarYear, calendarMonth, 0).getDate();
348
+ return `${String(calendarYear)}-${String(calendarMonth).padStart(2, '0')}-${String(lastDay).padStart(2, '0')}`;
349
+ })();
350
+
351
+ const { data: calendarTimesheetsResponse } = useQuery<
352
+ PaginatedResponse<OperationsTimesheet>
353
+ >({
354
+ queryKey: [
355
+ 'operations-timesheets-calendar',
356
+ currentLocaleCode,
357
+ search,
358
+ statusFilter,
359
+ calendarYear,
360
+ calendarMonth,
361
+ ],
362
+ enabled: viewMode === 'calendar',
363
+ queryFn: () => {
364
+ const params = new URLSearchParams({
365
+ sortField: 'weekStartDate',
366
+ sortOrder: 'desc',
367
+ dateFrom: calendarDateFrom,
368
+ dateTo: calendarDateTo,
369
+ });
370
+ if (search.trim()) params.set('search', search.trim());
371
+ if (statusFilter !== 'all') params.set('status', statusFilter);
372
+ return fetchOperations<PaginatedResponse<OperationsTimesheet>>(
373
+ request,
374
+ `/operations/timesheets?${params.toString()}`
375
+ );
376
+ },
377
+ placeholderData: (previous) => previous,
378
+ });
379
+ const calendarTimesheets = useMemo(
380
+ () => calendarTimesheetsResponse?.data ?? [],
381
+ [calendarTimesheetsResponse]
382
+ );
383
+
384
+ const getTimesheetStatusLabel = useCallback(
385
+ (status?: string | null) => {
386
+ if (!status) {
387
+ return commonT('labels.notAvailable');
388
+ }
389
+
390
+ return t.has(`statuses.${status}`)
391
+ ? t(`statuses.${status}`)
392
+ : formatEnumLabel(status);
393
+ },
394
+ [commonT, t]
395
+ );
396
+
397
+ const handleViewModeChange = (value: string) => {
398
+ if (value !== 'table' && value !== 'cards' && value !== 'calendar') return;
399
+ setViewMode(value as 'table' | 'cards' | 'calendar');
400
+ if (typeof window !== 'undefined') {
401
+ window.localStorage.setItem('operations-timesheets-view-mode', value);
402
+ }
403
+ };
404
+
405
+ const { data: me } = useQuery<OperationsCollaborator>({
406
+ queryKey: ['operations-timesheets-me', currentLocaleCode],
407
+ enabled: access.isCollaborator,
408
+ queryFn: () =>
409
+ fetchOperations<OperationsCollaborator>(
410
+ request,
411
+ '/operations/collaborators/me'
412
+ ),
413
+ });
414
+
415
+ const { refetch: refetchRecentEntries } = useQuery<
416
+ PaginatedResponse<OperationsTimesheetEntry>
417
+ >({
418
+ queryKey: [
419
+ 'operations-timesheet-recent-entries',
420
+ currentLocaleCode,
421
+ search,
422
+ statusFilter,
423
+ ],
424
+ enabled: access.isCollaborator,
425
+ queryFn: () => {
426
+ const params = new URLSearchParams({
427
+ page: '1',
428
+ pageSize: '8',
429
+ sortField: 'workDate',
430
+ sortOrder: 'desc',
431
+ });
432
+
433
+ if (search.trim()) {
434
+ params.set('search', search.trim());
435
+ }
436
+
437
+ if (statusFilter !== 'all') {
438
+ params.set('status', statusFilter);
439
+ }
440
+
441
+ return fetchOperations<PaginatedResponse<OperationsTimesheetEntry>>(
442
+ request,
443
+ `/operations/timesheet-entries?${params.toString()}`
444
+ );
445
+ },
446
+ placeholderData: (previous) => previous,
447
+ });
448
+
449
+ const {
450
+ data: projectOptionsResponse,
451
+ isLoading: isProjectOptionsLoading,
452
+ error: projectOptionsError,
453
+ } = useQuery<PaginatedResponse<OperationsProjectOption>>({
454
+ queryKey: [
455
+ 'operations-timesheet-project-options',
456
+ currentLocaleCode,
457
+ projectQuery.search,
458
+ projectQuery.page,
459
+ ],
460
+ enabled: access.isCollaborator && isSheetOpen,
461
+ queryFn: () => {
462
+ const params = new URLSearchParams({
463
+ page: String(projectQuery.page),
464
+ pageSize: '20',
465
+ });
466
+
467
+ if (projectQuery.search.trim()) {
468
+ params.set('search', projectQuery.search.trim());
469
+ }
470
+
471
+ return fetchOperations<PaginatedResponse<OperationsProjectOption>>(
472
+ request,
473
+ `/operations/projects/options?${params.toString()}`
474
+ );
475
+ },
476
+ placeholderData: (previous) => previous,
477
+ });
478
+
479
+ const selectedProject =
480
+ projectOptions.find((option) => option.id === selectedProjectId) ?? null;
481
+
482
+ const {
483
+ data: taskOptionsResponse,
484
+ isLoading: isTaskOptionsLoading,
485
+ error: taskOptionsError,
486
+ } = useQuery<PaginatedResponse<OperationsTaskOption>>({
487
+ queryKey: [
488
+ 'operations-timesheet-task-options',
489
+ currentLocaleCode,
490
+ selectedProjectId,
491
+ taskQuery.search,
492
+ taskQuery.page,
493
+ taskRefreshKey,
494
+ ],
495
+ enabled: access.isCollaborator && isSheetOpen && Boolean(selectedProjectId),
496
+ queryFn: () => {
497
+ const params = new URLSearchParams({
498
+ page: String(taskQuery.page),
499
+ pageSize: '20',
500
+ });
501
+
502
+ if (taskQuery.search.trim()) {
503
+ params.set('search', taskQuery.search.trim());
504
+ }
505
+
506
+ if (selectedProjectId) {
507
+ params.set('projectId', String(selectedProjectId));
508
+ }
509
+
510
+ return fetchOperations<PaginatedResponse<OperationsTaskOption>>(
511
+ request,
512
+ `/operations/tasks?${params.toString()}`
513
+ );
514
+ },
515
+ });
516
+
517
+ useEffect(() => {
518
+ if (!projectOptionsResponse) {
519
+ return;
520
+ }
521
+
522
+ setProjectOptions((current) =>
523
+ projectQuery.page === 1
524
+ ? editingEntry
525
+ ? appendUniqueById(current, projectOptionsResponse.data ?? [])
526
+ : (projectOptionsResponse.data ?? [])
527
+ : appendUniqueById(current, projectOptionsResponse.data ?? [])
528
+ );
529
+ }, [editingEntry, projectOptionsResponse, projectQuery.page]);
530
+
531
+ useEffect(() => {
532
+ if (!selectedProjectId) {
533
+ setTaskOptions([]);
534
+ return;
535
+ }
536
+
537
+ if (!taskOptionsResponse) {
538
+ return;
539
+ }
540
+
541
+ setTaskOptions((current) =>
542
+ taskQuery.page === 1
543
+ ? editingEntry
544
+ ? appendUniqueById(
545
+ current,
546
+ (taskOptionsResponse.data ?? []).filter(
547
+ (option) => option.projectId === selectedProjectId
548
+ )
549
+ )
550
+ : (taskOptionsResponse.data ?? []).filter(
551
+ (option) => option.projectId === selectedProjectId
552
+ )
553
+ : appendUniqueById(
554
+ current,
555
+ (taskOptionsResponse.data ?? []).filter(
556
+ (option) => option.projectId === selectedProjectId
557
+ )
558
+ )
559
+ );
560
+ }, [editingEntry, selectedProjectId, taskOptionsResponse, taskQuery.page]);
561
+
562
+ useEffect(() => {
563
+ const previousProjectId = previousProjectIdRef.current;
564
+ previousProjectIdRef.current = selectedProjectId;
565
+
566
+ if (
567
+ previousProjectId === undefined ||
568
+ previousProjectId === selectedProjectId
569
+ ) {
570
+ return;
571
+ }
572
+
573
+ setTaskOptions([]);
574
+ setTaskQuery({ search: '', page: 1 });
575
+ form.setValue('taskId', undefined, {
576
+ shouldDirty: true,
577
+ shouldTouch: true,
578
+ shouldValidate: false,
579
+ });
580
+ }, [form, selectedProjectId]);
581
+
582
+ useEffect(() => {
583
+ if (!projectOptionsError) {
584
+ return;
585
+ }
586
+
587
+ showToastHandler?.(
588
+ 'error',
589
+ getOperationsErrorMessage(
590
+ projectOptionsError,
591
+ t('messages.projectLoadError')
592
+ )
593
+ );
594
+ }, [projectOptionsError, showToastHandler, t]);
595
+
596
+ useEffect(() => {
597
+ if (!taskOptionsError) {
598
+ return;
599
+ }
600
+
601
+ showToastHandler?.(
602
+ 'error',
603
+ getOperationsErrorMessage(taskOptionsError, t('messages.taskLoadError'))
604
+ );
605
+ }, [showToastHandler, t, taskOptionsError]);
606
+
607
+ const filteredTaskOptions = selectedProjectId
608
+ ? taskOptions.filter((option) => option.projectId === selectedProjectId)
609
+ : [];
610
+ const selectedTask =
611
+ filteredTaskOptions.find((option) => option.id === selectedTaskId) ?? null;
612
+ const isEditingEntry = Boolean(editingEntry);
613
+
614
+ const filteredRows = timesheets;
615
+ const calendarItems = useMemo<OperationsCalendarItem[]>(
616
+ () =>
617
+ calendarTimesheets.map((timesheet) => ({
618
+ id: `timesheet-${timesheet.id}`,
619
+ date:
620
+ String(timesheet.weekStartDate).match(/(\d{4}-\d{2}-\d{2})/)?.[1] ??
621
+ timesheet.weekStartDate,
622
+ kind: 'timesheet',
623
+ title: `${formatHours(timesheet.totalHours)} • ${timesheet.collaboratorName}`,
624
+ subtitle:
625
+ (timesheet.entries ?? [])
626
+ .slice(0, 2)
627
+ .map(
628
+ (entry) =>
629
+ [entry.projectName, entry.taskName || entry.activityLabel]
630
+ .filter(Boolean)
631
+ .join(' • ') || commonT('labels.unassigned')
632
+ )
633
+ .join(', ') || commonT('labels.unassigned'),
634
+ meta: `${timesheet.entries?.length ?? 0} ${commonT('labels.lines')}`,
635
+ statusLabel: getTimesheetStatusLabel(timesheet.status),
636
+ badgeClassName: getStatusBadgeClass(timesheet.status),
637
+ })),
638
+ [calendarTimesheets, commonT, getTimesheetStatusLabel]
639
+ );
640
+
641
+ const cards = [
642
+ {
643
+ key: 'all',
644
+ title: t('cards.visible'),
645
+ description: t('cards.visibleDescription'),
646
+ value: timesheets.length,
647
+ },
648
+ {
649
+ key: 'pending',
650
+ title: t('cards.pending'),
651
+ description: t('cards.pendingDescription'),
652
+ value: timesheets.filter((item) => item.status === 'submitted').length,
653
+ },
654
+ {
655
+ key: 'hours',
656
+ title: t('cards.hours'),
657
+ description: t('cards.hoursDescription'),
658
+ value: formatHours(
659
+ timesheets.reduce(
660
+ (total, item) => total + Number(item.totalHours ?? 0),
661
+ 0
662
+ )
663
+ ),
664
+ },
665
+ ];
666
+
667
+ const openCreate = () => {
668
+ setEditingEntry(null);
669
+ form.reset(buildDefaultFormValues());
670
+ setProjectQuery({ search: '', page: 1 });
671
+ setTaskQuery({ search: '', page: 1 });
672
+ setProjectOptions([]);
673
+ setTaskOptions([]);
674
+ setIsTaskCreateSheetOpen(false);
675
+ setIsSheetOpen(true);
676
+ };
677
+
678
+ const closeCreateSheet = () => {
679
+ setIsSheetOpen(false);
680
+ setEditingEntry(null);
681
+ setIsTaskCreateSheetOpen(false);
682
+ form.reset(buildDefaultFormValues());
683
+ setProjectQuery({ search: '', page: 1 });
684
+ setTaskQuery({ search: '', page: 1 });
685
+ setProjectOptions([]);
686
+ setTaskOptions([]);
687
+ };
688
+
689
+ const openDetails = (timesheet: OperationsTimesheet) => {
690
+ setSelectedTimesheet(timesheet);
691
+ setIsDetailsOpen(true);
692
+ };
693
+
694
+ const openEditEntry = (entry: OperationsTimesheetEntry) => {
695
+ setEditingEntry(entry);
696
+ form.reset(buildEntryFormValues(entry));
697
+ setProjectQuery({ search: '', page: 1 });
698
+ setTaskQuery({ search: '', page: 1 });
699
+ setProjectOptions((current) =>
700
+ appendUniqueById(
701
+ current,
702
+ entry.projectId && entry.projectName
703
+ ? [
704
+ {
705
+ id: entry.projectId,
706
+ label:
707
+ [entry.projectCode, entry.projectName]
708
+ .filter(Boolean)
709
+ .join(' • ') || entry.projectName,
710
+ name: entry.projectName,
711
+ code: entry.projectCode,
712
+ status: entry.status ?? 'submitted',
713
+ },
714
+ ]
715
+ : []
716
+ )
717
+ );
718
+ setTaskOptions((current) =>
719
+ appendUniqueById(
720
+ current,
721
+ entry.taskId && entry.projectId
722
+ ? [
723
+ {
724
+ id: entry.taskId,
725
+ label:
726
+ entry.taskName ||
727
+ entry.activityLabel ||
728
+ commonT('labels.unassigned'),
729
+ name:
730
+ entry.taskName ||
731
+ entry.activityLabel ||
732
+ commonT('labels.unassigned'),
733
+ status: entry.status ?? 'submitted',
734
+ projectId: entry.projectId,
735
+ projectAssignmentId: entry.projectAssignmentId ?? 0,
736
+ projectName:
737
+ entry.projectName || commonT('labels.unassigned'),
738
+ },
739
+ ]
740
+ : []
741
+ )
742
+ );
743
+ setEntryToDelete(null);
744
+ setIsDetailsOpen(false);
745
+ setIsTaskCreateSheetOpen(false);
746
+ setIsSheetOpen(true);
747
+ };
748
+
749
+ const openTimesheetForDate = (date: string) => {
750
+ const existingTimesheet =
751
+ calendarTimesheets.find((item) => item.weekStartDate === date) ??
752
+ timesheets.find((item) => item.weekStartDate === date);
753
+
754
+ if (existingTimesheet) {
755
+ openDetails(existingTimesheet);
756
+ return;
757
+ }
758
+
759
+ setEditingEntry(null);
760
+ form.reset({
761
+ ...buildDefaultFormValues(),
762
+ workDate: date,
763
+ });
764
+ setProjectQuery({ search: '', page: 1 });
765
+ setTaskQuery({ search: '', page: 1 });
766
+ setProjectOptions([]);
767
+ setTaskOptions([]);
768
+ setIsTaskCreateSheetOpen(false);
769
+ setIsSheetOpen(true);
770
+ };
771
+
772
+ const canManageRow = (timesheet: OperationsTimesheet) => {
773
+ return Boolean(
774
+ me?.id &&
775
+ timesheet.collaboratorId === me.id &&
776
+ timesheet.status !== 'approved'
777
+ );
778
+ };
779
+
780
+ const canSubmitTimesheet = (timesheet: OperationsTimesheet) => {
781
+ return Boolean(
782
+ me?.id &&
783
+ timesheet.collaboratorId === me.id &&
784
+ ['draft', 'rejected'].includes(timesheet.status)
785
+ );
786
+ };
787
+
788
+ const handleQuickEntrySubmit = async (values: QuickEntryFormValues) => {
789
+ const payload = {
790
+ projectId: values.projectId,
791
+ taskId: values.taskId,
792
+ workDate: values.workDate,
793
+ duration: values.duration,
794
+ unit: values.unit,
795
+ description: trimToNull(values.description),
796
+ };
797
+
798
+ try {
799
+ if (editingEntry?.id) {
800
+ await mutateOperations(
801
+ request,
802
+ `/operations/timesheet-entries/${editingEntry.id}`,
803
+ 'PATCH',
804
+ payload
805
+ );
806
+ } else {
807
+ await mutateOperations(
808
+ request,
809
+ '/operations/timesheet-entries',
810
+ 'POST',
811
+ payload
812
+ );
813
+ }
814
+
815
+ showToastHandler?.(
816
+ 'success',
817
+ editingEntry ? t('messages.updateSuccess') : t('messages.saveSuccess')
818
+ );
819
+
820
+ if (!editingEntry && keepContextOnSave) {
821
+ form.reset(buildFollowUpFormValues(values, true));
822
+ setProjectQuery({ search: '', page: 1 });
823
+ setTaskQuery({ search: '', page: 1 });
824
+ setIsTaskCreateSheetOpen(false);
825
+ setTimeout(() => form.setFocus('duration'), 0);
826
+ } else {
827
+ closeCreateSheet();
828
+ }
829
+
830
+ await Promise.all([refetch(), refetchRecentEntries()]);
831
+ } catch (error) {
832
+ showToastHandler?.(
833
+ 'error',
834
+ getOperationsErrorMessage(
835
+ error,
836
+ editingEntry ? t('messages.updateError') : t('messages.saveError')
837
+ )
838
+ );
839
+ }
840
+ };
841
+
842
+ const submitTimesheet = async (timesheetId: number) => {
843
+ try {
844
+ await request({
845
+ url: `/operations/timesheets/${timesheetId}/submit`,
846
+ method: 'POST',
847
+ });
848
+ showToastHandler?.('success', t('messages.submitSuccess'));
849
+ await Promise.all([refetch(), refetchRecentEntries()]);
850
+ } catch (error) {
851
+ showToastHandler?.(
852
+ 'error',
853
+ getOperationsErrorMessage(error, t('messages.submitError'))
854
+ );
855
+ }
856
+ };
857
+
858
+ const openTaskCreateSheet = () => {
859
+ if (!selectedProjectId || !selectedProject) {
860
+ showToastHandler?.('error', t('messages.selectProjectFirst'));
861
+ return;
862
+ }
863
+
864
+ setIsTaskCreateSheetOpen(true);
865
+ };
866
+
867
+ const handleTaskCreated = (task: OperationsTaskOption) => {
868
+ setTaskOptions((current) => [
869
+ task,
870
+ ...current.filter((item) => item.id !== task.id),
871
+ ]);
872
+ form.setValue('taskId', task.id, {
873
+ shouldDirty: true,
874
+ shouldTouch: true,
875
+ shouldValidate: true,
876
+ });
877
+ setTaskQuery({ search: '', page: 1 });
878
+ setTaskRefreshKey((current) => current + 1);
879
+ };
880
+
881
+ const handleDeleteEntry = async () => {
882
+ if (!entryToDelete?.id) {
883
+ return;
884
+ }
885
+
886
+ try {
887
+ setIsDeletingEntry(true);
888
+ await mutateOperations(
889
+ request,
890
+ `/operations/timesheet-entries/${entryToDelete.id}`,
891
+ 'DELETE'
892
+ );
893
+ showToastHandler?.('success', t('messages.deleteSuccess'));
894
+ setEntryToDelete(null);
895
+ await Promise.all([refetch(), refetchRecentEntries()]);
896
+ } catch (error) {
897
+ showToastHandler?.(
898
+ 'error',
899
+ getOperationsErrorMessage(error, t('messages.deleteError'))
900
+ );
901
+ } finally {
902
+ setIsDeletingEntry(false);
903
+ }
904
+ };
905
+
906
+ return (
907
+ <Page>
908
+ <OperationsHeader
909
+ title={t('title')}
910
+ description={t('description')}
911
+ current={t('breadcrumb')}
912
+ actions={
913
+ access.isCollaborator ? (
914
+ <Button size="sm" onClick={openCreate}>
915
+ <Plus className="size-4" />
916
+ {commonT('actions.create')}
917
+ </Button>
918
+ ) : undefined
919
+ }
920
+ />
921
+
922
+ <div className="flex min-w-0 flex-col gap-4 xl:flex-row xl:items-center">
923
+ <div className="flex-1">
924
+ <SearchBar
925
+ searchQuery={search}
926
+ onSearchChange={(value) => {
927
+ setSearch(value);
928
+ setPage(1);
929
+ }}
930
+ showSearchButton={false}
931
+ debounceMs={500}
932
+ placeholder={t('searchPlaceholder')}
933
+ controls={[
934
+ {
935
+ id: 'status',
936
+ type: 'select',
937
+ value: statusFilter,
938
+ onChange: (value) => {
939
+ setStatusFilter(value);
940
+ setPage(1);
941
+ },
942
+ placeholder: commonT('labels.status'),
943
+ options: [
944
+ { value: 'all', label: commonT('filters.allStatuses') },
945
+ { value: 'draft', label: getTimesheetStatusLabel('draft') },
946
+ {
947
+ value: 'submitted',
948
+ label: getTimesheetStatusLabel('submitted'),
949
+ },
950
+ {
951
+ value: 'approved',
952
+ label: getTimesheetStatusLabel('approved'),
953
+ },
954
+ {
955
+ value: 'rejected',
956
+ label: getTimesheetStatusLabel('rejected'),
957
+ },
958
+ ],
959
+ },
960
+ {
961
+ id: 'dateFrom',
962
+ type: 'date',
963
+ value: dateFrom,
964
+ onChange: (value) => {
965
+ setDateFrom(value);
966
+ setPage(1);
967
+ },
968
+ label: commonT('filters.dateFrom'),
969
+ },
970
+ {
971
+ id: 'dateTo',
972
+ type: 'date',
973
+ value: dateTo,
974
+ onChange: (value) => {
975
+ setDateTo(value);
976
+ setPage(1);
977
+ },
978
+ label: commonT('filters.dateTo'),
979
+ },
980
+ ]}
981
+ />
982
+ </div>
983
+
984
+ <div className="flex items-center justify-between gap-3 xl:justify-end">
985
+ <span className="text-xs font-medium text-muted-foreground">
986
+ {t('viewMode')}
987
+ </span>
988
+ <ToggleGroup
989
+ type="single"
990
+ value={viewMode}
991
+ onValueChange={handleViewModeChange}
992
+ variant="outline"
993
+ size="sm"
994
+ >
995
+ <ToggleGroupItem value="table" className="gap-1.5 px-2.5">
996
+ <List className="h-4 w-4" />
997
+ <span className="hidden sm:inline">{t('viewModeTable')}</span>
998
+ </ToggleGroupItem>
999
+ <ToggleGroupItem value="cards" className="gap-1.5 px-2.5">
1000
+ <LayoutGrid className="h-4 w-4" />
1001
+ <span className="hidden sm:inline">{t('viewModeCards')}</span>
1002
+ </ToggleGroupItem>
1003
+ <ToggleGroupItem value="calendar" className="gap-1.5 px-2.5">
1004
+ <CalendarDays className="h-4 w-4" />
1005
+ <span className="hidden sm:inline">{t('viewModeCalendar')}</span>
1006
+ </ToggleGroupItem>
1007
+ </ToggleGroup>
1008
+ </div>
1009
+ </div>
1010
+
1011
+ <KpiCardsGrid items={cards} columns={3} />
1012
+
1013
+ {(viewMode === 'calendar' ? true : timesheets.length > 0) ? (
1014
+ viewMode === 'calendar' ? (
1015
+ <OperationsCalendarView
1016
+ locale={currentLocaleCode}
1017
+ items={calendarItems}
1018
+ emptyLabel={t('emptyDescription')}
1019
+ actionLabel={t('actions.viewDetails')}
1020
+ onMonthChange={(year, month) => {
1021
+ setCalendarYear(year);
1022
+ setCalendarMonth(month);
1023
+ }}
1024
+ onOpenItem={(item) => {
1025
+ openTimesheetForDate(item.date);
1026
+ }}
1027
+ onDateSelect={(date, items) => {
1028
+ if (items.some((item) => item.kind === 'timesheet')) {
1029
+ openTimesheetForDate(date);
1030
+ }
1031
+ }}
1032
+ />
1033
+ ) : viewMode === 'cards' ? (
1034
+ <div className="grid gap-4 md:grid-cols-2 2xl:grid-cols-3">
1035
+ {timesheets.map((timesheet) => (
1036
+ <div
1037
+ key={timesheet.id}
1038
+ className="rounded-lg border bg-card shadow-sm p-4 space-y-3"
1039
+ >
1040
+ <div className="flex items-start justify-between gap-3">
1041
+ <div className="min-w-0">
1042
+ <div className="truncate font-semibold">
1043
+ {timesheet.collaboratorName}
1044
+ </div>
1045
+ <div className="truncate text-xs text-muted-foreground">
1046
+ {formatDate(timesheet.weekStartDate)}
1047
+ </div>
1048
+ </div>
1049
+ <StatusBadge
1050
+ label={getTimesheetStatusLabel(timesheet.status)}
1051
+ className={getStatusBadgeClass(timesheet.status)}
1052
+ />
1053
+ </div>
1054
+ <div className="grid grid-cols-2 gap-2 text-sm text-muted-foreground">
1055
+ <div>
1056
+ <span className="font-medium text-foreground">
1057
+ {commonT('labels.totalHours')}:
1058
+ </span>{' '}
1059
+ {formatHours(timesheet.totalHours)}
1060
+ </div>
1061
+ <div>
1062
+ <span className="font-medium text-foreground">
1063
+ {commonT('labels.entries')}:
1064
+ </span>{' '}
1065
+ {timesheet.entries?.length ?? 0}
1066
+ </div>
1067
+ </div>
1068
+ {timesheet.approverName ? (
1069
+ <div className="text-sm text-muted-foreground">
1070
+ <span className="font-medium text-foreground">
1071
+ {commonT('labels.approver')}:
1072
+ </span>{' '}
1073
+ {timesheet.approverName}
1074
+ </div>
1075
+ ) : null}
1076
+ {canManageRow(timesheet) ? (
1077
+ <div className="flex justify-end gap-2 border-t border-border/60 pt-3">
1078
+ <Button
1079
+ variant="outline"
1080
+ size="sm"
1081
+ className="cursor-pointer"
1082
+ onClick={() => openDetails(timesheet)}
1083
+ >
1084
+ <Eye className="size-4" />
1085
+ {t('actions.viewDetails')}
1086
+ </Button>
1087
+ {canSubmitTimesheet(timesheet) ? (
1088
+ <Button
1089
+ size="sm"
1090
+ onClick={() => void submitTimesheet(timesheet.id)}
1091
+ >
1092
+ <Send className="size-4" />
1093
+ {commonT('actions.submit')}
1094
+ </Button>
1095
+ ) : null}
1096
+ </div>
1097
+ ) : (
1098
+ <div className="flex justify-end border-t border-border/60 pt-3">
1099
+ <Button
1100
+ variant="outline"
1101
+ size="sm"
1102
+ className="cursor-pointer"
1103
+ onClick={() => openDetails(timesheet)}
1104
+ >
1105
+ <Eye className="size-4" />
1106
+ {t('actions.viewDetails')}
1107
+ </Button>
1108
+ </div>
1109
+ )}
1110
+ </div>
1111
+ ))}
1112
+ </div>
1113
+ ) : (
1114
+ <div className="overflow-x-auto rounded-md border">
1115
+ <Table>
1116
+ <TableHeader>
1117
+ <TableRow>
1118
+ <TableHead>{commonT('labels.collaborator')}</TableHead>
1119
+ <TableHead>{commonT('labels.workDate')}</TableHead>
1120
+ <TableHead>{commonT('labels.entries')}</TableHead>
1121
+ <TableHead>{commonT('labels.totalHours')}</TableHead>
1122
+ <TableHead>{commonT('labels.approver')}</TableHead>
1123
+ <TableHead>{commonT('labels.decisionNote')}</TableHead>
1124
+ <TableHead>{commonT('labels.status')}</TableHead>
1125
+ <TableHead>{commonT('labels.actions')}</TableHead>
1126
+ </TableRow>
1127
+ </TableHeader>
1128
+ <TableBody>
1129
+ {filteredRows.map((timesheet) => (
1130
+ <TableRow key={timesheet.id} className="hover:bg-muted/30">
1131
+ <TableCell>
1132
+ <div className="font-medium">
1133
+ {timesheet.collaboratorName}
1134
+ </div>
1135
+ <div className="text-xs text-muted-foreground">
1136
+ {timesheet.notes || commonT('labels.noNotes')}
1137
+ </div>
1138
+ </TableCell>
1139
+ <TableCell>{formatDate(timesheet.weekStartDate)}</TableCell>
1140
+ <TableCell>
1141
+ <div className="font-medium">
1142
+ {timesheet.entries?.length ?? 0}{' '}
1143
+ {commonT('labels.lines')}
1144
+ </div>
1145
+ <div className="text-xs text-muted-foreground">
1146
+ {(timesheet.entries ?? [])
1147
+ .slice(0, 2)
1148
+ .map(
1149
+ (entry) =>
1150
+ [
1151
+ entry.projectName,
1152
+ entry.taskName || entry.activityLabel,
1153
+ ]
1154
+ .filter(Boolean)
1155
+ .join(' • ') || commonT('labels.unassigned')
1156
+ )
1157
+ .join(', ') || commonT('labels.unassigned')}
1158
+ </div>
1159
+ </TableCell>
1160
+ <TableCell>{formatHours(timesheet.totalHours)}</TableCell>
1161
+ <TableCell>
1162
+ {timesheet.approverName || commonT('labels.notAssigned')}
1163
+ </TableCell>
1164
+ <TableCell>
1165
+ <div className="text-sm text-muted-foreground">
1166
+ {timesheet.decisionNote || commonT('labels.noNotes')}
1167
+ </div>
1168
+ </TableCell>
1169
+ <TableCell>
1170
+ <StatusBadge
1171
+ label={getTimesheetStatusLabel(timesheet.status)}
1172
+ className={getStatusBadgeClass(timesheet.status)}
1173
+ />
1174
+ </TableCell>
1175
+ <TableCell>
1176
+ <div className="flex justify-end gap-2">
1177
+ {canManageRow(timesheet) ? (
1178
+ <>
1179
+ <Button
1180
+ variant="outline"
1181
+ size="sm"
1182
+ className="cursor-pointer"
1183
+ onClick={() => openDetails(timesheet)}
1184
+ >
1185
+ <Eye className="size-4" />
1186
+ {t('actions.viewDetails')}
1187
+ </Button>
1188
+ {canSubmitTimesheet(timesheet) ? (
1189
+ <Button
1190
+ size="icon"
1191
+ onClick={() => void submitTimesheet(timesheet.id)}
1192
+ >
1193
+ <Send className="size-4" />
1194
+ </Button>
1195
+ ) : null}
1196
+ </>
1197
+ ) : (
1198
+ <Button
1199
+ variant="outline"
1200
+ size="sm"
1201
+ className="cursor-pointer"
1202
+ onClick={() => openDetails(timesheet)}
1203
+ >
1204
+ <Eye className="size-4" />
1205
+ {t('actions.viewDetails')}
1206
+ </Button>
1207
+ )}
1208
+ </div>
1209
+ </TableCell>
1210
+ </TableRow>
1211
+ ))}
1212
+ </TableBody>
1213
+ </Table>
1214
+ </div>
1215
+ )
1216
+ ) : (
1217
+ <EmptyState
1218
+ icon={<ClipboardList className="size-12" />}
1219
+ title={commonT('states.emptyTitle')}
1220
+ description={t('emptyDescription')}
1221
+ actionLabel={
1222
+ access.isCollaborator
1223
+ ? commonT('actions.create')
1224
+ : commonT('actions.refresh')
1225
+ }
1226
+ onAction={access.isCollaborator ? openCreate : () => void refetch()}
1227
+ />
1228
+ )}
1229
+
1230
+ <PaginationFooter
1231
+ currentPage={page}
1232
+ pageSize={pageSize}
1233
+ totalItems={timesheetsResponse?.total ?? 0}
1234
+ pageSizeOptions={[12, 24, 48]}
1235
+ onPageChange={setPage}
1236
+ onPageSizeChange={(size) => {
1237
+ setPageSize(size);
1238
+ setPage(1);
1239
+ }}
1240
+ />
1241
+
1242
+ <Sheet
1243
+ open={isSheetOpen}
1244
+ onOpenChange={(open) => {
1245
+ if (form.formState.isSubmitting && !open) {
1246
+ return;
1247
+ }
1248
+
1249
+ if (!open) {
1250
+ closeCreateSheet();
1251
+ return;
1252
+ }
1253
+
1254
+ setIsSheetOpen(true);
1255
+ }}
1256
+ >
1257
+ <SheetContent className="flex h-full w-full flex-col gap-0 overflow-hidden p-0 sm:max-w-2xl">
1258
+ <SheetHeader className="border-b px-4 py-4 text-left">
1259
+ <div className="flex items-start gap-3">
1260
+ <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary">
1261
+ <Clock3 className="size-5" />
1262
+ </div>
1263
+
1264
+ <div className="space-y-1">
1265
+ <SheetTitle>
1266
+ {isEditingEntry
1267
+ ? t('sheet.editTitle')
1268
+ : t('sheet.createTitle')}
1269
+ </SheetTitle>
1270
+ <SheetDescription>{t('sheet.description')}</SheetDescription>
1271
+ </div>
1272
+ </div>
1273
+ </SheetHeader>
1274
+
1275
+ <Form {...form}>
1276
+ <form
1277
+ onSubmit={form.handleSubmit(handleQuickEntrySubmit)}
1278
+ className="flex min-h-0 flex-1 flex-col"
1279
+ >
1280
+ <div className="flex-1 space-y-5 overflow-y-auto px-4 py-4">
1281
+ <div className="grid gap-4 lg:grid-cols-2">
1282
+ <FormField
1283
+ control={form.control}
1284
+ name="projectId"
1285
+ render={({ field }) => (
1286
+ <FormItem>
1287
+ <FormLabel>{t('sheet.fields.project')}</FormLabel>
1288
+ <FormControl>
1289
+ <AsyncOptionsCombobox
1290
+ value={field.value}
1291
+ selectedOption={selectedProject}
1292
+ options={projectOptions}
1293
+ onSelect={(option) => {
1294
+ field.onChange(option?.id);
1295
+ form.setValue('taskId', undefined, {
1296
+ shouldDirty: true,
1297
+ shouldTouch: true,
1298
+ });
1299
+ setTaskQuery({ search: '', page: 1 });
1300
+ setTaskOptions([]);
1301
+ }}
1302
+ searchValue={projectQuery.search}
1303
+ onSearchValueChange={(value) =>
1304
+ setProjectQuery({ search: value, page: 1 })
1305
+ }
1306
+ placeholder={t('sheet.placeholders.project')}
1307
+ searchPlaceholder={t(
1308
+ 'sheet.placeholders.projectSearch'
1309
+ )}
1310
+ emptyLabel={t('entries.projectHint')}
1311
+ loadMoreLabel={commonT('actions.loadMore')}
1312
+ clearLabel={commonT('actions.clearSelection')}
1313
+ isLoading={isProjectOptionsLoading}
1314
+ hasMore={Boolean(projectOptionsResponse?.next)}
1315
+ onLoadMore={() =>
1316
+ setProjectQuery((current) => ({
1317
+ ...current,
1318
+ page: current.page + 1,
1319
+ }))
1320
+ }
1321
+ />
1322
+ </FormControl>
1323
+ <FormMessage />
1324
+ </FormItem>
1325
+ )}
1326
+ />
1327
+
1328
+ <FormField
1329
+ control={form.control}
1330
+ name="taskId"
1331
+ render={({ field }) => (
1332
+ <FormItem>
1333
+ <FormLabel>{t('sheet.fields.task')}</FormLabel>
1334
+ <FormControl>
1335
+ <AsyncOptionsCombobox
1336
+ value={field.value}
1337
+ selectedOption={selectedTask}
1338
+ options={filteredTaskOptions}
1339
+ onSelect={(option) => field.onChange(option?.id)}
1340
+ searchValue={taskQuery.search}
1341
+ onSearchValueChange={(value) =>
1342
+ setTaskQuery({ search: value, page: 1 })
1343
+ }
1344
+ placeholder={t('sheet.placeholders.task')}
1345
+ searchPlaceholder={t(
1346
+ 'sheet.placeholders.taskSearch'
1347
+ )}
1348
+ emptyLabel={
1349
+ selectedProjectId
1350
+ ? t('sheet.helper.task')
1351
+ : t('sheet.helper.selectProjectFirst')
1352
+ }
1353
+ loadMoreLabel={commonT('actions.loadMore')}
1354
+ clearLabel={commonT('actions.clearSelection')}
1355
+ createLabel={t('sheet.task.createAction')}
1356
+ onCreateClick={openTaskCreateSheet}
1357
+ isLoading={isTaskOptionsLoading}
1358
+ hasMore={Boolean(taskOptionsResponse?.next)}
1359
+ onLoadMore={() =>
1360
+ setTaskQuery((current) => ({
1361
+ ...current,
1362
+ page: current.page + 1,
1363
+ }))
1364
+ }
1365
+ disabled={!selectedProjectId}
1366
+ />
1367
+ </FormControl>
1368
+
1369
+ <FormMessage />
1370
+ </FormItem>
1371
+ )}
1372
+ />
1373
+ </div>
1374
+
1375
+ <div className="grid gap-4 md:grid-cols-[1fr_1fr_220px]">
1376
+ <FormField
1377
+ control={form.control}
1378
+ name="workDate"
1379
+ render={({ field }) => (
1380
+ <FormItem>
1381
+ <FormLabel>{commonT('labels.workDate')}</FormLabel>
1382
+ <FormControl>
1383
+ <Input type="date" {...field} />
1384
+ </FormControl>
1385
+ <FormMessage />
1386
+ </FormItem>
1387
+ )}
1388
+ />
1389
+
1390
+ <FormField
1391
+ control={form.control}
1392
+ name="duration"
1393
+ render={({ field }) => (
1394
+ <FormItem>
1395
+ <FormLabel>{t('sheet.fields.duration')}</FormLabel>
1396
+ <FormControl>
1397
+ <Input
1398
+ type="number"
1399
+ min="0"
1400
+ step={unitValue === 'minutes' ? '5' : '0.25'}
1401
+ placeholder={t('sheet.placeholders.duration')}
1402
+ value={field.value ?? ''}
1403
+ onChange={(event) => {
1404
+ const nextValue = event.target.value;
1405
+ field.onChange(
1406
+ nextValue === '' ? undefined : Number(nextValue)
1407
+ );
1408
+ }}
1409
+ />
1410
+ </FormControl>
1411
+ <FormMessage />
1412
+ </FormItem>
1413
+ )}
1414
+ />
1415
+
1416
+ <FormField
1417
+ control={form.control}
1418
+ name="unit"
1419
+ render={({ field }) => (
1420
+ <FormItem>
1421
+ <FormLabel>{t('sheet.fields.unit')}</FormLabel>
1422
+ <FormControl>
1423
+ <ToggleGroup
1424
+ type="single"
1425
+ value={field.value}
1426
+ className="w-full"
1427
+ onValueChange={(value) => {
1428
+ if (value === 'hours' || value === 'minutes') {
1429
+ field.onChange(value);
1430
+ }
1431
+ }}
1432
+ >
1433
+ <ToggleGroupItem value="hours" className="flex-1">
1434
+ {t('sheet.fields.hours')}
1435
+ </ToggleGroupItem>
1436
+ <ToggleGroupItem value="minutes" className="flex-1">
1437
+ {t('sheet.fields.minutes')}
1438
+ </ToggleGroupItem>
1439
+ </ToggleGroup>
1440
+ </FormControl>
1441
+ <FormMessage />
1442
+ </FormItem>
1443
+ )}
1444
+ />
1445
+ </div>
1446
+
1447
+ <FormField
1448
+ control={form.control}
1449
+ name="description"
1450
+ render={({ field }) => (
1451
+ <FormItem>
1452
+ <FormLabel>{commonT('labels.description')}</FormLabel>
1453
+ <FormControl>
1454
+ <Textarea
1455
+ {...field}
1456
+ rows={4}
1457
+ placeholder={t('sheet.placeholders.description')}
1458
+ />
1459
+ </FormControl>
1460
+ <FormMessage />
1461
+ </FormItem>
1462
+ )}
1463
+ />
1464
+
1465
+ <div className="flex items-center justify-between rounded-lg border bg-background p-3">
1466
+ <div className="space-y-1 pr-3">
1467
+ <p className="text-sm font-medium text-foreground">
1468
+ {t('sheet.helper.keepContext')}
1469
+ </p>
1470
+ <p className="text-xs text-muted-foreground">
1471
+ {t('sheet.helper.keepContextDescription')}
1472
+ </p>
1473
+ </div>
1474
+
1475
+ <Switch
1476
+ checked={keepContextOnSave}
1477
+ onCheckedChange={setKeepContextOnSave}
1478
+ aria-label={t('sheet.helper.keepContext')}
1479
+ />
1480
+ </div>
1481
+ </div>
1482
+
1483
+ <FormActions
1484
+ sheet
1485
+ onCancel={closeCreateSheet}
1486
+ cancelLabel={commonT('actions.cancel')}
1487
+ submitType="submit"
1488
+ submitLabel={
1489
+ isEditingEntry
1490
+ ? commonT('actions.save')
1491
+ : commonT('actions.submit')
1492
+ }
1493
+ submitDisabled={form.formState.isSubmitting}
1494
+ />
1495
+ </form>
1496
+ </Form>
1497
+ </SheetContent>
1498
+ </Sheet>
1499
+
1500
+ <TimesheetTaskCreateSheet
1501
+ open={isTaskCreateSheetOpen}
1502
+ onOpenChange={setIsTaskCreateSheetOpen}
1503
+ project={selectedProject}
1504
+ onCreated={handleTaskCreated}
1505
+ />
1506
+
1507
+ <Sheet open={isDetailsOpen} onOpenChange={setIsDetailsOpen}>
1508
+ <SheetContent className="w-full overflow-y-auto sm:max-w-2xl">
1509
+ <SheetHeader>
1510
+ <SheetTitle>{t('details.title')}</SheetTitle>
1511
+ <SheetDescription>{t('details.description')}</SheetDescription>
1512
+ </SheetHeader>
1513
+
1514
+ {selectedTimesheet ? (
1515
+ <div className="mt-6 space-y-5 px-4 pb-8">
1516
+ <div className="rounded-lg border bg-muted/20 p-4">
1517
+ <div className="flex flex-wrap items-start justify-between gap-3">
1518
+ <div>
1519
+ <div className="text-lg font-semibold">
1520
+ {selectedTimesheet.collaboratorName}
1521
+ </div>
1522
+ <div className="mt-1 text-sm text-muted-foreground">
1523
+ {formatDate(selectedTimesheet.weekStartDate)}
1524
+ </div>
1525
+ </div>
1526
+ <StatusBadge
1527
+ label={
1528
+ t.has(`statuses.${selectedTimesheet.status}`)
1529
+ ? t(`statuses.${selectedTimesheet.status}`)
1530
+ : formatEnumLabel(selectedTimesheet.status)
1531
+ }
1532
+ className={getStatusBadgeClass(selectedTimesheet.status)}
1533
+ />
1534
+ </div>
1535
+ </div>
1536
+
1537
+ <div className="grid gap-4 sm:grid-cols-2">
1538
+ <div>
1539
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1540
+ {commonT('labels.totalHours')}
1541
+ </div>
1542
+ <div className="mt-1 text-sm">
1543
+ {formatHours(selectedTimesheet.totalHours)}
1544
+ </div>
1545
+ </div>
1546
+ <div>
1547
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1548
+ {commonT('labels.entries')}
1549
+ </div>
1550
+ <div className="mt-1 text-sm">
1551
+ {selectedTimesheet.entries?.length ?? 0}
1552
+ </div>
1553
+ </div>
1554
+ <div>
1555
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1556
+ {commonT('labels.approver')}
1557
+ </div>
1558
+ <div className="mt-1 text-sm">
1559
+ {selectedTimesheet.approverName ||
1560
+ commonT('labels.notAssigned')}
1561
+ </div>
1562
+ </div>
1563
+ <div>
1564
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1565
+ {t('details.period')}
1566
+ </div>
1567
+ <div className="mt-1 text-sm">
1568
+ {formatDateLabel(selectedTimesheet.weekStartDate)}
1569
+ </div>
1570
+ </div>
1571
+ </div>
1572
+
1573
+ <div>
1574
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1575
+ {commonT('labels.notes')}
1576
+ </div>
1577
+ <div className="mt-1 rounded-lg border p-3 text-sm">
1578
+ {selectedTimesheet.notes || commonT('labels.noNotes')}
1579
+ </div>
1580
+ </div>
1581
+
1582
+ <div>
1583
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1584
+ {commonT('labels.decisionNote')}
1585
+ </div>
1586
+ <div className="mt-1 rounded-lg border p-3 text-sm">
1587
+ {selectedTimesheet.decisionNote || commonT('labels.noNotes')}
1588
+ </div>
1589
+ </div>
1590
+
1591
+ <div>
1592
+ <div className="text-xs font-medium uppercase text-muted-foreground">
1593
+ {t('details.entriesTitle')}
1594
+ </div>
1595
+ <div className="mt-2 space-y-3">
1596
+ {(selectedTimesheet.entries ?? []).length ? (
1597
+ (selectedTimesheet.entries ?? []).map((entry) => (
1598
+ <div key={entry.id} className="rounded-lg border p-3">
1599
+ <div className="flex flex-wrap items-start justify-between gap-3">
1600
+ <div>
1601
+ <div className="font-medium">
1602
+ {entry.taskName ||
1603
+ entry.activityLabel ||
1604
+ commonT('labels.unassigned')}
1605
+ </div>
1606
+ <div className="text-xs text-muted-foreground">
1607
+ {[entry.projectName, entry.roleLabel]
1608
+ .filter(Boolean)
1609
+ .join(' • ') || commonT('labels.unassigned')}
1610
+ </div>
1611
+ </div>
1612
+ <div className="text-sm text-muted-foreground">
1613
+ {formatEntryDuration(
1614
+ entry.durationMinutes,
1615
+ entry.hours
1616
+ )}
1617
+ </div>
1618
+ </div>
1619
+ <div className="mt-2 text-xs text-muted-foreground">
1620
+ {formatDateLabel(entry.workDate)}
1621
+ </div>
1622
+ <div className="mt-2 text-sm">
1623
+ {entry.description || commonT('labels.noNotes')}
1624
+ </div>
1625
+ {canManageRow(selectedTimesheet) ? (
1626
+ <div className="mt-3 flex justify-end gap-2 border-t border-border/60 pt-3">
1627
+ <Button
1628
+ type="button"
1629
+ variant="outline"
1630
+ size="sm"
1631
+ className="cursor-pointer"
1632
+ onClick={() => openEditEntry(entry)}
1633
+ >
1634
+ <Pencil className="size-4" />
1635
+ {commonT('actions.edit')}
1636
+ </Button>
1637
+ <Button
1638
+ type="button"
1639
+ variant="outline"
1640
+ size="sm"
1641
+ className="cursor-pointer text-destructive hover:bg-destructive/10"
1642
+ onClick={() => setEntryToDelete(entry)}
1643
+ >
1644
+ <Trash2 className="size-4" />
1645
+ {commonT('actions.delete')}
1646
+ </Button>
1647
+ </div>
1648
+ ) : null}
1649
+ </div>
1650
+ ))
1651
+ ) : (
1652
+ <div className="rounded-lg border p-3 text-sm text-muted-foreground">
1653
+ {t('details.noEntries')}
1654
+ </div>
1655
+ )}
1656
+ </div>
1657
+ </div>
1658
+ </div>
1659
+ ) : null}
1660
+ </SheetContent>
1661
+ </Sheet>
1662
+
1663
+ <AlertDialog
1664
+ open={Boolean(entryToDelete)}
1665
+ onOpenChange={(open) => {
1666
+ if (!open && !isDeletingEntry) {
1667
+ setEntryToDelete(null);
1668
+ }
1669
+ }}
1670
+ >
1671
+ <AlertDialogContent>
1672
+ <AlertDialogHeader>
1673
+ <AlertDialogTitle>
1674
+ {t('messages.confirmDeleteTitle')}
1675
+ </AlertDialogTitle>
1676
+ <AlertDialogDescription>
1677
+ {t('messages.confirmDeleteDescription', {
1678
+ name:
1679
+ entryToDelete?.taskName ||
1680
+ entryToDelete?.activityLabel ||
1681
+ entryToDelete?.projectName ||
1682
+ `#${entryToDelete?.id ?? ''}`,
1683
+ })}
1684
+ </AlertDialogDescription>
1685
+ </AlertDialogHeader>
1686
+
1687
+ <AlertDialogFooter>
1688
+ <AlertDialogCancel disabled={isDeletingEntry}>
1689
+ {commonT('actions.cancel')}
1690
+ </AlertDialogCancel>
1691
+ <AlertDialogAction
1692
+ onClick={() => void handleDeleteEntry()}
1693
+ disabled={isDeletingEntry}
1694
+ >
1695
+ {isDeletingEntry ? (
1696
+ <Loader2 className="size-4 animate-spin" />
1697
+ ) : null}
1698
+ {commonT('actions.delete')}
1699
+ </AlertDialogAction>
1700
+ </AlertDialogFooter>
1701
+ </AlertDialogContent>
1702
+ </AlertDialog>
1703
+ </Page>
1704
+ );
1705
+ }