@hed-hog/lms 0.0.329 → 0.0.331
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/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +18 -8
- package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +10 -8
- package/hedhog/frontend/app/_components/create-lms-person-sheet.tsx.ejs +5 -9
- package/hedhog/frontend/app/_components/create-lms-student-person-sheet.tsx.ejs +5 -9
- package/hedhog/frontend/app/certificates/models/LeftPanel.tsx.ejs +15 -14
- package/hedhog/frontend/app/certificates/models/RightPanel.tsx.ejs +66 -29
- package/hedhog/frontend/app/certificates/models/TemplateEditorPage.tsx.ejs +4 -2
- package/hedhog/frontend/app/certificates/models/TopBar.tsx.ejs +44 -34
- package/hedhog/frontend/app/certificates/models/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +27 -27
- package/hedhog/frontend/app/classes/page.tsx.ejs +23 -15
- package/hedhog/frontend/app/courses/[id]/_components/CourseMultiEntityPicker.tsx.ejs +2 -2
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +8 -6
- package/hedhog/frontend/app/courses/[id]/structure/_components/confirm-dialog.tsx.ejs +5 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +1 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-panel.tsx.ejs +9 -7
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-skeleton.tsx.ejs +3 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-handle.tsx.ejs +4 -2
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +24 -23
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +228 -152
- package/hedhog/frontend/app/courses/[id]/structure/_components/multi-select-bar.tsx.ejs +21 -19
- package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +78 -36
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +18 -16
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +13 -11
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-session.tsx.ejs +5 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/use-course-structure-shortcuts.ts.ejs +14 -9
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +42 -25
- package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +37 -41
- package/hedhog/frontend/app/enterprise/_components/enterprise-admin-create-sheet.tsx.ejs +3 -1
- package/hedhog/frontend/app/enterprise/_components/enterprise-administrators-tab.tsx.ejs +10 -8
- package/hedhog/frontend/app/enterprise/_components/enterprise-classes-tab.tsx.ejs +22 -20
- package/hedhog/frontend/app/enterprise/_components/enterprise-course-create-sheet.tsx.ejs +3 -3
- package/hedhog/frontend/app/enterprise/_components/enterprise-courses-tab.tsx.ejs +21 -19
- package/hedhog/frontend/app/enterprise/_components/enterprise-sheet.tsx.ejs +34 -36
- package/hedhog/frontend/app/enterprise/_components/enterprise-student-create-sheet.tsx.ejs +3 -1
- package/hedhog/frontend/app/enterprise/_components/enterprise-students-tab.tsx.ejs +7 -5
- package/hedhog/frontend/app/enterprise/page.tsx.ejs +106 -54
- package/hedhog/frontend/app/evaluations/_components/evaluation-topic-form-sheet.tsx.ejs +1 -1
- package/hedhog/frontend/app/exams/page.tsx.ejs +6 -2
- package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +79 -59
- package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +145 -119
- package/hedhog/frontend/app/instructors/page.tsx.ejs +75 -54
- package/hedhog/frontend/app/paths/page.tsx.ejs +11 -7
- package/hedhog/frontend/app/reports/courses/page.tsx.ejs +5 -5
- package/hedhog/frontend/app/reports/dashboard/page.tsx.ejs +8 -8
- package/hedhog/frontend/app/reports/page.tsx.ejs +7 -7
- package/hedhog/frontend/app/reports/students/page.tsx.ejs +6 -6
- package/hedhog/frontend/app/training/page.tsx.ejs +5 -5
- package/hedhog/frontend/messages/en.json +899 -45
- package/hedhog/frontend/messages/pt.json +894 -38
- package/hedhog/frontend/widgets/active-classes-kpi.tsx.ejs +1 -1
- package/hedhog/frontend/widgets/active-courses-kpi.tsx.ejs +1 -1
- package/hedhog/frontend/widgets/approval-rate-kpi.tsx.ejs +1 -1
- package/hedhog/frontend/widgets/class-calendar.tsx.ejs +2 -2
- package/hedhog/frontend/widgets/completion-rate-kpi.tsx.ejs +1 -1
- package/hedhog/frontend/widgets/issued-certificates-kpi.tsx.ejs +1 -1
- package/hedhog/frontend/widgets/total-students-kpi.tsx.ejs +1 -1
- package/hedhog/table/instructor_qualification.yaml +1 -1
- package/hedhog/table/instructor_skill.yaml +1 -1
- package/package.json +7 -7
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
UserRoundPen,
|
|
55
55
|
Users,
|
|
56
56
|
} from 'lucide-react';
|
|
57
|
+
import { useTranslations } from 'next-intl';
|
|
57
58
|
import { useEffect, useState } from 'react';
|
|
58
59
|
import { toast } from 'sonner';
|
|
59
60
|
import { InstructorFormSheet } from './_components/instructor-form-sheet';
|
|
@@ -72,6 +73,15 @@ const QUALIFICATION_LABELS: Record<string, string> = {
|
|
|
72
73
|
'class-sessions': 'Sessões de turma',
|
|
73
74
|
};
|
|
74
75
|
|
|
76
|
+
function getQualificationLabel(
|
|
77
|
+
slug: string,
|
|
78
|
+
t: (key: string) => string
|
|
79
|
+
): string {
|
|
80
|
+
if (slug === 'course-lessons') return t('qualificationLabels.courseLessons');
|
|
81
|
+
if (slug === 'class-sessions') return t('qualificationLabels.classSessions');
|
|
82
|
+
return QUALIFICATION_LABELS[slug] ?? slug;
|
|
83
|
+
}
|
|
84
|
+
|
|
75
85
|
function getInstructorInitials(name: string) {
|
|
76
86
|
return name
|
|
77
87
|
.split(' ')
|
|
@@ -89,6 +99,7 @@ function getAvatarUrl(avatarId?: number | null) {
|
|
|
89
99
|
|
|
90
100
|
export default function InstructorsPage() {
|
|
91
101
|
const { request } = useApp();
|
|
102
|
+
const t = useTranslations('lms.InstructorsPage');
|
|
92
103
|
|
|
93
104
|
const [page, setPage] = useState(1);
|
|
94
105
|
const [pageSize, setPageSize] = useState(12);
|
|
@@ -223,12 +234,12 @@ export default function InstructorsPage() {
|
|
|
223
234
|
url: `/lms/instructors/${instructorToDelete.id}`,
|
|
224
235
|
method: 'DELETE',
|
|
225
236
|
});
|
|
226
|
-
toast.success('
|
|
237
|
+
toast.success(t('messages.instructorRemovedSuccess'));
|
|
227
238
|
setDeleteDialogOpen(false);
|
|
228
239
|
setInstructorToDelete(null);
|
|
229
240
|
await Promise.all([refetchList(), refetchStats()]);
|
|
230
241
|
} catch {
|
|
231
|
-
toast.error('
|
|
242
|
+
toast.error(t('messages.instructorRemoveError'));
|
|
232
243
|
} finally {
|
|
233
244
|
setIsDeleting(false);
|
|
234
245
|
}
|
|
@@ -237,7 +248,7 @@ export default function InstructorsPage() {
|
|
|
237
248
|
const statsCards = [
|
|
238
249
|
{
|
|
239
250
|
key: 'total',
|
|
240
|
-
title: '
|
|
251
|
+
title: t('kpis.total'),
|
|
241
252
|
value: stats.total,
|
|
242
253
|
icon: Users,
|
|
243
254
|
accentClassName: 'from-slate-500/20 via-slate-400/10 to-transparent',
|
|
@@ -245,7 +256,7 @@ export default function InstructorsPage() {
|
|
|
245
256
|
},
|
|
246
257
|
{
|
|
247
258
|
key: 'active',
|
|
248
|
-
title: '
|
|
259
|
+
title: t('kpis.active'),
|
|
249
260
|
value: stats.active,
|
|
250
261
|
icon: UserRoundPen,
|
|
251
262
|
accentClassName: 'from-green-500/20 via-emerald-500/10 to-transparent',
|
|
@@ -253,7 +264,7 @@ export default function InstructorsPage() {
|
|
|
253
264
|
},
|
|
254
265
|
{
|
|
255
266
|
key: 'inactive',
|
|
256
|
-
title: '
|
|
267
|
+
title: t('kpis.inactive'),
|
|
257
268
|
value: stats.inactive,
|
|
258
269
|
icon: UserRoundPen,
|
|
259
270
|
accentClassName: 'from-gray-500/20 via-gray-400/10 to-transparent',
|
|
@@ -270,11 +281,11 @@ export default function InstructorsPage() {
|
|
|
270
281
|
setStatusFilter(value);
|
|
271
282
|
setPage(1);
|
|
272
283
|
},
|
|
273
|
-
placeholder: '
|
|
284
|
+
placeholder: t('filters.statusPlaceholder'),
|
|
274
285
|
options: [
|
|
275
|
-
{ value: 'all', label: '
|
|
276
|
-
{ value: 'active', label: '
|
|
277
|
-
{ value: 'inactive', label: '
|
|
286
|
+
{ value: 'all', label: t('filters.allStatuses') },
|
|
287
|
+
{ value: 'active', label: t('form.fields.active') },
|
|
288
|
+
{ value: 'inactive', label: t('form.fields.inactive') },
|
|
278
289
|
],
|
|
279
290
|
},
|
|
280
291
|
{
|
|
@@ -285,11 +296,17 @@ export default function InstructorsPage() {
|
|
|
285
296
|
setQualificationFilter(value);
|
|
286
297
|
setPage(1);
|
|
287
298
|
},
|
|
288
|
-
placeholder: '
|
|
299
|
+
placeholder: t('filters.qualificationPlaceholder'),
|
|
289
300
|
options: [
|
|
290
|
-
{ value: 'all', label: '
|
|
291
|
-
{
|
|
292
|
-
|
|
301
|
+
{ value: 'all', label: t('filters.allQualifications') },
|
|
302
|
+
{
|
|
303
|
+
value: 'course-lessons',
|
|
304
|
+
label: t('qualificationLabels.courseLessons'),
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
value: 'class-sessions',
|
|
308
|
+
label: t('qualificationLabels.classSessions'),
|
|
309
|
+
},
|
|
293
310
|
],
|
|
294
311
|
},
|
|
295
312
|
];
|
|
@@ -298,15 +315,15 @@ export default function InstructorsPage() {
|
|
|
298
315
|
<Page>
|
|
299
316
|
<PageHeader
|
|
300
317
|
breadcrumbs={[
|
|
301
|
-
{ label: '
|
|
302
|
-
{ label: '
|
|
303
|
-
{ label: '
|
|
318
|
+
{ label: t('breadcrumbs.home'), href: '/' },
|
|
319
|
+
{ label: t('breadcrumbs.lms'), href: '/lms' },
|
|
320
|
+
{ label: t('breadcrumbs.instructors') },
|
|
304
321
|
]}
|
|
305
|
-
title=
|
|
306
|
-
description=
|
|
322
|
+
title={t('header.title')}
|
|
323
|
+
description={t('header.description')}
|
|
307
324
|
actions={[
|
|
308
325
|
{
|
|
309
|
-
label: '
|
|
326
|
+
label: t('form.title'),
|
|
310
327
|
onClick: openCreateSheet,
|
|
311
328
|
icon: <Plus className="h-4 w-4" />,
|
|
312
329
|
},
|
|
@@ -323,14 +340,14 @@ export default function InstructorsPage() {
|
|
|
323
340
|
setSearchInput(value);
|
|
324
341
|
}}
|
|
325
342
|
onSearch={() => setPage(1)}
|
|
326
|
-
placeholder=
|
|
343
|
+
placeholder={t('search.placeholder')}
|
|
327
344
|
controls={searchControls}
|
|
328
|
-
/>
|
|
345
|
+
/>{' '}
|
|
329
346
|
</div>
|
|
330
347
|
|
|
331
348
|
<div className="flex items-center justify-between gap-3 sm:justify-start xl:justify-end">
|
|
332
349
|
<span className="text-xs font-medium text-muted-foreground">
|
|
333
|
-
|
|
350
|
+
{t('viewMode.label')}
|
|
334
351
|
</span>
|
|
335
352
|
<ToggleGroup
|
|
336
353
|
type="single"
|
|
@@ -338,23 +355,23 @@ export default function InstructorsPage() {
|
|
|
338
355
|
onValueChange={handleViewModeChange}
|
|
339
356
|
variant="outline"
|
|
340
357
|
size="sm"
|
|
341
|
-
aria-label=
|
|
358
|
+
aria-label={t('viewMode.ariaLabel')}
|
|
342
359
|
>
|
|
343
360
|
<ToggleGroupItem
|
|
344
361
|
value="table"
|
|
345
362
|
className="gap-1.5 px-2.5"
|
|
346
|
-
aria-label=
|
|
363
|
+
aria-label={t('viewMode.tableAriaLabel')}
|
|
347
364
|
>
|
|
348
365
|
<List className="h-4 w-4" />
|
|
349
|
-
<span className="hidden sm:inline">
|
|
366
|
+
<span className="hidden sm:inline">{t('viewMode.table')}</span>
|
|
350
367
|
</ToggleGroupItem>
|
|
351
368
|
<ToggleGroupItem
|
|
352
369
|
value="cards"
|
|
353
370
|
className="gap-1.5 px-2.5"
|
|
354
|
-
aria-label=
|
|
371
|
+
aria-label={t('viewMode.cardsAriaLabel')}
|
|
355
372
|
>
|
|
356
373
|
<LayoutGrid className="h-4 w-4" />
|
|
357
|
-
<span className="hidden sm:inline">
|
|
374
|
+
<span className="hidden sm:inline">{t('viewMode.cards')}</span>
|
|
358
375
|
</ToggleGroupItem>
|
|
359
376
|
</ToggleGroup>
|
|
360
377
|
</div>
|
|
@@ -391,9 +408,9 @@ export default function InstructorsPage() {
|
|
|
391
408
|
) : paginate.data.length === 0 ? (
|
|
392
409
|
<EmptyState
|
|
393
410
|
icon={<UserRoundPen className="h-12 w-12" />}
|
|
394
|
-
title=
|
|
395
|
-
description=
|
|
396
|
-
actionLabel=
|
|
411
|
+
title={t('emptyState.title')}
|
|
412
|
+
description={t('emptyState.description')}
|
|
413
|
+
actionLabel={t('form.title')}
|
|
397
414
|
actionIcon={<Plus className="mr-2 h-4 w-4" />}
|
|
398
415
|
onAction={openCreateSheet}
|
|
399
416
|
/>
|
|
@@ -404,14 +421,14 @@ export default function InstructorsPage() {
|
|
|
404
421
|
<Table>
|
|
405
422
|
<TableHeader>
|
|
406
423
|
<TableRow>
|
|
407
|
-
<TableHead>
|
|
408
|
-
<TableHead>
|
|
409
|
-
<TableHead>
|
|
410
|
-
<TableHead>
|
|
411
|
-
<TableHead>
|
|
412
|
-
<TableHead>
|
|
413
|
-
<TableHead>
|
|
414
|
-
<TableHead>
|
|
424
|
+
<TableHead>{t('table.instructor')}</TableHead>
|
|
425
|
+
<TableHead>{t('table.email')}</TableHead>
|
|
426
|
+
<TableHead>{t('table.phone')}</TableHead>
|
|
427
|
+
<TableHead>{t('table.qualifications')}</TableHead>
|
|
428
|
+
<TableHead>{t('table.skills')}</TableHead>
|
|
429
|
+
<TableHead>{t('table.hourlyRate')}</TableHead>
|
|
430
|
+
<TableHead>{t('table.training')}</TableHead>
|
|
431
|
+
<TableHead>{t('table.status')}</TableHead>
|
|
415
432
|
<TableHead className="w-10" />
|
|
416
433
|
</TableRow>
|
|
417
434
|
</TableHeader>
|
|
@@ -474,7 +491,7 @@ export default function InstructorsPage() {
|
|
|
474
491
|
variant="outline"
|
|
475
492
|
className="border-blue-500/20 bg-blue-500/10 px-2 py-0.5 text-[11px] font-medium text-blue-600"
|
|
476
493
|
>
|
|
477
|
-
{
|
|
494
|
+
{getQualificationLabel(slug, t)}
|
|
478
495
|
</Badge>
|
|
479
496
|
)
|
|
480
497
|
)}
|
|
@@ -516,14 +533,14 @@ export default function InstructorsPage() {
|
|
|
516
533
|
variant="outline"
|
|
517
534
|
className="border-amber-500/20 bg-amber-500/10 px-2.5 py-1 text-xs font-medium text-amber-600"
|
|
518
535
|
>
|
|
519
|
-
|
|
536
|
+
{t('training.active')}
|
|
520
537
|
</Badge>
|
|
521
538
|
) : instructor.userId ? (
|
|
522
539
|
<Badge
|
|
523
540
|
variant="outline"
|
|
524
541
|
className="border-gray-500/20 bg-gray-500/10 px-2.5 py-1 text-xs font-medium text-gray-500"
|
|
525
542
|
>
|
|
526
|
-
|
|
543
|
+
{t('training.disabled')}
|
|
527
544
|
</Badge>
|
|
528
545
|
) : (
|
|
529
546
|
<span className="text-xs text-muted-foreground">
|
|
@@ -541,7 +558,9 @@ export default function InstructorsPage() {
|
|
|
541
558
|
: 'border-gray-500/20 bg-gray-500/10 text-gray-600'
|
|
542
559
|
)}
|
|
543
560
|
>
|
|
544
|
-
{instructor.status === 'active'
|
|
561
|
+
{instructor.status === 'active'
|
|
562
|
+
? t('form.fields.active')
|
|
563
|
+
: t('form.fields.inactive')}
|
|
545
564
|
</Badge>
|
|
546
565
|
</TableCell>
|
|
547
566
|
<TableCell>
|
|
@@ -560,7 +579,7 @@ export default function InstructorsPage() {
|
|
|
560
579
|
onClick={() => openEditSheet(instructor)}
|
|
561
580
|
>
|
|
562
581
|
<Pencil className="mr-2 h-4 w-4" />
|
|
563
|
-
|
|
582
|
+
{t('actions.edit')}
|
|
564
583
|
</DropdownMenuItem>
|
|
565
584
|
<DropdownMenuSeparator />
|
|
566
585
|
<DropdownMenuItem
|
|
@@ -571,7 +590,7 @@ export default function InstructorsPage() {
|
|
|
571
590
|
}}
|
|
572
591
|
>
|
|
573
592
|
<Trash2 className="mr-2 h-4 w-4" />
|
|
574
|
-
|
|
593
|
+
{t('actions.delete')}
|
|
575
594
|
</DropdownMenuItem>
|
|
576
595
|
</DropdownMenuContent>
|
|
577
596
|
</DropdownMenu>
|
|
@@ -639,7 +658,7 @@ export default function InstructorsPage() {
|
|
|
639
658
|
onClick={() => openEditSheet(instructor)}
|
|
640
659
|
>
|
|
641
660
|
<Pencil className="mr-2 h-4 w-4" />
|
|
642
|
-
|
|
661
|
+
{t('actions.edit')}
|
|
643
662
|
</DropdownMenuItem>
|
|
644
663
|
<DropdownMenuSeparator />
|
|
645
664
|
<DropdownMenuItem
|
|
@@ -650,7 +669,7 @@ export default function InstructorsPage() {
|
|
|
650
669
|
}}
|
|
651
670
|
>
|
|
652
671
|
<Trash2 className="mr-2 h-4 w-4" />
|
|
653
|
-
|
|
672
|
+
{t('actions.delete')}
|
|
654
673
|
</DropdownMenuItem>
|
|
655
674
|
</DropdownMenuContent>
|
|
656
675
|
</DropdownMenu>
|
|
@@ -666,7 +685,9 @@ export default function InstructorsPage() {
|
|
|
666
685
|
: 'border-gray-500/20 bg-gray-500/10 text-gray-600'
|
|
667
686
|
)}
|
|
668
687
|
>
|
|
669
|
-
{instructor.status === 'active'
|
|
688
|
+
{instructor.status === 'active'
|
|
689
|
+
? t('form.fields.active')
|
|
690
|
+
: t('form.fields.inactive')}
|
|
670
691
|
</Badge>
|
|
671
692
|
{instructor.qualificationSlugs.map((slug) => (
|
|
672
693
|
<Badge
|
|
@@ -674,7 +695,7 @@ export default function InstructorsPage() {
|
|
|
674
695
|
variant="outline"
|
|
675
696
|
className="border-blue-500/20 bg-blue-500/10 px-2 py-0.5 text-[11px] font-medium text-blue-600"
|
|
676
697
|
>
|
|
677
|
-
{
|
|
698
|
+
{getQualificationLabel(slug, t)}
|
|
678
699
|
</Badge>
|
|
679
700
|
))}
|
|
680
701
|
{(instructor.skills ?? []).map((skill) => (
|
|
@@ -721,23 +742,23 @@ export default function InstructorsPage() {
|
|
|
721
742
|
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
|
722
743
|
<AlertDialogContent>
|
|
723
744
|
<AlertDialogHeader>
|
|
724
|
-
<AlertDialogTitle>
|
|
745
|
+
<AlertDialogTitle>{t('deleteDialog.title')}</AlertDialogTitle>
|
|
725
746
|
<AlertDialogDescription>
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
747
|
+
{t('deleteDialog.description', {
|
|
748
|
+
name: instructorToDelete?.name ?? '',
|
|
749
|
+
})}
|
|
729
750
|
</AlertDialogDescription>
|
|
730
751
|
</AlertDialogHeader>
|
|
731
752
|
<div className="flex justify-end gap-2">
|
|
732
753
|
<AlertDialogCancel disabled={isDeleting}>
|
|
733
|
-
|
|
754
|
+
{t('actions.cancel')}
|
|
734
755
|
</AlertDialogCancel>
|
|
735
756
|
<AlertDialogAction
|
|
736
757
|
onClick={handleDeleteConfirm}
|
|
737
758
|
disabled={isDeleting}
|
|
738
759
|
className="bg-red-600 hover:bg-red-700"
|
|
739
760
|
>
|
|
740
|
-
{isDeleting ? '
|
|
761
|
+
{isDeleting ? t('actions.deleting') : t('actions.delete')}
|
|
741
762
|
</AlertDialogAction>
|
|
742
763
|
</div>
|
|
743
764
|
</AlertDialogContent>
|
|
@@ -1893,15 +1893,15 @@ export default function TrainingPage() {
|
|
|
1893
1893
|
<FieldError>{form.formState.errors.nome?.message}</FieldError>
|
|
1894
1894
|
</Field>
|
|
1895
1895
|
<Field>
|
|
1896
|
-
<FieldLabel htmlFor="descricao">
|
|
1897
|
-
{t('form.fields.
|
|
1896
|
+
<FieldLabel htmlFor="descricao">
|
|
1897
|
+
{t('form.fields.description.label')}{' '}
|
|
1898
1898
|
<span className="text-destructive">*</span>
|
|
1899
1899
|
</FieldLabel>
|
|
1900
1900
|
<Textarea
|
|
1901
|
-
id="descricao"
|
|
1901
|
+
id="descricao"
|
|
1902
1902
|
rows={3}
|
|
1903
|
-
placeholder={t('form.fields.
|
|
1904
|
-
{...form.register('descricao')}
|
|
1903
|
+
placeholder={t('form.fields.description.placeholder')}
|
|
1904
|
+
{...form.register('descricao')}
|
|
1905
1905
|
/>
|
|
1906
1906
|
<FieldError>
|
|
1907
1907
|
{form.formState.errors.descricao?.message}
|
|
@@ -1984,7 +1984,9 @@ export default function TrainingPage() {
|
|
|
1984
1984
|
|
|
1985
1985
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
1986
1986
|
<Field>
|
|
1987
|
-
<FieldLabel htmlFor="primaryColor">
|
|
1987
|
+
<FieldLabel htmlFor="primaryColor">
|
|
1988
|
+
{t('form.fields.primaryColor.label')}
|
|
1989
|
+
</FieldLabel>
|
|
1988
1990
|
<Controller
|
|
1989
1991
|
name="primaryColor"
|
|
1990
1992
|
control={form.control}
|
|
@@ -2011,7 +2013,9 @@ export default function TrainingPage() {
|
|
|
2011
2013
|
</Field>
|
|
2012
2014
|
|
|
2013
2015
|
<Field>
|
|
2014
|
-
<FieldLabel htmlFor="secondaryColor">
|
|
2016
|
+
<FieldLabel htmlFor="secondaryColor">
|
|
2017
|
+
{t('form.fields.secondaryColor.label')}
|
|
2018
|
+
</FieldLabel>
|
|
2015
2019
|
<Controller
|
|
2016
2020
|
name="secondaryColor"
|
|
2017
2021
|
control={form.control}
|
|
@@ -429,7 +429,7 @@ export default function ReportCoursesPage() {
|
|
|
429
429
|
}
|
|
430
430
|
};
|
|
431
431
|
|
|
432
|
-
const renderEmptyState = (className = 'min-h-
|
|
432
|
+
const renderEmptyState = (className = 'min-h-45') => (
|
|
433
433
|
<EmptyState
|
|
434
434
|
icon={Inbox}
|
|
435
435
|
title={t('emptyState.title')}
|
|
@@ -495,7 +495,7 @@ export default function ReportCoursesPage() {
|
|
|
495
495
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
496
496
|
{Array.from({ length: 4 }).map((_, i) => (
|
|
497
497
|
<Card key={i} className="overflow-hidden border-border/70 py-0">
|
|
498
|
-
<div className="h-1 w-full bg-
|
|
498
|
+
<div className="h-1 w-full bg-linear-to-r from-slate-300/70 via-slate-200 to-transparent" />
|
|
499
499
|
<CardContent className="p-6">
|
|
500
500
|
<Skeleton className="mb-3 h-4 w-28" />
|
|
501
501
|
<Skeleton className="mb-2 h-8 w-24" />
|
|
@@ -544,7 +544,7 @@ export default function ReportCoursesPage() {
|
|
|
544
544
|
<Card>
|
|
545
545
|
<CardContent className="p-6">
|
|
546
546
|
<Skeleton className="mb-4 h-5 w-40" />
|
|
547
|
-
<Skeleton className="h-
|
|
547
|
+
<Skeleton className="h-60 w-full" />
|
|
548
548
|
</CardContent>
|
|
549
549
|
</Card>
|
|
550
550
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
@@ -664,7 +664,7 @@ export default function ReportCoursesPage() {
|
|
|
664
664
|
<Table>
|
|
665
665
|
<TableHeader>
|
|
666
666
|
<TableRow>
|
|
667
|
-
<TableHead className="w-
|
|
667
|
+
<TableHead className="w-11">#</TableHead>
|
|
668
668
|
<TableHead>{t('table.course')}</TableHead>
|
|
669
669
|
<TableHead>{t('table.students')}</TableHead>
|
|
670
670
|
<TableHead className="hidden sm:table-cell">
|
|
@@ -789,7 +789,7 @@ export default function ReportCoursesPage() {
|
|
|
789
789
|
{loading ? (
|
|
790
790
|
<div className="p-6">
|
|
791
791
|
<Skeleton className="mb-4 h-5 w-48" />
|
|
792
|
-
<Skeleton className="h-
|
|
792
|
+
<Skeleton className="h-45 w-full" />
|
|
793
793
|
</div>
|
|
794
794
|
) : filteredCategoryPerformance.length === 0 ? (
|
|
795
795
|
<div className="px-6 pb-6">
|
|
@@ -452,7 +452,7 @@ export default function ReportsDashboardPage() {
|
|
|
452
452
|
}
|
|
453
453
|
};
|
|
454
454
|
|
|
455
|
-
const renderEmptyState = (className = 'min-h-
|
|
455
|
+
const renderEmptyState = (className = 'min-h-45') => (
|
|
456
456
|
<EmptyState
|
|
457
457
|
icon={Inbox}
|
|
458
458
|
title={t('emptyState.title')}
|
|
@@ -493,7 +493,7 @@ export default function ReportsDashboardPage() {
|
|
|
493
493
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
494
494
|
{Array.from({ length: 4 }).map((_, i) => (
|
|
495
495
|
<Card key={i} className="overflow-hidden border-border/70 py-0">
|
|
496
|
-
<div className="h-1 w-full bg-
|
|
496
|
+
<div className="h-1 w-full bg-linear-to-r from-slate-300/70 via-slate-200 to-transparent" />
|
|
497
497
|
<CardContent className="p-6">
|
|
498
498
|
<Skeleton className="mb-3 h-4 w-28" />
|
|
499
499
|
<Skeleton className="mb-2 h-8 w-24" />
|
|
@@ -534,7 +534,7 @@ export default function ReportsDashboardPage() {
|
|
|
534
534
|
<Card>
|
|
535
535
|
<CardContent className="p-6">
|
|
536
536
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
537
|
-
<Skeleton className="h-
|
|
537
|
+
<Skeleton className="h-60 w-full" />
|
|
538
538
|
</CardContent>
|
|
539
539
|
</Card>
|
|
540
540
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
@@ -626,13 +626,13 @@ export default function ReportsDashboardPage() {
|
|
|
626
626
|
<Card>
|
|
627
627
|
<CardContent className="p-6">
|
|
628
628
|
<Skeleton className="mb-4 h-5 w-40" />
|
|
629
|
-
<Skeleton className="h-
|
|
629
|
+
<Skeleton className="h-75 w-full" />
|
|
630
630
|
</CardContent>
|
|
631
631
|
</Card>
|
|
632
632
|
<Card>
|
|
633
633
|
<CardContent className="p-6">
|
|
634
634
|
<Skeleton className="mb-4 h-5 w-40" />
|
|
635
|
-
<Skeleton className="h-
|
|
635
|
+
<Skeleton className="h-75 w-full" />
|
|
636
636
|
</CardContent>
|
|
637
637
|
</Card>
|
|
638
638
|
</>
|
|
@@ -654,7 +654,7 @@ export default function ReportsDashboardPage() {
|
|
|
654
654
|
<Table>
|
|
655
655
|
<TableHeader>
|
|
656
656
|
<TableRow>
|
|
657
|
-
<TableHead className="w-
|
|
657
|
+
<TableHead className="w-11">#</TableHead>
|
|
658
658
|
<TableHead>{t('table.course')}</TableHead>
|
|
659
659
|
<TableHead>{t('table.students')}</TableHead>
|
|
660
660
|
<TableHead>{t('table.score')}</TableHead>
|
|
@@ -736,13 +736,13 @@ export default function ReportsDashboardPage() {
|
|
|
736
736
|
<Card>
|
|
737
737
|
<CardContent className="p-6">
|
|
738
738
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
739
|
-
<Skeleton className="h-
|
|
739
|
+
<Skeleton className="h-65 w-full" />
|
|
740
740
|
</CardContent>
|
|
741
741
|
</Card>
|
|
742
742
|
<Card>
|
|
743
743
|
<CardContent className="p-6">
|
|
744
744
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
745
|
-
<Skeleton className="h-
|
|
745
|
+
<Skeleton className="h-65 w-full" />
|
|
746
746
|
</CardContent>
|
|
747
747
|
</Card>
|
|
748
748
|
</>
|
|
@@ -412,7 +412,7 @@ export default function ReportsDashboardPage() {
|
|
|
412
412
|
}
|
|
413
413
|
};
|
|
414
414
|
|
|
415
|
-
const renderEmptyState = (className = 'min-h-
|
|
415
|
+
const renderEmptyState = (className = 'min-h-45') => (
|
|
416
416
|
<div
|
|
417
417
|
className={`flex flex-col items-center justify-center rounded-lg border border-dashed bg-muted/20 px-6 py-10 text-center ${className}`}
|
|
418
418
|
>
|
|
@@ -496,7 +496,7 @@ export default function ReportsDashboardPage() {
|
|
|
496
496
|
<Card>
|
|
497
497
|
<CardContent className="p-6">
|
|
498
498
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
499
|
-
<Skeleton className="h-
|
|
499
|
+
<Skeleton className="h-60 w-full" />
|
|
500
500
|
</CardContent>
|
|
501
501
|
</Card>
|
|
502
502
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
@@ -640,13 +640,13 @@ export default function ReportsDashboardPage() {
|
|
|
640
640
|
<Card>
|
|
641
641
|
<CardContent className="p-6">
|
|
642
642
|
<Skeleton className="mb-4 h-5 w-40" />
|
|
643
|
-
<Skeleton className="h-
|
|
643
|
+
<Skeleton className="h-75 w-full" />
|
|
644
644
|
</CardContent>
|
|
645
645
|
</Card>
|
|
646
646
|
<Card>
|
|
647
647
|
<CardContent className="p-6">
|
|
648
648
|
<Skeleton className="mb-4 h-5 w-40" />
|
|
649
|
-
<Skeleton className="h-
|
|
649
|
+
<Skeleton className="h-75 w-full" />
|
|
650
650
|
</CardContent>
|
|
651
651
|
</Card>
|
|
652
652
|
</>
|
|
@@ -668,7 +668,7 @@ export default function ReportsDashboardPage() {
|
|
|
668
668
|
<Table>
|
|
669
669
|
<TableHeader>
|
|
670
670
|
<TableRow>
|
|
671
|
-
<TableHead className="w-
|
|
671
|
+
<TableHead className="w-11">#</TableHead>
|
|
672
672
|
<TableHead>{t('table.course')}</TableHead>
|
|
673
673
|
<TableHead>{t('table.students')}</TableHead>
|
|
674
674
|
<TableHead>{t('table.score')}</TableHead>
|
|
@@ -750,13 +750,13 @@ export default function ReportsDashboardPage() {
|
|
|
750
750
|
<Card>
|
|
751
751
|
<CardContent className="p-6">
|
|
752
752
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
753
|
-
<Skeleton className="h-
|
|
753
|
+
<Skeleton className="h-65 w-full" />
|
|
754
754
|
</CardContent>
|
|
755
755
|
</Card>
|
|
756
756
|
<Card>
|
|
757
757
|
<CardContent className="p-6">
|
|
758
758
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
759
|
-
<Skeleton className="h-
|
|
759
|
+
<Skeleton className="h-65 w-full" />
|
|
760
760
|
</CardContent>
|
|
761
761
|
</Card>
|
|
762
762
|
</>
|
|
@@ -422,7 +422,7 @@ export default function ReportStudentsPage() {
|
|
|
422
422
|
}
|
|
423
423
|
};
|
|
424
424
|
|
|
425
|
-
const renderEmptyState = (className = 'min-h-
|
|
425
|
+
const renderEmptyState = (className = 'min-h-45') => (
|
|
426
426
|
<EmptyState
|
|
427
427
|
icon={Inbox}
|
|
428
428
|
title={t('emptyState.title')}
|
|
@@ -480,7 +480,7 @@ export default function ReportStudentsPage() {
|
|
|
480
480
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
481
481
|
{Array.from({ length: 4 }).map((_, i) => (
|
|
482
482
|
<Card key={i} className="overflow-hidden border-border/70 py-0">
|
|
483
|
-
<div className="h-1 w-full bg-
|
|
483
|
+
<div className="h-1 w-full bg-linear-to-r from-slate-300/70 via-slate-200 to-transparent" />
|
|
484
484
|
<CardContent className="p-6">
|
|
485
485
|
<Skeleton className="mb-3 h-4 w-28" />
|
|
486
486
|
<Skeleton className="mb-2 h-8 w-24" />
|
|
@@ -529,7 +529,7 @@ export default function ReportStudentsPage() {
|
|
|
529
529
|
<Card>
|
|
530
530
|
<CardContent className="p-6">
|
|
531
531
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
532
|
-
<Skeleton className="h-
|
|
532
|
+
<Skeleton className="h-60 w-full" />
|
|
533
533
|
</CardContent>
|
|
534
534
|
</Card>
|
|
535
535
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
@@ -611,13 +611,13 @@ export default function ReportStudentsPage() {
|
|
|
611
611
|
<Card>
|
|
612
612
|
<CardContent className="p-6">
|
|
613
613
|
<Skeleton className="mb-4 h-5 w-40" />
|
|
614
|
-
<Skeleton className="h-
|
|
614
|
+
<Skeleton className="h-75 w-full" />
|
|
615
615
|
</CardContent>
|
|
616
616
|
</Card>
|
|
617
617
|
<Card>
|
|
618
618
|
<CardContent className="p-6">
|
|
619
619
|
<Skeleton className="mb-4 h-5 w-44" />
|
|
620
|
-
<Skeleton className="h-
|
|
620
|
+
<Skeleton className="h-75 w-full" />
|
|
621
621
|
</CardContent>
|
|
622
622
|
</Card>
|
|
623
623
|
</>
|
|
@@ -718,7 +718,7 @@ export default function ReportStudentsPage() {
|
|
|
718
718
|
{loading ? (
|
|
719
719
|
<div className="p-6">
|
|
720
720
|
<Skeleton className="mb-4 h-5 w-48" />
|
|
721
|
-
<Skeleton className="h-
|
|
721
|
+
<Skeleton className="h-45 w-full" />
|
|
722
722
|
</div>
|
|
723
723
|
) : filteredCategoryPerformance.length === 0 ? (
|
|
724
724
|
<div className="px-6 pb-6">
|
|
@@ -1886,15 +1886,15 @@ export default function TrainingPage() {
|
|
|
1886
1886
|
<FieldError>{form.formState.errors.nome?.message}</FieldError>
|
|
1887
1887
|
</Field>
|
|
1888
1888
|
<Field>
|
|
1889
|
-
<FieldLabel htmlFor="descricao">
|
|
1890
|
-
{t('form.fields.
|
|
1889
|
+
<FieldLabel htmlFor="descricao">
|
|
1890
|
+
{t('form.fields.description.label')}{' '}
|
|
1891
1891
|
<span className="text-destructive">*</span>
|
|
1892
1892
|
</FieldLabel>
|
|
1893
1893
|
<Textarea
|
|
1894
|
-
id="descricao"
|
|
1894
|
+
id="descricao"
|
|
1895
1895
|
rows={3}
|
|
1896
|
-
placeholder={t('form.fields.
|
|
1897
|
-
{...form.register('descricao')}
|
|
1896
|
+
placeholder={t('form.fields.description.placeholder')}
|
|
1897
|
+
{...form.register('descricao')}
|
|
1898
1898
|
/>
|
|
1899
1899
|
<FieldError>
|
|
1900
1900
|
{form.formState.errors.descricao?.message}
|