@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.
- package/README.md +200 -43
- package/dist/controllers/operations-approvals.controller.d.ts +9 -0
- package/dist/controllers/operations-approvals.controller.d.ts.map +1 -0
- package/dist/controllers/operations-approvals.controller.js +64 -0
- package/dist/controllers/operations-approvals.controller.js.map +1 -0
- package/dist/controllers/operations-collaborators.controller.d.ts +223 -0
- package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -0
- package/dist/controllers/operations-collaborators.controller.js +96 -0
- package/dist/controllers/operations-collaborators.controller.js.map +1 -0
- package/dist/controllers/operations-contracts.controller.d.ts +683 -0
- package/dist/controllers/operations-contracts.controller.d.ts.map +1 -0
- package/dist/controllers/operations-contracts.controller.js +198 -0
- package/dist/controllers/operations-contracts.controller.js.map +1 -0
- package/dist/controllers/operations-org-structure.controller.d.ts +108 -0
- package/dist/controllers/operations-org-structure.controller.d.ts.map +1 -0
- package/dist/controllers/operations-org-structure.controller.js +143 -0
- package/dist/controllers/operations-org-structure.controller.js.map +1 -0
- package/dist/controllers/operations-projects.controller.d.ts +169 -0
- package/dist/controllers/operations-projects.controller.d.ts.map +1 -0
- package/dist/controllers/operations-projects.controller.js +87 -0
- package/dist/controllers/operations-projects.controller.js.map +1 -0
- package/dist/controllers/operations-tasks.controller.d.ts +54 -0
- package/dist/controllers/operations-tasks.controller.d.ts.map +1 -0
- package/dist/controllers/operations-tasks.controller.js +79 -0
- package/dist/controllers/operations-tasks.controller.js.map +1 -0
- package/dist/controllers/operations-timesheets.controller.d.ts +99 -0
- package/dist/controllers/operations-timesheets.controller.d.ts.map +1 -0
- package/dist/controllers/operations-timesheets.controller.js +154 -0
- package/dist/controllers/operations-timesheets.controller.js.map +1 -0
- package/dist/dto/create-collaborator-type.dto.d.ts +10 -0
- package/dist/dto/create-collaborator-type.dto.d.ts.map +1 -0
- package/dist/dto/create-collaborator-type.dto.js +56 -0
- package/dist/dto/create-collaborator-type.dto.js.map +1 -0
- package/dist/dto/create-collaborator.dto.d.ts +42 -0
- package/dist/dto/create-collaborator.dto.d.ts.map +1 -0
- package/dist/dto/create-collaborator.dto.js +228 -0
- package/dist/dto/create-collaborator.dto.js.map +1 -0
- package/dist/dto/create-schedule-adjustment-request.dto.d.ts +17 -0
- package/dist/dto/create-schedule-adjustment-request.dto.d.ts.map +1 -0
- package/dist/dto/create-schedule-adjustment-request.dto.js +89 -0
- package/dist/dto/create-schedule-adjustment-request.dto.js.map +1 -0
- package/dist/dto/create-task.dto.d.ts +8 -0
- package/dist/dto/create-task.dto.d.ts.map +1 -0
- package/dist/dto/create-task.dto.js +50 -0
- package/dist/dto/create-task.dto.js.map +1 -0
- package/dist/dto/create-time-off-request.dto.d.ts +9 -0
- package/dist/dto/create-time-off-request.dto.d.ts.map +1 -0
- package/dist/dto/create-time-off-request.dto.js +54 -0
- package/dist/dto/create-time-off-request.dto.js.map +1 -0
- package/dist/dto/create-timesheet-entry.dto.d.ts +12 -0
- package/dist/dto/create-timesheet-entry.dto.d.ts.map +1 -0
- package/dist/dto/create-timesheet-entry.dto.js +75 -0
- package/dist/dto/create-timesheet-entry.dto.js.map +1 -0
- package/dist/dto/list-collaborator-types.dto.d.ts +4 -0
- package/dist/dto/list-collaborator-types.dto.d.ts.map +1 -0
- package/dist/dto/list-collaborator-types.dto.js +29 -0
- package/dist/dto/list-collaborator-types.dto.js.map +1 -0
- package/dist/dto/list-collaborators.dto.d.ts +8 -0
- package/dist/dto/list-collaborators.dto.d.ts.map +1 -0
- package/dist/dto/list-collaborators.dto.js +42 -0
- package/dist/dto/list-collaborators.dto.js.map +1 -0
- package/dist/dto/list-project-options.dto.d.ts +4 -0
- package/dist/dto/list-project-options.dto.d.ts.map +1 -0
- package/dist/dto/list-project-options.dto.js +8 -0
- package/dist/dto/list-project-options.dto.js.map +1 -0
- package/dist/dto/list-tasks.dto.d.ts +7 -0
- package/dist/dto/list-tasks.dto.d.ts.map +1 -0
- package/dist/dto/list-tasks.dto.js +38 -0
- package/dist/dto/list-tasks.dto.js.map +1 -0
- package/dist/dto/list-timesheet-entries.dto.d.ts +10 -0
- package/dist/dto/list-timesheet-entries.dto.d.ts.map +1 -0
- package/dist/dto/list-timesheet-entries.dto.js +54 -0
- package/dist/dto/list-timesheet-entries.dto.js.map +1 -0
- package/dist/dto/update-collaborator-type.dto.d.ts +4 -0
- package/dist/dto/update-collaborator-type.dto.d.ts.map +1 -0
- package/dist/dto/update-collaborator-type.dto.js +8 -0
- package/dist/dto/update-collaborator-type.dto.js.map +1 -0
- package/dist/dto/update-collaborator.dto.d.ts +4 -0
- package/dist/dto/update-collaborator.dto.d.ts.map +1 -0
- package/dist/dto/update-collaborator.dto.js +8 -0
- package/dist/dto/update-collaborator.dto.js.map +1 -0
- package/dist/dto/update-task.dto.d.ts +8 -0
- package/dist/dto/update-task.dto.d.ts.map +1 -0
- package/dist/dto/update-task.dto.js +51 -0
- package/dist/dto/update-task.dto.js.map +1 -0
- package/dist/operations.controller.d.ts +0 -1045
- package/dist/operations.controller.d.ts.map +1 -1
- package/dist/operations.controller.js +0 -429
- package/dist/operations.controller.js.map +1 -1
- package/dist/operations.module.d.ts.map +1 -1
- package/dist/operations.module.js +23 -2
- package/dist/operations.module.js.map +1 -1
- package/dist/operations.service.d.ts +373 -8
- package/dist/operations.service.d.ts.map +1 -1
- package/dist/operations.service.js +1598 -111
- package/dist/operations.service.js.map +1 -1
- package/dist/operations.service.spec.js +315 -1
- package/dist/operations.service.spec.js.map +1 -1
- package/dist/services/shared/operations-access.service.d.ts +16 -0
- package/dist/services/shared/operations-access.service.d.ts.map +1 -0
- package/dist/services/shared/operations-access.service.js +48 -0
- package/dist/services/shared/operations-access.service.js.map +1 -0
- package/hedhog/data/dashboard.yaml +20 -0
- package/hedhog/data/dashboard_component.yaml +274 -0
- package/hedhog/data/dashboard_component_role.yaml +174 -0
- package/hedhog/data/dashboard_item.yaml +299 -0
- package/hedhog/data/dashboard_role.yaml +20 -0
- package/hedhog/data/menu.yaml +30 -13
- package/hedhog/data/operations_collaborator_type.yaml +76 -0
- package/hedhog/data/route.yaml +183 -0
- package/hedhog/frontend/app/_components/async-options-combobox.tsx.ejs +231 -0
- package/hedhog/frontend/app/_components/collaborator-details-screen.tsx.ejs +134 -49
- package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +772 -93
- package/hedhog/frontend/app/_components/department-select-with-create.tsx.ejs +38 -16
- package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +875 -632
- package/hedhog/frontend/app/_components/timesheet-task-create-sheet.tsx.ejs +213 -0
- package/hedhog/frontend/app/_lib/api.ts.ejs +30 -1
- package/hedhog/frontend/app/_lib/types.ts.ejs +142 -39
- package/hedhog/frontend/app/_lib/utils/format.ts.ejs +33 -2
- package/hedhog/frontend/app/approvals/page.tsx.ejs +116 -98
- package/hedhog/frontend/app/collaborator-types/page.tsx.ejs +502 -0
- package/hedhog/frontend/app/collaborators/page.tsx.ejs +109 -68
- package/hedhog/frontend/app/contracts/page.tsx.ejs +99 -102
- package/hedhog/frontend/app/contracts/templates/page.tsx.ejs +98 -102
- package/hedhog/frontend/app/departments/page.tsx.ejs +96 -75
- package/hedhog/frontend/app/projects/page.tsx.ejs +137 -127
- package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +244 -120
- package/hedhog/frontend/app/team/page.tsx.ejs +15 -2
- package/hedhog/frontend/app/time-off/page.tsx.ejs +158 -82
- package/hedhog/frontend/app/timesheets/page.tsx.ejs +814 -357
- package/hedhog/frontend/messages/en.json +243 -51
- package/hedhog/frontend/messages/pt.json +458 -268
- package/hedhog/table/operations_collaborator.yaml +26 -13
- package/hedhog/table/operations_collaborator_equity_participation.yaml +43 -0
- package/hedhog/table/operations_collaborator_type.yaml +33 -0
- package/hedhog/table/operations_job_title.yaml +24 -0
- package/hedhog/table/operations_project_assignment.yaml +9 -0
- package/hedhog/table/operations_project_role.yaml +39 -0
- package/hedhog/table/operations_task.yaml +30 -0
- package/hedhog/table/operations_timesheet_entry.yaml +12 -0
- package/package.json +6 -6
- package/src/controllers/operations-approvals.controller.ts +24 -0
- package/src/controllers/operations-collaborators.controller.ts +60 -0
- package/src/controllers/operations-contracts.controller.ts +138 -0
- package/src/controllers/operations-org-structure.controller.ts +92 -0
- package/src/controllers/operations-projects.controller.ts +50 -0
- package/src/controllers/operations-tasks.controller.ts +52 -0
- package/src/controllers/operations-timesheets.controller.ts +100 -0
- package/src/dto/create-collaborator-type.dto.ts +43 -0
- package/src/dto/create-collaborator.dto.ts +223 -0
- package/src/dto/create-schedule-adjustment-request.dto.ts +91 -0
- package/src/dto/create-task.dto.ts +35 -0
- package/src/dto/create-time-off-request.dto.ts +53 -0
- package/src/dto/create-timesheet-entry.dto.ts +67 -0
- package/src/dto/list-collaborator-types.dto.ts +15 -0
- package/src/dto/list-collaborators.dto.ts +30 -0
- package/src/dto/list-project-options.dto.ts +3 -0
- package/src/dto/list-tasks.dto.ts +25 -0
- package/src/dto/list-timesheet-entries.dto.ts +40 -0
- package/src/dto/update-collaborator-type.dto.ts +3 -0
- package/src/dto/update-collaborator.dto.ts +3 -0
- package/src/dto/update-task.dto.ts +36 -0
- package/src/operations.controller.ts +1 -278
- package/src/operations.module.ts +23 -2
- package/src/operations.service.spec.ts +450 -0
- package/src/operations.service.ts +4641 -2163
- package/src/services/shared/operations-access.service.ts +52 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { EmptyState, Page, SearchBar } from '@/components/entity-list';
|
|
4
4
|
import { Button } from '@/components/ui/button';
|
|
5
|
+
import { FormActions } from '@/components/ui/form-actions';
|
|
5
6
|
import { Input } from '@/components/ui/input';
|
|
6
7
|
import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
|
|
7
8
|
import {
|
|
@@ -29,19 +30,19 @@ import {
|
|
|
29
30
|
import { Textarea } from '@/components/ui/textarea';
|
|
30
31
|
import { useApp, useQuery } from '@hed-hog/next-app-provider';
|
|
31
32
|
import { Palmtree, Plus } from 'lucide-react';
|
|
32
|
-
import { useMemo, useState } from 'react';
|
|
33
33
|
import { useTranslations } from 'next-intl';
|
|
34
|
+
import { useMemo, useState } from 'react';
|
|
34
35
|
import { OperationsHeader } from '../_components/operations-header';
|
|
35
36
|
import { StatusBadge } from '../_components/status-badge';
|
|
36
37
|
import { fetchOperations, mutateOperations } from '../_lib/api';
|
|
37
38
|
import { useOperationsAccess } from '../_lib/hooks/use-operations-access';
|
|
38
39
|
import type { OperationsTimeOffRequest } from '../_lib/types';
|
|
39
|
-
import { parseNumberInput, trimToNull } from '../_lib/utils/forms';
|
|
40
40
|
import {
|
|
41
41
|
formatDateRange,
|
|
42
42
|
formatEnumLabel,
|
|
43
43
|
getStatusBadgeClass,
|
|
44
44
|
} from '../_lib/utils/format';
|
|
45
|
+
import { parseNumberInput, trimToNull } from '../_lib/utils/forms';
|
|
45
46
|
|
|
46
47
|
type TimeOffFormState = {
|
|
47
48
|
requestType: string;
|
|
@@ -59,50 +60,71 @@ const emptyForm: TimeOffFormState = {
|
|
|
59
60
|
reason: '',
|
|
60
61
|
};
|
|
61
62
|
|
|
62
|
-
export default function OperationsTimeOffPage() {
|
|
63
|
-
const t = useTranslations('operations.TimeOffPage');
|
|
64
|
-
const commonT = useTranslations('operations.Common');
|
|
65
|
-
const { request, showToastHandler, currentLocaleCode } = useApp();
|
|
66
|
-
const access = useOperationsAccess();
|
|
67
|
-
const [search, setSearch] = useState('');
|
|
68
|
-
const [statusFilter, setStatusFilter] = useState('all');
|
|
69
|
-
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
|
70
|
-
const [form, setForm] = useState<TimeOffFormState>(emptyForm);
|
|
71
|
-
|
|
72
|
-
const getRequestTypeLabel = (value?: string | null) => {
|
|
73
|
-
if (!value) {
|
|
74
|
-
return '-';
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const key = `options.requestTypes.${value}`;
|
|
78
|
-
return t.has(key) ? t(key) : formatEnumLabel(value);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const getStatusLabel = (value?: string | null) => {
|
|
82
|
-
if (!value) {
|
|
83
|
-
return '-';
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const key = `options.statuses.${value}`;
|
|
87
|
-
return t.has(key) ? t(key) : formatEnumLabel(value);
|
|
88
|
-
};
|
|
63
|
+
export default function OperationsTimeOffPage() {
|
|
64
|
+
const t = useTranslations('operations.TimeOffPage');
|
|
65
|
+
const commonT = useTranslations('operations.Common');
|
|
66
|
+
const { request, showToastHandler, currentLocaleCode } = useApp();
|
|
67
|
+
const access = useOperationsAccess();
|
|
68
|
+
const [search, setSearch] = useState('');
|
|
69
|
+
const [statusFilter, setStatusFilter] = useState('all');
|
|
70
|
+
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
|
71
|
+
const [form, setForm] = useState<TimeOffFormState>(emptyForm);
|
|
89
72
|
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
73
|
+
const getRequestTypeLabel = (value?: string | null) => {
|
|
74
|
+
if (!value) {
|
|
75
|
+
return '-';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const key = `options.requestTypes.${value}`;
|
|
79
|
+
return t.has(key) ? t(key) : formatEnumLabel(value);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const getStatusLabel = (value?: string | null) => {
|
|
83
|
+
if (!value) {
|
|
84
|
+
return '-';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const key = `options.statuses.${value}`;
|
|
88
|
+
return t.has(key) ? t(key) : formatEnumLabel(value);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const getStatusDescription = (value?: string | null) => {
|
|
92
|
+
if (!value) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const key = `statusHelp.${value}`;
|
|
97
|
+
return t.has(key) ? t(key) : null;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const { data: requests = [], refetch } = useQuery<OperationsTimeOffRequest[]>(
|
|
101
|
+
{
|
|
102
|
+
queryKey: ['operations-time-off', currentLocaleCode],
|
|
103
|
+
enabled: access.isCollaborator,
|
|
104
|
+
queryFn: () =>
|
|
105
|
+
fetchOperations<OperationsTimeOffRequest[]>(
|
|
106
|
+
request,
|
|
107
|
+
'/operations/time-off'
|
|
108
|
+
),
|
|
109
|
+
}
|
|
110
|
+
);
|
|
96
111
|
|
|
97
112
|
const filteredRows = useMemo(
|
|
98
113
|
() =>
|
|
99
114
|
requests.filter((item) => {
|
|
100
115
|
const matchesSearch = !search.trim()
|
|
101
116
|
? true
|
|
102
|
-
: [
|
|
117
|
+
: [
|
|
118
|
+
item.collaboratorName,
|
|
119
|
+
item.approverName,
|
|
120
|
+
item.reason,
|
|
121
|
+
item.requestType,
|
|
122
|
+
]
|
|
103
123
|
.filter(Boolean)
|
|
104
124
|
.some((value) =>
|
|
105
|
-
String(value)
|
|
125
|
+
String(value)
|
|
126
|
+
.toLowerCase()
|
|
127
|
+
.includes(search.trim().toLowerCase())
|
|
106
128
|
);
|
|
107
129
|
const matchesStatus =
|
|
108
130
|
statusFilter === 'all' ? true : item.status === statusFilter;
|
|
@@ -115,16 +137,19 @@ export default function OperationsTimeOffPage() {
|
|
|
115
137
|
{
|
|
116
138
|
key: 'submitted',
|
|
117
139
|
title: t('cards.submitted'),
|
|
140
|
+
description: t('cards.submittedDescription'),
|
|
118
141
|
value: requests.filter((item) => item.status === 'submitted').length,
|
|
119
142
|
},
|
|
120
143
|
{
|
|
121
144
|
key: 'approved',
|
|
122
145
|
title: t('cards.approved'),
|
|
146
|
+
description: t('cards.approvedDescription'),
|
|
123
147
|
value: requests.filter((item) => item.status === 'approved').length,
|
|
124
148
|
},
|
|
125
149
|
{
|
|
126
150
|
key: 'days',
|
|
127
151
|
title: t('cards.days'),
|
|
152
|
+
description: t('cards.daysDescription'),
|
|
128
153
|
value: requests.reduce(
|
|
129
154
|
(total, item) => total + Number(item.totalDays ?? 0),
|
|
130
155
|
0
|
|
@@ -172,6 +197,8 @@ export default function OperationsTimeOffPage() {
|
|
|
172
197
|
}
|
|
173
198
|
/>
|
|
174
199
|
|
|
200
|
+
<KpiCardsGrid items={cards} columns={3} />
|
|
201
|
+
|
|
175
202
|
<SearchBar
|
|
176
203
|
searchQuery={search}
|
|
177
204
|
onSearchChange={setSearch}
|
|
@@ -184,18 +211,16 @@ export default function OperationsTimeOffPage() {
|
|
|
184
211
|
value: statusFilter,
|
|
185
212
|
onChange: setStatusFilter,
|
|
186
213
|
placeholder: commonT('labels.status'),
|
|
187
|
-
options: [
|
|
188
|
-
{ value: 'all', label: commonT('filters.allStatuses') },
|
|
189
|
-
{ value: 'submitted', label: getStatusLabel('submitted') },
|
|
190
|
-
{ value: 'approved', label: getStatusLabel('approved') },
|
|
191
|
-
{ value: 'rejected', label: getStatusLabel('rejected') },
|
|
192
|
-
],
|
|
214
|
+
options: [
|
|
215
|
+
{ value: 'all', label: commonT('filters.allStatuses') },
|
|
216
|
+
{ value: 'submitted', label: getStatusLabel('submitted') },
|
|
217
|
+
{ value: 'approved', label: getStatusLabel('approved') },
|
|
218
|
+
{ value: 'rejected', label: getStatusLabel('rejected') },
|
|
219
|
+
],
|
|
193
220
|
},
|
|
194
221
|
]}
|
|
195
222
|
/>
|
|
196
223
|
|
|
197
|
-
<KpiCardsGrid items={cards} columns={3} />
|
|
198
|
-
|
|
199
224
|
{filteredRows.length > 0 ? (
|
|
200
225
|
<div className="overflow-x-auto rounded-md border">
|
|
201
226
|
<Table>
|
|
@@ -212,12 +237,17 @@ export default function OperationsTimeOffPage() {
|
|
|
212
237
|
</TableHeader>
|
|
213
238
|
<TableBody>
|
|
214
239
|
{filteredRows.map((requestItem) => (
|
|
215
|
-
<TableRow key={requestItem.id}>
|
|
240
|
+
<TableRow key={requestItem.id} className="hover:bg-muted/30">
|
|
216
241
|
<TableCell>{requestItem.collaboratorName}</TableCell>
|
|
217
|
-
<TableCell>
|
|
242
|
+
<TableCell>
|
|
243
|
+
{getRequestTypeLabel(requestItem.requestType)}
|
|
244
|
+
</TableCell>
|
|
218
245
|
<TableCell>
|
|
219
246
|
<div>
|
|
220
|
-
{formatDateRange(
|
|
247
|
+
{formatDateRange(
|
|
248
|
+
requestItem.startDate,
|
|
249
|
+
requestItem.endDate
|
|
250
|
+
)}
|
|
221
251
|
</div>
|
|
222
252
|
<div className="text-xs text-muted-foreground">
|
|
223
253
|
{requestItem.totalDays ?? 0} {commonT('labels.days')}
|
|
@@ -227,10 +257,17 @@ export default function OperationsTimeOffPage() {
|
|
|
227
257
|
{requestItem.approverName || commonT('labels.notAssigned')}
|
|
228
258
|
</TableCell>
|
|
229
259
|
<TableCell>
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
260
|
+
<div className="space-y-1">
|
|
261
|
+
<StatusBadge
|
|
262
|
+
label={getStatusLabel(requestItem.status)}
|
|
263
|
+
className={getStatusBadgeClass(requestItem.status)}
|
|
264
|
+
/>
|
|
265
|
+
{getStatusDescription(requestItem.status) ? (
|
|
266
|
+
<p className="max-w-40 text-xs text-muted-foreground">
|
|
267
|
+
{getStatusDescription(requestItem.status)}
|
|
268
|
+
</p>
|
|
269
|
+
) : null}
|
|
270
|
+
</div>
|
|
234
271
|
</TableCell>
|
|
235
272
|
<TableCell>
|
|
236
273
|
{requestItem.reason || commonT('labels.noNotes')}
|
|
@@ -248,8 +285,16 @@ export default function OperationsTimeOffPage() {
|
|
|
248
285
|
icon={<Palmtree className="size-12" />}
|
|
249
286
|
title={commonT('states.emptyTitle')}
|
|
250
287
|
description={t('emptyDescription')}
|
|
251
|
-
actionLabel={
|
|
252
|
-
|
|
288
|
+
actionLabel={
|
|
289
|
+
access.isCollaborator
|
|
290
|
+
? commonT('actions.create')
|
|
291
|
+
: commonT('actions.refresh')
|
|
292
|
+
}
|
|
293
|
+
onAction={
|
|
294
|
+
access.isCollaborator
|
|
295
|
+
? () => setIsSheetOpen(true)
|
|
296
|
+
: () => void refetch()
|
|
297
|
+
}
|
|
253
298
|
/>
|
|
254
299
|
)}
|
|
255
300
|
|
|
@@ -260,39 +305,54 @@ export default function OperationsTimeOffPage() {
|
|
|
260
305
|
<SheetDescription>{t('sheet.description')}</SheetDescription>
|
|
261
306
|
</SheetHeader>
|
|
262
307
|
|
|
263
|
-
<div className="mt-6 grid gap-4">
|
|
308
|
+
<div className="mt-6 grid gap-4 px-4 pb-20">
|
|
309
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-sm">
|
|
310
|
+
<div className="font-medium text-foreground">
|
|
311
|
+
{t('sheet.helperTitle')}
|
|
312
|
+
</div>
|
|
313
|
+
<p className="mt-1 text-muted-foreground">
|
|
314
|
+
{t('sheet.helperDescription')}
|
|
315
|
+
</p>
|
|
316
|
+
</div>
|
|
317
|
+
|
|
264
318
|
<div className="space-y-2">
|
|
265
|
-
<label className="text-sm font-medium">
|
|
319
|
+
<label className="text-sm font-medium">
|
|
320
|
+
{commonT('labels.requestType')}
|
|
321
|
+
</label>
|
|
266
322
|
<Select
|
|
267
323
|
value={form.requestType}
|
|
268
324
|
onValueChange={(value) =>
|
|
269
325
|
setForm((current) => ({ ...current, requestType: value }))
|
|
270
326
|
}
|
|
271
327
|
>
|
|
272
|
-
<SelectTrigger>
|
|
273
|
-
<SelectValue />
|
|
274
|
-
</SelectTrigger>
|
|
275
|
-
<SelectContent>
|
|
276
|
-
<SelectItem value="vacation">
|
|
277
|
-
{getRequestTypeLabel('vacation')}
|
|
278
|
-
</SelectItem>
|
|
279
|
-
<SelectItem value="personal_time">
|
|
280
|
-
{getRequestTypeLabel('personal_time')}
|
|
281
|
-
</SelectItem>
|
|
282
|
-
<SelectItem value="sick_leave">
|
|
283
|
-
{getRequestTypeLabel('sick_leave')}
|
|
284
|
-
</SelectItem>
|
|
285
|
-
<SelectItem value="unpaid_leave">
|
|
286
|
-
{getRequestTypeLabel('unpaid_leave')}
|
|
287
|
-
</SelectItem>
|
|
288
|
-
<SelectItem value="other">
|
|
289
|
-
|
|
290
|
-
|
|
328
|
+
<SelectTrigger className="w-full">
|
|
329
|
+
<SelectValue />
|
|
330
|
+
</SelectTrigger>
|
|
331
|
+
<SelectContent>
|
|
332
|
+
<SelectItem value="vacation">
|
|
333
|
+
{getRequestTypeLabel('vacation')}
|
|
334
|
+
</SelectItem>
|
|
335
|
+
<SelectItem value="personal_time">
|
|
336
|
+
{getRequestTypeLabel('personal_time')}
|
|
337
|
+
</SelectItem>
|
|
338
|
+
<SelectItem value="sick_leave">
|
|
339
|
+
{getRequestTypeLabel('sick_leave')}
|
|
340
|
+
</SelectItem>
|
|
341
|
+
<SelectItem value="unpaid_leave">
|
|
342
|
+
{getRequestTypeLabel('unpaid_leave')}
|
|
343
|
+
</SelectItem>
|
|
344
|
+
<SelectItem value="other">
|
|
345
|
+
{getRequestTypeLabel('other')}
|
|
346
|
+
</SelectItem>
|
|
347
|
+
</SelectContent>
|
|
348
|
+
</Select>
|
|
291
349
|
</div>
|
|
292
350
|
|
|
293
351
|
<div className="grid gap-4 md:grid-cols-2">
|
|
294
352
|
<div className="space-y-2">
|
|
295
|
-
<label className="text-sm font-medium">
|
|
353
|
+
<label className="text-sm font-medium">
|
|
354
|
+
{commonT('labels.startDate')}
|
|
355
|
+
</label>
|
|
296
356
|
<Input
|
|
297
357
|
type="date"
|
|
298
358
|
value={form.startDate}
|
|
@@ -305,7 +365,9 @@ export default function OperationsTimeOffPage() {
|
|
|
305
365
|
/>
|
|
306
366
|
</div>
|
|
307
367
|
<div className="space-y-2">
|
|
308
|
-
<label className="text-sm font-medium">
|
|
368
|
+
<label className="text-sm font-medium">
|
|
369
|
+
{commonT('labels.endDate')}
|
|
370
|
+
</label>
|
|
309
371
|
<Input
|
|
310
372
|
type="date"
|
|
311
373
|
value={form.endDate}
|
|
@@ -320,7 +382,9 @@ export default function OperationsTimeOffPage() {
|
|
|
320
382
|
</div>
|
|
321
383
|
|
|
322
384
|
<div className="space-y-2">
|
|
323
|
-
<label className="text-sm font-medium">
|
|
385
|
+
<label className="text-sm font-medium">
|
|
386
|
+
{commonT('labels.days')}
|
|
387
|
+
</label>
|
|
324
388
|
<Input
|
|
325
389
|
type="number"
|
|
326
390
|
step="0.5"
|
|
@@ -335,18 +399,30 @@ export default function OperationsTimeOffPage() {
|
|
|
335
399
|
</div>
|
|
336
400
|
|
|
337
401
|
<div className="space-y-2">
|
|
338
|
-
<label className="text-sm font-medium">
|
|
402
|
+
<label className="text-sm font-medium">
|
|
403
|
+
{commonT('labels.reason')}
|
|
404
|
+
</label>
|
|
339
405
|
<Textarea
|
|
340
406
|
rows={4}
|
|
407
|
+
placeholder={t('sheet.reasonPlaceholder')}
|
|
341
408
|
value={form.reason}
|
|
342
409
|
onChange={(event) =>
|
|
343
|
-
setForm((current) => ({
|
|
410
|
+
setForm((current) => ({
|
|
411
|
+
...current,
|
|
412
|
+
reason: event.target.value,
|
|
413
|
+
}))
|
|
344
414
|
}
|
|
345
415
|
/>
|
|
346
416
|
</div>
|
|
347
|
-
|
|
348
|
-
<Button onClick={() => void onSubmit()}>{commonT('actions.save')}</Button>
|
|
349
417
|
</div>
|
|
418
|
+
|
|
419
|
+
<FormActions
|
|
420
|
+
sheet
|
|
421
|
+
cancelLabel={commonT('actions.cancel')}
|
|
422
|
+
onCancel={() => setIsSheetOpen(false)}
|
|
423
|
+
onSubmit={() => void onSubmit()}
|
|
424
|
+
submitLabel={commonT('actions.save')}
|
|
425
|
+
/>
|
|
350
426
|
</SheetContent>
|
|
351
427
|
</Sheet>
|
|
352
428
|
</Page>
|