@hed-hog/operations 0.0.302 → 0.0.304

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 (167) hide show
  1. package/README.md +200 -43
  2. package/dist/controllers/operations-approvals.controller.d.ts +9 -0
  3. package/dist/controllers/operations-approvals.controller.d.ts.map +1 -0
  4. package/dist/controllers/operations-approvals.controller.js +64 -0
  5. package/dist/controllers/operations-approvals.controller.js.map +1 -0
  6. package/dist/controllers/operations-collaborators.controller.d.ts +223 -0
  7. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -0
  8. package/dist/controllers/operations-collaborators.controller.js +96 -0
  9. package/dist/controllers/operations-collaborators.controller.js.map +1 -0
  10. package/dist/controllers/operations-contracts.controller.d.ts +683 -0
  11. package/dist/controllers/operations-contracts.controller.d.ts.map +1 -0
  12. package/dist/controllers/operations-contracts.controller.js +198 -0
  13. package/dist/controllers/operations-contracts.controller.js.map +1 -0
  14. package/dist/controllers/operations-org-structure.controller.d.ts +108 -0
  15. package/dist/controllers/operations-org-structure.controller.d.ts.map +1 -0
  16. package/dist/controllers/operations-org-structure.controller.js +143 -0
  17. package/dist/controllers/operations-org-structure.controller.js.map +1 -0
  18. package/dist/controllers/operations-projects.controller.d.ts +169 -0
  19. package/dist/controllers/operations-projects.controller.d.ts.map +1 -0
  20. package/dist/controllers/operations-projects.controller.js +87 -0
  21. package/dist/controllers/operations-projects.controller.js.map +1 -0
  22. package/dist/controllers/operations-tasks.controller.d.ts +54 -0
  23. package/dist/controllers/operations-tasks.controller.d.ts.map +1 -0
  24. package/dist/controllers/operations-tasks.controller.js +79 -0
  25. package/dist/controllers/operations-tasks.controller.js.map +1 -0
  26. package/dist/controllers/operations-timesheets.controller.d.ts +99 -0
  27. package/dist/controllers/operations-timesheets.controller.d.ts.map +1 -0
  28. package/dist/controllers/operations-timesheets.controller.js +154 -0
  29. package/dist/controllers/operations-timesheets.controller.js.map +1 -0
  30. package/dist/dto/create-collaborator-type.dto.d.ts +10 -0
  31. package/dist/dto/create-collaborator-type.dto.d.ts.map +1 -0
  32. package/dist/dto/create-collaborator-type.dto.js +56 -0
  33. package/dist/dto/create-collaborator-type.dto.js.map +1 -0
  34. package/dist/dto/create-collaborator.dto.d.ts +42 -0
  35. package/dist/dto/create-collaborator.dto.d.ts.map +1 -0
  36. package/dist/dto/create-collaborator.dto.js +228 -0
  37. package/dist/dto/create-collaborator.dto.js.map +1 -0
  38. package/dist/dto/create-schedule-adjustment-request.dto.d.ts +17 -0
  39. package/dist/dto/create-schedule-adjustment-request.dto.d.ts.map +1 -0
  40. package/dist/dto/create-schedule-adjustment-request.dto.js +89 -0
  41. package/dist/dto/create-schedule-adjustment-request.dto.js.map +1 -0
  42. package/dist/dto/create-task.dto.d.ts +8 -0
  43. package/dist/dto/create-task.dto.d.ts.map +1 -0
  44. package/dist/dto/create-task.dto.js +50 -0
  45. package/dist/dto/create-task.dto.js.map +1 -0
  46. package/dist/dto/create-time-off-request.dto.d.ts +9 -0
  47. package/dist/dto/create-time-off-request.dto.d.ts.map +1 -0
  48. package/dist/dto/create-time-off-request.dto.js +54 -0
  49. package/dist/dto/create-time-off-request.dto.js.map +1 -0
  50. package/dist/dto/create-timesheet-entry.dto.d.ts +12 -0
  51. package/dist/dto/create-timesheet-entry.dto.d.ts.map +1 -0
  52. package/dist/dto/create-timesheet-entry.dto.js +75 -0
  53. package/dist/dto/create-timesheet-entry.dto.js.map +1 -0
  54. package/dist/dto/list-collaborator-types.dto.d.ts +4 -0
  55. package/dist/dto/list-collaborator-types.dto.d.ts.map +1 -0
  56. package/dist/dto/list-collaborator-types.dto.js +29 -0
  57. package/dist/dto/list-collaborator-types.dto.js.map +1 -0
  58. package/dist/dto/list-collaborators.dto.d.ts +8 -0
  59. package/dist/dto/list-collaborators.dto.d.ts.map +1 -0
  60. package/dist/dto/list-collaborators.dto.js +42 -0
  61. package/dist/dto/list-collaborators.dto.js.map +1 -0
  62. package/dist/dto/list-project-options.dto.d.ts +4 -0
  63. package/dist/dto/list-project-options.dto.d.ts.map +1 -0
  64. package/dist/dto/list-project-options.dto.js +8 -0
  65. package/dist/dto/list-project-options.dto.js.map +1 -0
  66. package/dist/dto/list-tasks.dto.d.ts +7 -0
  67. package/dist/dto/list-tasks.dto.d.ts.map +1 -0
  68. package/dist/dto/list-tasks.dto.js +38 -0
  69. package/dist/dto/list-tasks.dto.js.map +1 -0
  70. package/dist/dto/list-timesheet-entries.dto.d.ts +10 -0
  71. package/dist/dto/list-timesheet-entries.dto.d.ts.map +1 -0
  72. package/dist/dto/list-timesheet-entries.dto.js +54 -0
  73. package/dist/dto/list-timesheet-entries.dto.js.map +1 -0
  74. package/dist/dto/update-collaborator-type.dto.d.ts +4 -0
  75. package/dist/dto/update-collaborator-type.dto.d.ts.map +1 -0
  76. package/dist/dto/update-collaborator-type.dto.js +8 -0
  77. package/dist/dto/update-collaborator-type.dto.js.map +1 -0
  78. package/dist/dto/update-collaborator.dto.d.ts +4 -0
  79. package/dist/dto/update-collaborator.dto.d.ts.map +1 -0
  80. package/dist/dto/update-collaborator.dto.js +8 -0
  81. package/dist/dto/update-collaborator.dto.js.map +1 -0
  82. package/dist/dto/update-task.dto.d.ts +8 -0
  83. package/dist/dto/update-task.dto.d.ts.map +1 -0
  84. package/dist/dto/update-task.dto.js +51 -0
  85. package/dist/dto/update-task.dto.js.map +1 -0
  86. package/dist/operations.controller.d.ts +0 -1045
  87. package/dist/operations.controller.d.ts.map +1 -1
  88. package/dist/operations.controller.js +0 -429
  89. package/dist/operations.controller.js.map +1 -1
  90. package/dist/operations.module.d.ts.map +1 -1
  91. package/dist/operations.module.js +23 -2
  92. package/dist/operations.module.js.map +1 -1
  93. package/dist/operations.service.d.ts +373 -8
  94. package/dist/operations.service.d.ts.map +1 -1
  95. package/dist/operations.service.js +1598 -111
  96. package/dist/operations.service.js.map +1 -1
  97. package/dist/operations.service.spec.js +315 -1
  98. package/dist/operations.service.spec.js.map +1 -1
  99. package/dist/services/shared/operations-access.service.d.ts +16 -0
  100. package/dist/services/shared/operations-access.service.d.ts.map +1 -0
  101. package/dist/services/shared/operations-access.service.js +48 -0
  102. package/dist/services/shared/operations-access.service.js.map +1 -0
  103. package/hedhog/data/dashboard.yaml +20 -0
  104. package/hedhog/data/dashboard_component.yaml +274 -0
  105. package/hedhog/data/dashboard_component_role.yaml +174 -0
  106. package/hedhog/data/dashboard_item.yaml +299 -0
  107. package/hedhog/data/dashboard_role.yaml +20 -0
  108. package/hedhog/data/menu.yaml +30 -13
  109. package/hedhog/data/operations_collaborator_type.yaml +76 -0
  110. package/hedhog/data/route.yaml +183 -0
  111. package/hedhog/frontend/app/_components/async-options-combobox.tsx.ejs +231 -0
  112. package/hedhog/frontend/app/_components/collaborator-details-screen.tsx.ejs +134 -49
  113. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +772 -93
  114. package/hedhog/frontend/app/_components/department-select-with-create.tsx.ejs +38 -16
  115. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +875 -632
  116. package/hedhog/frontend/app/_components/timesheet-task-create-sheet.tsx.ejs +213 -0
  117. package/hedhog/frontend/app/_lib/api.ts.ejs +30 -1
  118. package/hedhog/frontend/app/_lib/types.ts.ejs +142 -39
  119. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +33 -2
  120. package/hedhog/frontend/app/approvals/page.tsx.ejs +116 -98
  121. package/hedhog/frontend/app/collaborator-types/page.tsx.ejs +502 -0
  122. package/hedhog/frontend/app/collaborators/page.tsx.ejs +109 -68
  123. package/hedhog/frontend/app/contracts/page.tsx.ejs +99 -102
  124. package/hedhog/frontend/app/contracts/templates/page.tsx.ejs +98 -102
  125. package/hedhog/frontend/app/departments/page.tsx.ejs +96 -75
  126. package/hedhog/frontend/app/projects/page.tsx.ejs +137 -127
  127. package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +244 -120
  128. package/hedhog/frontend/app/team/page.tsx.ejs +15 -2
  129. package/hedhog/frontend/app/time-off/page.tsx.ejs +158 -82
  130. package/hedhog/frontend/app/timesheets/page.tsx.ejs +814 -357
  131. package/hedhog/frontend/messages/en.json +243 -51
  132. package/hedhog/frontend/messages/pt.json +458 -268
  133. package/hedhog/table/operations_collaborator.yaml +26 -13
  134. package/hedhog/table/operations_collaborator_equity_participation.yaml +43 -0
  135. package/hedhog/table/operations_collaborator_type.yaml +33 -0
  136. package/hedhog/table/operations_job_title.yaml +24 -0
  137. package/hedhog/table/operations_project_assignment.yaml +9 -0
  138. package/hedhog/table/operations_project_role.yaml +39 -0
  139. package/hedhog/table/operations_task.yaml +30 -0
  140. package/hedhog/table/operations_timesheet_entry.yaml +12 -0
  141. package/package.json +6 -6
  142. package/src/controllers/operations-approvals.controller.ts +24 -0
  143. package/src/controllers/operations-collaborators.controller.ts +60 -0
  144. package/src/controllers/operations-contracts.controller.ts +138 -0
  145. package/src/controllers/operations-org-structure.controller.ts +92 -0
  146. package/src/controllers/operations-projects.controller.ts +50 -0
  147. package/src/controllers/operations-tasks.controller.ts +52 -0
  148. package/src/controllers/operations-timesheets.controller.ts +100 -0
  149. package/src/dto/create-collaborator-type.dto.ts +43 -0
  150. package/src/dto/create-collaborator.dto.ts +223 -0
  151. package/src/dto/create-schedule-adjustment-request.dto.ts +91 -0
  152. package/src/dto/create-task.dto.ts +35 -0
  153. package/src/dto/create-time-off-request.dto.ts +53 -0
  154. package/src/dto/create-timesheet-entry.dto.ts +67 -0
  155. package/src/dto/list-collaborator-types.dto.ts +15 -0
  156. package/src/dto/list-collaborators.dto.ts +30 -0
  157. package/src/dto/list-project-options.dto.ts +3 -0
  158. package/src/dto/list-tasks.dto.ts +25 -0
  159. package/src/dto/list-timesheet-entries.dto.ts +40 -0
  160. package/src/dto/update-collaborator-type.dto.ts +3 -0
  161. package/src/dto/update-collaborator.dto.ts +3 -0
  162. package/src/dto/update-task.dto.ts +36 -0
  163. package/src/operations.controller.ts +1 -278
  164. package/src/operations.module.ts +23 -2
  165. package/src/operations.service.spec.ts +450 -0
  166. package/src/operations.service.ts +4641 -2163
  167. package/src/services/shared/operations-access.service.ts +52 -0
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { EmptyState, Page, SearchBar } from '@/components/entity-list';
4
4
  import { Button } from '@/components/ui/button';
5
- import { Card, CardContent } from '@/components/ui/card';
6
5
  import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
7
6
  import {
8
7
  Sheet,
@@ -256,99 +255,94 @@ export default function OperationsContractTemplatesPage() {
256
255
  />
257
256
 
258
257
  {isLoading ? (
259
- <Card className="py-0">
260
- <CardContent className="p-6 text-sm text-muted-foreground">
261
- {commonT('actions.refresh')}...
262
- </CardContent>
263
- </Card>
258
+ <div className="rounded-md border px-4 py-6 text-sm text-muted-foreground">
259
+ {commonT('actions.refresh')}...
260
+ </div>
264
261
  ) : filteredTemplates.length ? (
265
- <Card className="py-0">
266
- <CardContent className="p-0">
267
- <div className="overflow-x-auto rounded-md border">
268
- <Table>
269
- <TableHeader>
270
- <TableRow>
271
- <TableHead>{t('columns.name')}</TableHead>
272
- <TableHead>{t('columns.code')}</TableHead>
273
- <TableHead>{t('columns.type')}</TableHead>
274
- <TableHead>{t('columns.usageCount')}</TableHead>
275
- <TableHead>{commonT('labels.billingModel')}</TableHead>
276
- <TableHead>{t('columns.updatedAt')}</TableHead>
277
- <TableHead>{commonT('labels.status')}</TableHead>
278
- <TableHead className="text-right">
279
- {commonT('labels.actions')}
280
- </TableHead>
281
- </TableRow>
282
- </TableHeader>
283
- <TableBody>
284
- {filteredTemplates.map((template) => (
285
- <TableRow key={template.id}>
286
- <TableCell>
287
- <div className="space-y-1">
288
- <div className="font-medium">{template.name}</div>
289
- <div className="max-w-md text-xs text-muted-foreground">
290
- {template.description ||
291
- commonT('labels.notAvailable')}
292
- </div>
293
- </div>
294
- </TableCell>
295
- <TableCell>{template.code || '—'}</TableCell>
296
- <TableCell>
297
- {formatEnumLabel(template.contractType)}
298
- </TableCell>
299
- <TableCell>{template.usageCount ?? 0}</TableCell>
300
- <TableCell>
301
- {formatEnumLabel(template.billingModel)}
302
- </TableCell>
303
- <TableCell>{formatDate(template.updatedAt)}</TableCell>
304
- <TableCell>
305
- <StatusBadge
306
- label={formatEnumLabel(template.status)}
307
- className={getStatusBadgeClass(template.status)}
308
- />
309
- </TableCell>
310
- <TableCell>
311
- <div className="flex justify-end gap-2">
312
- <Button
313
- type="button"
314
- variant="outline"
315
- size="sm"
316
- className="cursor-pointer"
317
- asChild
318
- >
319
- <Link href={`/operations/contracts?template=${template.id}`}>
320
- {commonT('actions.useTemplate')}
321
- </Link>
322
- </Button>
323
- <Button
324
- type="button"
325
- variant="outline"
326
- size="icon"
327
- className="cursor-pointer"
328
- onClick={() => openEditSheet(template)}
329
- >
330
- <Pencil className="size-4" />
331
- </Button>
332
- <Button
333
- type="button"
334
- variant="outline"
335
- size="sm"
336
- className="cursor-pointer"
337
- onClick={() => void toggleTemplateStatus(template)}
338
- >
339
- {template.status === 'active'
340
- ? commonT('actions.deactivate')
341
- : commonT('actions.activate')}
342
- </Button>
343
- </div>
344
- </TableCell>
345
- </TableRow>
346
- ))}
347
- </TableBody>
348
- </Table>
349
- </div>
350
- </CardContent>
351
- </Card>
262
+ <div className="overflow-x-auto rounded-md border">
263
+ <Table>
264
+ <TableHeader>
265
+ <TableRow>
266
+ <TableHead>{t('columns.name')}</TableHead>
267
+ <TableHead>{t('columns.code')}</TableHead>
268
+ <TableHead>{t('columns.type')}</TableHead>
269
+ <TableHead>{t('columns.usageCount')}</TableHead>
270
+ <TableHead>{commonT('labels.billingModel')}</TableHead>
271
+ <TableHead>{t('columns.updatedAt')}</TableHead>
272
+ <TableHead>{commonT('labels.status')}</TableHead>
273
+ <TableHead className="text-right">
274
+ {commonT('labels.actions')}
275
+ </TableHead>
276
+ </TableRow>
277
+ </TableHeader>
278
+ <TableBody>
279
+ {filteredTemplates.map((template) => (
280
+ <TableRow key={template.id}>
281
+ <TableCell>
282
+ <div className="space-y-1">
283
+ <div className="font-medium">{template.name}</div>
284
+ <div className="max-w-md text-xs text-muted-foreground">
285
+ {template.description || commonT('labels.notAvailable')}
286
+ </div>
287
+ </div>
288
+ </TableCell>
289
+ <TableCell>{template.code || '—'}</TableCell>
290
+ <TableCell>
291
+ {formatEnumLabel(template.contractType)}
292
+ </TableCell>
293
+ <TableCell>{template.usageCount ?? 0}</TableCell>
294
+ <TableCell>
295
+ {formatEnumLabel(template.billingModel)}
296
+ </TableCell>
297
+ <TableCell>{formatDate(template.updatedAt)}</TableCell>
298
+ <TableCell>
299
+ <StatusBadge
300
+ label={formatEnumLabel(template.status)}
301
+ className={getStatusBadgeClass(template.status)}
302
+ />
303
+ </TableCell>
304
+ <TableCell>
305
+ <div className="flex justify-end gap-2">
306
+ <Button
307
+ type="button"
308
+ variant="outline"
309
+ size="sm"
310
+ className="cursor-pointer"
311
+ asChild
312
+ >
313
+ <Link
314
+ href={`/operations/contracts?template=${template.id}`}
315
+ >
316
+ {commonT('actions.useTemplate')}
317
+ </Link>
318
+ </Button>
319
+ <Button
320
+ type="button"
321
+ variant="outline"
322
+ size="icon"
323
+ className="cursor-pointer"
324
+ onClick={() => openEditSheet(template)}
325
+ >
326
+ <Pencil className="size-4" />
327
+ </Button>
328
+ <Button
329
+ type="button"
330
+ variant="outline"
331
+ size="sm"
332
+ className="cursor-pointer"
333
+ onClick={() => void toggleTemplateStatus(template)}
334
+ >
335
+ {template.status === 'active'
336
+ ? commonT('actions.deactivate')
337
+ : commonT('actions.activate')}
338
+ </Button>
339
+ </div>
340
+ </TableCell>
341
+ </TableRow>
342
+ ))}
343
+ </TableBody>
344
+ </Table>
345
+ </div>
352
346
  ) : (
353
347
  <EmptyState
354
348
  icon={<FileStack className="size-12" />}
@@ -368,15 +362,17 @@ export default function OperationsContractTemplatesPage() {
368
362
  <SheetDescription>{t('sheet.description')}</SheetDescription>
369
363
  </SheetHeader>
370
364
 
371
- <ContractTemplateFormScreen
372
- templateId={editingTemplate?.id}
373
- onCancel={() => setIsSheetOpen(false)}
374
- onSaved={async () => {
375
- setIsSheetOpen(false);
376
- setEditingTemplate(null);
377
- await refetch();
378
- }}
379
- />
365
+ <div className="px-4">
366
+ <ContractTemplateFormScreen
367
+ templateId={editingTemplate?.id}
368
+ onCancel={() => setIsSheetOpen(false)}
369
+ onSaved={async () => {
370
+ setIsSheetOpen(false);
371
+ setEditingTemplate(null);
372
+ await refetch();
373
+ }}
374
+ />
375
+ </div>
380
376
  </SheetContent>
381
377
  </Sheet>
382
378
  </Page>
@@ -2,7 +2,6 @@
2
2
 
3
3
  import { EmptyState, Page, SearchBar } from '@/components/entity-list';
4
4
  import { Button } from '@/components/ui/button';
5
- import { Card, CardContent } from '@/components/ui/card';
6
5
  import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
7
6
  import {
8
7
  Sheet,
@@ -51,10 +50,13 @@ export default function OperationsDepartmentsPage() {
51
50
  const { request, showToastHandler, currentLocaleCode } = useApp();
52
51
  const access = useOperationsAccess();
53
52
  const [search, setSearch] = useState('');
54
- const [statusFilter, setStatusFilter] = useState<'all' | 'active' | 'inactive'>('all');
53
+ const [statusFilter, setStatusFilter] = useState<
54
+ 'all' | 'active' | 'inactive'
55
+ >('all');
55
56
  const [isSheetOpen, setIsSheetOpen] = useState(false);
56
57
  const [isSaving, setIsSaving] = useState(false);
57
- const [editingDepartment, setEditingDepartment] = useState<OperationsDepartment | null>(null);
58
+ const [editingDepartment, setEditingDepartment] =
59
+ useState<OperationsDepartment | null>(null);
58
60
  const [form, setForm] = useState<DepartmentFormState>(EMPTY_FORM_STATE);
59
61
 
60
62
  const {
@@ -65,7 +67,10 @@ export default function OperationsDepartmentsPage() {
65
67
  queryKey: ['operations-departments-list', currentLocaleCode],
66
68
  enabled: access.isDirector,
67
69
  queryFn: () =>
68
- fetchOperations<OperationsDepartment[]>(request, '/operations/departments'),
70
+ fetchOperations<OperationsDepartment[]>(
71
+ request,
72
+ '/operations/departments'
73
+ ),
69
74
  });
70
75
 
71
76
  const filteredDepartments = useMemo(
@@ -210,7 +215,9 @@ export default function OperationsDepartmentsPage() {
210
215
  current={t('breadcrumb')}
211
216
  actions={
212
217
  <Button variant="outline" size="sm" asChild>
213
- <Link href="/operations/collaborators">{commonT('actions.back')}</Link>
218
+ <Link href="/operations/collaborators">
219
+ {commonT('actions.back')}
220
+ </Link>
214
221
  </Button>
215
222
  }
216
223
  />
@@ -237,7 +244,9 @@ export default function OperationsDepartmentsPage() {
237
244
  actions={
238
245
  <div className="flex flex-wrap gap-2">
239
246
  <Button variant="outline" size="sm" asChild>
240
- <Link href="/operations/collaborators">{commonT('actions.back')}</Link>
247
+ <Link href="/operations/collaborators">
248
+ {commonT('actions.back')}
249
+ </Link>
241
250
  </Button>
242
251
  <Button size="sm" onClick={openCreateSheet}>
243
252
  {commonT('actions.create')}
@@ -260,7 +269,9 @@ export default function OperationsDepartmentsPage() {
260
269
  type: 'select',
261
270
  value: statusFilter,
262
271
  onChange: (value) =>
263
- setStatusFilter((value as 'all' | 'active' | 'inactive') ?? 'all'),
272
+ setStatusFilter(
273
+ (value as 'all' | 'active' | 'inactive') ?? 'all'
274
+ ),
264
275
  placeholder: commonT('labels.status'),
265
276
  options: [
266
277
  { value: 'all', label: commonT('filters.allStatuses') },
@@ -273,70 +284,70 @@ export default function OperationsDepartmentsPage() {
273
284
  </div>
274
285
 
275
286
  {isLoading ? (
276
- <Card className="py-0">
277
- <CardContent className="p-6 text-sm text-muted-foreground">
278
- {commonT('actions.refresh')}...
279
- </CardContent>
280
- </Card>
287
+ <div className="rounded-md border px-4 py-6 text-sm text-muted-foreground">
288
+ {commonT('actions.refresh')}...
289
+ </div>
281
290
  ) : filteredDepartments.length > 0 ? (
282
- <Card className="py-0">
283
- <CardContent className="p-0">
284
- <div className="overflow-x-auto rounded-md border">
285
- <Table>
286
- <TableHeader>
287
- <TableRow>
288
- <TableHead>{t('columns.name')}</TableHead>
289
- <TableHead>{t('columns.code')}</TableHead>
290
- <TableHead>{t('columns.description')}</TableHead>
291
- <TableHead>{t('columns.collaborators')}</TableHead>
292
- <TableHead>{commonT('labels.status')}</TableHead>
293
- <TableHead className="text-right">{commonT('labels.actions')}</TableHead>
294
- </TableRow>
295
- </TableHeader>
296
- <TableBody>
297
- {filteredDepartments.map((department) => (
298
- <TableRow key={department.id}>
299
- <TableCell className="font-medium">{department.name}</TableCell>
300
- <TableCell>{department.code || '—'}</TableCell>
301
- <TableCell className="max-w-md text-sm text-muted-foreground">
302
- {department.description || commonT('labels.notAvailable')}
303
- </TableCell>
304
- <TableCell>{Number(department.collaboratorCount ?? 0)}</TableCell>
305
- <TableCell>
306
- <StatusBadge
307
- label={formatEnumLabel(department.status)}
308
- className={getStatusBadgeClass(department.status)}
309
- />
310
- </TableCell>
311
- <TableCell>
312
- <div className="flex justify-end gap-2">
313
- <Button
314
- variant="outline"
315
- size="icon"
316
- className="cursor-pointer"
317
- onClick={() => openEditSheet(department)}
318
- >
319
- <Pencil className="size-4" />
320
- </Button>
321
- <Button
322
- variant="outline"
323
- size="sm"
324
- className="cursor-pointer"
325
- onClick={() => void toggleStatus(department)}
326
- >
327
- {department.status === 'inactive'
328
- ? commonT('actions.activate')
329
- : commonT('actions.deactivate')}
330
- </Button>
331
- </div>
332
- </TableCell>
333
- </TableRow>
334
- ))}
335
- </TableBody>
336
- </Table>
337
- </div>
338
- </CardContent>
339
- </Card>
291
+ <div className="overflow-x-auto rounded-md border">
292
+ <Table>
293
+ <TableHeader>
294
+ <TableRow>
295
+ <TableHead>{t('columns.name')}</TableHead>
296
+ <TableHead>{t('columns.code')}</TableHead>
297
+ <TableHead>{t('columns.description')}</TableHead>
298
+ <TableHead>{t('columns.collaborators')}</TableHead>
299
+ <TableHead>{commonT('labels.status')}</TableHead>
300
+ <TableHead className="text-right">
301
+ {commonT('labels.actions')}
302
+ </TableHead>
303
+ </TableRow>
304
+ </TableHeader>
305
+ <TableBody>
306
+ {filteredDepartments.map((department) => (
307
+ <TableRow key={department.id}>
308
+ <TableCell className="font-medium">
309
+ {department.name}
310
+ </TableCell>
311
+ <TableCell>{department.code || ''}</TableCell>
312
+ <TableCell className="max-w-md text-sm text-muted-foreground">
313
+ {department.description || commonT('labels.notAvailable')}
314
+ </TableCell>
315
+ <TableCell>
316
+ {Number(department.collaboratorCount ?? 0)}
317
+ </TableCell>
318
+ <TableCell>
319
+ <StatusBadge
320
+ label={formatEnumLabel(department.status)}
321
+ className={getStatusBadgeClass(department.status)}
322
+ />
323
+ </TableCell>
324
+ <TableCell>
325
+ <div className="flex justify-end gap-2">
326
+ <Button
327
+ variant="outline"
328
+ size="icon"
329
+ className="cursor-pointer"
330
+ onClick={() => openEditSheet(department)}
331
+ >
332
+ <Pencil className="size-4" />
333
+ </Button>
334
+ <Button
335
+ variant="outline"
336
+ size="sm"
337
+ className="cursor-pointer"
338
+ onClick={() => void toggleStatus(department)}
339
+ >
340
+ {department.status === 'inactive'
341
+ ? commonT('actions.activate')
342
+ : commonT('actions.deactivate')}
343
+ </Button>
344
+ </div>
345
+ </TableCell>
346
+ </TableRow>
347
+ ))}
348
+ </TableBody>
349
+ </Table>
350
+ </div>
340
351
  ) : (
341
352
  <EmptyState
342
353
  icon={<Building2 className="size-12" />}
@@ -351,13 +362,15 @@ export default function OperationsDepartmentsPage() {
351
362
  <SheetContent className="w-full overflow-y-auto sm:max-w-xl">
352
363
  <SheetHeader>
353
364
  <SheetTitle>
354
- {editingDepartment ? t('sheet.editTitle') : t('sheet.createTitle')}
365
+ {editingDepartment
366
+ ? t('sheet.editTitle')
367
+ : t('sheet.createTitle')}
355
368
  </SheetTitle>
356
369
  <SheetDescription>{t('sheet.description')}</SheetDescription>
357
370
  </SheetHeader>
358
371
 
359
372
  <form
360
- className="mt-6 space-y-4"
373
+ className="mt-6 space-y-4 px-4"
361
374
  onSubmit={(event) => {
362
375
  event.preventDefault();
363
376
  void saveDepartment();
@@ -390,20 +403,28 @@ export default function OperationsDepartmentsPage() {
390
403
  </div>
391
404
 
392
405
  <div className="space-y-2">
393
- <label className="text-sm font-medium" htmlFor="department-description">
406
+ <label
407
+ className="text-sm font-medium"
408
+ htmlFor="department-description"
409
+ >
394
410
  {t('form.description')}
395
411
  </label>
396
412
  <textarea
397
413
  id="department-description"
398
414
  value={form.description}
399
- onChange={(event) => updateForm('description', event.target.value)}
415
+ onChange={(event) =>
416
+ updateForm('description', event.target.value)
417
+ }
400
418
  className="min-h-24 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
401
419
  placeholder={t('form.description')}
402
420
  />
403
421
  </div>
404
422
 
405
423
  <div className="space-y-2">
406
- <label className="text-sm font-medium" htmlFor="department-status">
424
+ <label
425
+ className="text-sm font-medium"
426
+ htmlFor="department-status"
427
+ >
407
428
  {t('form.status')}
408
429
  </label>
409
430
  <select