@hed-hog/operations 0.0.294 → 0.0.296

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 (126) hide show
  1. package/dist/operations.controller.d.ts +415 -0
  2. package/dist/operations.controller.d.ts.map +1 -0
  3. package/dist/operations.controller.js +333 -0
  4. package/dist/operations.controller.js.map +1 -0
  5. package/dist/operations.module.d.ts.map +1 -1
  6. package/dist/operations.module.js +4 -3
  7. package/dist/operations.module.js.map +1 -1
  8. package/dist/operations.service.d.ts +589 -153
  9. package/dist/operations.service.d.ts.map +1 -1
  10. package/dist/operations.service.js +2229 -100
  11. package/dist/operations.service.js.map +1 -1
  12. package/hedhog/data/menu.yaml +198 -251
  13. package/hedhog/data/role.yaml +23 -14
  14. package/hedhog/data/route.yaml +317 -143
  15. package/hedhog/frontend/app/_components/collaborator-details-screen.tsx.ejs +310 -0
  16. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +631 -0
  17. package/hedhog/frontend/app/_components/contract-details-screen.tsx.ejs +132 -0
  18. package/hedhog/frontend/app/_components/contract-form-screen.tsx.ejs +558 -0
  19. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +291 -0
  20. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +689 -0
  21. package/hedhog/frontend/app/_lib/api.ts.ejs +32 -0
  22. package/hedhog/frontend/app/_lib/hooks/use-operations-access.ts.ejs +44 -0
  23. package/hedhog/frontend/app/_lib/types.ts.ejs +360 -0
  24. package/hedhog/frontend/app/_lib/utils/format.ts.ejs +129 -25
  25. package/hedhog/frontend/app/_lib/utils/forms.ts.ejs +14 -0
  26. package/hedhog/frontend/app/approvals/page.tsx.ejs +386 -147
  27. package/hedhog/frontend/app/collaborators/[id]/edit/page.tsx.ejs +11 -0
  28. package/hedhog/frontend/app/collaborators/[id]/page.tsx.ejs +11 -0
  29. package/hedhog/frontend/app/collaborators/new/page.tsx.ejs +5 -0
  30. package/hedhog/frontend/app/collaborators/page.tsx.ejs +261 -0
  31. package/hedhog/frontend/app/contracts/[id]/edit/page.tsx.ejs +11 -0
  32. package/hedhog/frontend/app/contracts/[id]/page.tsx.ejs +11 -108
  33. package/hedhog/frontend/app/contracts/new/page.tsx.ejs +17 -0
  34. package/hedhog/frontend/app/contracts/page.tsx.ejs +262 -181
  35. package/hedhog/frontend/app/page.tsx.ejs +319 -177
  36. package/hedhog/frontend/app/projects/[id]/edit/page.tsx.ejs +11 -0
  37. package/hedhog/frontend/app/projects/[id]/page.tsx.ejs +11 -936
  38. package/hedhog/frontend/app/projects/new/page.tsx.ejs +5 -0
  39. package/hedhog/frontend/app/projects/page.tsx.ejs +236 -1074
  40. package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +418 -0
  41. package/hedhog/frontend/app/team/page.tsx.ejs +339 -0
  42. package/hedhog/frontend/app/time-off/page.tsx.ejs +328 -0
  43. package/hedhog/frontend/app/timesheets/page.tsx.ejs +636 -126
  44. package/hedhog/frontend/messages/en.json +648 -454
  45. package/hedhog/frontend/messages/pt.json +647 -454
  46. package/hedhog/table/operations_approval.yaml +49 -0
  47. package/hedhog/table/operations_approval_history.yaml +29 -0
  48. package/hedhog/table/{operations_employee.yaml → operations_collaborator.yaml} +67 -64
  49. package/hedhog/table/operations_collaborator_schedule_day.yaml +34 -0
  50. package/hedhog/table/operations_contract.yaml +100 -48
  51. package/hedhog/table/operations_contract_document.yaml +39 -0
  52. package/hedhog/table/operations_contract_financial_term.yaml +40 -0
  53. package/hedhog/table/operations_contract_history.yaml +27 -0
  54. package/hedhog/table/operations_contract_party.yaml +46 -0
  55. package/hedhog/table/operations_contract_revision.yaml +38 -0
  56. package/hedhog/table/operations_contract_signature.yaml +38 -0
  57. package/hedhog/table/operations_project.yaml +54 -50
  58. package/hedhog/table/{operations_allocation.yaml → operations_project_assignment.yaml} +55 -52
  59. package/hedhog/table/operations_schedule_adjustment_day.yaml +34 -0
  60. package/hedhog/table/operations_schedule_adjustment_request.yaml +53 -0
  61. package/hedhog/table/operations_time_off_request.yaml +57 -0
  62. package/hedhog/table/operations_timesheet.yaml +41 -36
  63. package/hedhog/table/operations_timesheet_entry.yaml +40 -50
  64. package/package.json +7 -6
  65. package/src/operations.controller.ts +182 -0
  66. package/src/operations.module.ts +22 -21
  67. package/src/operations.service.ts +3595 -137
  68. package/hedhog/data/operations_career_level.yaml +0 -102
  69. package/hedhog/data/operations_career_track.yaml +0 -8
  70. package/hedhog/data/operations_certification.yaml +0 -38
  71. package/hedhog/data/operations_evaluation_cycle.yaml +0 -18
  72. package/hedhog/data/operations_performance_criterion.yaml +0 -48
  73. package/hedhog/frontend/app/_components/allocation-calendar.tsx.ejs +0 -56
  74. package/hedhog/frontend/app/_components/kanban-board.tsx.ejs +0 -626
  75. package/hedhog/frontend/app/_components/timesheet-entry-dialog.tsx.ejs +0 -142
  76. package/hedhog/frontend/app/_lib/hooks/use-operations-data.ts.ejs +0 -41
  77. package/hedhog/frontend/app/_lib/hooks/use-operations-growth-data.ts.ejs +0 -63
  78. package/hedhog/frontend/app/_lib/mocks/allocations.mock.ts.ejs +0 -74
  79. package/hedhog/frontend/app/_lib/mocks/contracts.mock.ts.ejs +0 -74
  80. package/hedhog/frontend/app/_lib/mocks/operations-growth.mock.ts.ejs +0 -824
  81. package/hedhog/frontend/app/_lib/mocks/projects.mock.ts.ejs +0 -455
  82. package/hedhog/frontend/app/_lib/mocks/tasks.mock.ts.ejs +0 -117
  83. package/hedhog/frontend/app/_lib/mocks/timesheets.mock.ts.ejs +0 -84
  84. package/hedhog/frontend/app/_lib/mocks/users.mock.ts.ejs +0 -67
  85. package/hedhog/frontend/app/_lib/services/contracts.service.ts.ejs +0 -10
  86. package/hedhog/frontend/app/_lib/services/operations-growth.service.ts.ejs +0 -31
  87. package/hedhog/frontend/app/_lib/services/projects.service.ts.ejs +0 -10
  88. package/hedhog/frontend/app/_lib/services/tasks.service.ts.ejs +0 -10
  89. package/hedhog/frontend/app/_lib/services/timesheets.service.ts.ejs +0 -10
  90. package/hedhog/frontend/app/_lib/types/operations-growth.ts.ejs +0 -209
  91. package/hedhog/frontend/app/_lib/types/operations.ts.ejs +0 -156
  92. package/hedhog/frontend/app/_lib/utils/growth.ts.ejs +0 -62
  93. package/hedhog/frontend/app/_lib/utils/metrics.ts.ejs +0 -103
  94. package/hedhog/frontend/app/_lib/utils/status.ts.ejs +0 -80
  95. package/hedhog/frontend/app/allocations/page.tsx.ejs +0 -155
  96. package/hedhog/frontend/app/career/page.tsx.ejs +0 -143
  97. package/hedhog/frontend/app/certifications/page.tsx.ejs +0 -202
  98. package/hedhog/frontend/app/evaluations/page.tsx.ejs +0 -278
  99. package/hedhog/frontend/app/goals/page.tsx.ejs +0 -171
  100. package/hedhog/frontend/app/growth/page.tsx.ejs +0 -288
  101. package/hedhog/frontend/app/manager/page.tsx.ejs +0 -175
  102. package/hedhog/frontend/app/rewards/page.tsx.ejs +0 -196
  103. package/hedhog/frontend/app/tasks/page.tsx.ejs +0 -999
  104. package/hedhog/table/operations_calibration_item.yaml +0 -61
  105. package/hedhog/table/operations_calibration_session.yaml +0 -25
  106. package/hedhog/table/operations_career_level.yaml +0 -75
  107. package/hedhog/table/operations_career_track.yaml +0 -21
  108. package/hedhog/table/operations_certification.yaml +0 -48
  109. package/hedhog/table/operations_employee_certification.yaml +0 -43
  110. package/hedhog/table/operations_employee_connect.yaml +0 -61
  111. package/hedhog/table/operations_employee_evaluation.yaml +0 -113
  112. package/hedhog/table/operations_employee_evaluation_item.yaml +0 -39
  113. package/hedhog/table/operations_employee_profile.yaml +0 -80
  114. package/hedhog/table/operations_employee_skill_matrix.yaml +0 -30
  115. package/hedhog/table/operations_evaluation_cycle.yaml +0 -31
  116. package/hedhog/table/operations_goal.yaml +0 -67
  117. package/hedhog/table/operations_goal_progress.yaml +0 -31
  118. package/hedhog/table/operations_performance_criterion.yaml +0 -29
  119. package/hedhog/table/operations_promotion_readiness.yaml +0 -49
  120. package/hedhog/table/operations_promotion_recommendation.yaml +0 -63
  121. package/hedhog/table/operations_public_recognition.yaml +0 -46
  122. package/hedhog/table/operations_reward.yaml +0 -100
  123. package/hedhog/table/operations_score_event.yaml +0 -81
  124. package/hedhog/table/operations_task.yaml +0 -60
  125. package/src/operations-data.controller.ts +0 -54
  126. package/src/operations-growth.controller.ts +0 -44
@@ -0,0 +1,310 @@
1
+ 'use client';
2
+
3
+ import { EmptyState, Page } from '@/components/entity-list';
4
+ import { Button } from '@/components/ui/button';
5
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
6
+ import {
7
+ Table,
8
+ TableBody,
9
+ TableCell,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ } from '@/components/ui/table';
14
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
15
+ import { Pencil, UserRound } from 'lucide-react';
16
+ import Link from 'next/link';
17
+ import { useTranslations } from 'next-intl';
18
+ import { OperationsHeader } from './operations-header';
19
+ import { SectionCard } from './section-card';
20
+ import { StatusBadge } from './status-badge';
21
+ import { fetchOperations } from '../_lib/api';
22
+ import type { OperationsCollaboratorDetails } from '../_lib/types';
23
+ import {
24
+ formatDate,
25
+ formatDateRange,
26
+ formatEnumLabel,
27
+ formatHours,
28
+ getStatusBadgeClass,
29
+ summarizeScheduleDays,
30
+ } from '../_lib/utils/format';
31
+ import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
32
+
33
+ export function CollaboratorDetailsScreen({
34
+ collaboratorId,
35
+ }: {
36
+ collaboratorId: number;
37
+ }) {
38
+ const t = useTranslations('operations.CollaboratorDetailsPage');
39
+ const commonT = useTranslations('operations.Common');
40
+ const { request, currentLocaleCode } = useApp();
41
+ const access = useOperationsAccess();
42
+
43
+ const { data: collaborator, refetch } = useQuery<OperationsCollaboratorDetails>({
44
+ queryKey: ['operations-collaborator-details', currentLocaleCode, collaboratorId],
45
+ queryFn: () =>
46
+ fetchOperations<OperationsCollaboratorDetails>(
47
+ request,
48
+ `/operations/collaborators/${collaboratorId}`
49
+ ),
50
+ });
51
+
52
+ if (!collaborator) {
53
+ return (
54
+ <Page>
55
+ <OperationsHeader
56
+ title={t('title')}
57
+ description={t('description')}
58
+ current={t('breadcrumb')}
59
+ />
60
+ <EmptyState
61
+ icon={<UserRound className="size-12" />}
62
+ title={commonT('states.emptyTitle')}
63
+ description={t('notFound')}
64
+ actionLabel={commonT('actions.refresh')}
65
+ onAction={() => void refetch()}
66
+ />
67
+ </Page>
68
+ );
69
+ }
70
+
71
+ const summaryCards = [
72
+ {
73
+ key: 'timesheets',
74
+ title: t('cards.timesheets'),
75
+ value: collaborator.timesheetSummary.totalTimesheets,
76
+ description: t('cards.timesheetsDescription', {
77
+ pending: collaborator.timesheetSummary.pendingTimesheets,
78
+ }),
79
+ },
80
+ {
81
+ key: 'hours',
82
+ title: t('cards.loggedHours'),
83
+ value: formatHours(collaborator.timesheetSummary.totalHours),
84
+ description: t('cards.loggedHoursDescription'),
85
+ },
86
+ {
87
+ key: 'timeOff',
88
+ title: t('cards.timeOff'),
89
+ value: collaborator.timeOffSummary.totalRequests,
90
+ description: t('cards.timeOffDescription', {
91
+ pending: collaborator.timeOffSummary.pendingRequests,
92
+ }),
93
+ },
94
+ {
95
+ key: 'assignments',
96
+ title: t('cards.assignments'),
97
+ value: collaborator.assignedProjects.length,
98
+ description: t('cards.assignmentsDescription'),
99
+ },
100
+ ];
101
+
102
+ return (
103
+ <Page>
104
+ <OperationsHeader
105
+ title={collaborator.displayName}
106
+ description={t('description')}
107
+ current={t('breadcrumb')}
108
+ actions={
109
+ access.isDirector ? (
110
+ <Button size="sm" asChild>
111
+ <Link href={`/operations/collaborators/${collaborator.id}/edit`}>
112
+ <Pencil className="size-4" />
113
+ {commonT('actions.edit')}
114
+ </Link>
115
+ </Button>
116
+ ) : undefined
117
+ }
118
+ />
119
+
120
+ <div className="grid gap-4 xl:grid-cols-4">
121
+ <SectionCard title={t('sections.profile')} className="xl:col-span-2">
122
+ <dl className="grid gap-3 md:grid-cols-2 text-sm">
123
+ <div>
124
+ <dt className="text-muted-foreground">{commonT('labels.collaborator')}</dt>
125
+ <dd className="font-medium">{collaborator.displayName}</dd>
126
+ </div>
127
+ <div>
128
+ <dt className="text-muted-foreground">{commonT('labels.collaboratorType')}</dt>
129
+ <dd className="font-medium">
130
+ {formatEnumLabel(collaborator.collaboratorType)}
131
+ </dd>
132
+ </div>
133
+ <div>
134
+ <dt className="text-muted-foreground">{commonT('labels.department')}</dt>
135
+ <dd className="font-medium">
136
+ {collaborator.department || commonT('labels.notAvailable')}
137
+ </dd>
138
+ </div>
139
+ <div>
140
+ <dt className="text-muted-foreground">{commonT('labels.title')}</dt>
141
+ <dd className="font-medium">
142
+ {collaborator.title || commonT('labels.notAvailable')}
143
+ </dd>
144
+ </div>
145
+ <div>
146
+ <dt className="text-muted-foreground">{commonT('labels.supervisor')}</dt>
147
+ <dd className="font-medium">
148
+ {collaborator.supervisorName || commonT('labels.notAssigned')}
149
+ </dd>
150
+ </div>
151
+ <div>
152
+ <dt className="text-muted-foreground">{commonT('labels.weeklyCapacity')}</dt>
153
+ <dd className="font-medium">
154
+ {formatHours(collaborator.weeklyCapacityHours)}
155
+ </dd>
156
+ </div>
157
+ <div>
158
+ <dt className="text-muted-foreground">{commonT('labels.startDate')}</dt>
159
+ <dd className="font-medium">{formatDate(collaborator.joinedAt)}</dd>
160
+ </div>
161
+ <div>
162
+ <dt className="text-muted-foreground">{commonT('labels.status')}</dt>
163
+ <dd className="font-medium">
164
+ <StatusBadge
165
+ label={formatEnumLabel(collaborator.status)}
166
+ className={getStatusBadgeClass(collaborator.status)}
167
+ />
168
+ </dd>
169
+ </div>
170
+ </dl>
171
+ </SectionCard>
172
+
173
+ <SectionCard title={t('sections.primaryContract')} className="xl:col-span-2">
174
+ {collaborator.relatedContracts.length > 0 ? (
175
+ <div className="space-y-3">
176
+ {collaborator.relatedContracts.slice(0, 2).map((contract) => (
177
+ <div
178
+ key={contract.id}
179
+ className="flex items-center justify-between rounded-lg border px-4 py-3"
180
+ >
181
+ <div>
182
+ <div className="font-medium">{contract.name}</div>
183
+ <div className="text-sm text-muted-foreground">
184
+ {contract.code} • {formatEnumLabel(contract.contractCategory)}
185
+ </div>
186
+ </div>
187
+ <div className="flex items-center gap-2">
188
+ <StatusBadge
189
+ label={formatEnumLabel(contract.status)}
190
+ className={getStatusBadgeClass(contract.status)}
191
+ />
192
+ <Button variant="outline" size="sm" asChild>
193
+ <Link href={`/operations/contracts?edit=${contract.id}`}>
194
+ {commonT('actions.openContract')}
195
+ </Link>
196
+ </Button>
197
+ </div>
198
+ </div>
199
+ ))}
200
+ </div>
201
+ ) : (
202
+ <p className="text-sm text-muted-foreground">{t('noContracts')}</p>
203
+ )}
204
+ </SectionCard>
205
+ </div>
206
+
207
+ <KpiCardsGrid items={summaryCards} />
208
+
209
+ <div className="grid gap-4 xl:grid-cols-2">
210
+ <SectionCard title={t('sections.projects')} description={t('sections.projectsDescription')}>
211
+ {collaborator.assignedProjects.length > 0 ? (
212
+ <div className="overflow-x-auto rounded-md border">
213
+ <Table>
214
+ <TableHeader>
215
+ <TableRow>
216
+ <TableHead>{commonT('labels.project')}</TableHead>
217
+ <TableHead>{commonT('labels.role')}</TableHead>
218
+ <TableHead>{commonT('labels.timeline')}</TableHead>
219
+ <TableHead>{commonT('labels.status')}</TableHead>
220
+ </TableRow>
221
+ </TableHeader>
222
+ <TableBody>
223
+ {collaborator.assignedProjects.map((project) => (
224
+ <TableRow key={project.id}>
225
+ <TableCell>
226
+ <div className="font-medium">{project.name}</div>
227
+ <div className="text-xs text-muted-foreground">
228
+ {project.code}
229
+ </div>
230
+ </TableCell>
231
+ <TableCell>{project.roleLabel || commonT('labels.notAssigned')}</TableCell>
232
+ <TableCell>{formatDateRange(project.startDate, project.endDate)}</TableCell>
233
+ <TableCell>
234
+ <StatusBadge
235
+ label={formatEnumLabel(project.status)}
236
+ className={getStatusBadgeClass(project.status)}
237
+ />
238
+ </TableCell>
239
+ </TableRow>
240
+ ))}
241
+ </TableBody>
242
+ </Table>
243
+ </div>
244
+ ) : (
245
+ <p className="text-sm text-muted-foreground">{t('noProjects')}</p>
246
+ )}
247
+ </SectionCard>
248
+
249
+ <SectionCard title={t('sections.schedule')} description={t('sections.scheduleDescription')}>
250
+ <p className="text-sm">
251
+ {summarizeScheduleDays(collaborator.weeklySchedule)}
252
+ </p>
253
+ </SectionCard>
254
+ </div>
255
+
256
+ <div className="grid gap-4 xl:grid-cols-2">
257
+ <SectionCard title={t('sections.timeOff')} description={t('sections.timeOffDescription')}>
258
+ <dl className="grid gap-3 md:grid-cols-3 text-sm">
259
+ <div>
260
+ <dt className="text-muted-foreground">{commonT('labels.total')}</dt>
261
+ <dd className="font-medium">{collaborator.timeOffSummary.totalRequests}</dd>
262
+ </div>
263
+ <div>
264
+ <dt className="text-muted-foreground">{commonT('labels.pending')}</dt>
265
+ <dd className="font-medium">{collaborator.timeOffSummary.pendingRequests}</dd>
266
+ </div>
267
+ <div>
268
+ <dt className="text-muted-foreground">{commonT('labels.approved')}</dt>
269
+ <dd className="font-medium">{collaborator.timeOffSummary.approvedRequests}</dd>
270
+ </div>
271
+ </dl>
272
+ </SectionCard>
273
+
274
+ <SectionCard
275
+ title={t('sections.scheduleAdjustments')}
276
+ description={t('sections.scheduleAdjustmentsDescription')}
277
+ >
278
+ {collaborator.scheduleAdjustmentRequests.length > 0 ? (
279
+ <div className="space-y-2">
280
+ {collaborator.scheduleAdjustmentRequests.map((request) => (
281
+ <div
282
+ key={request.id}
283
+ className="flex items-center justify-between rounded-lg border px-4 py-3 text-sm"
284
+ >
285
+ <div>
286
+ <div className="font-medium">
287
+ {formatEnumLabel(request.requestScope)}
288
+ </div>
289
+ <div className="text-muted-foreground">
290
+ {formatDateRange(
291
+ request.effectiveStartDate,
292
+ request.effectiveEndDate
293
+ )}
294
+ </div>
295
+ </div>
296
+ <StatusBadge
297
+ label={formatEnumLabel(request.status)}
298
+ className={getStatusBadgeClass(request.status)}
299
+ />
300
+ </div>
301
+ ))}
302
+ </div>
303
+ ) : (
304
+ <p className="text-sm text-muted-foreground">{t('noScheduleAdjustments')}</p>
305
+ )}
306
+ </SectionCard>
307
+ </div>
308
+ </Page>
309
+ );
310
+ }