@hed-hog/lms 0.0.330 → 0.0.338
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/dist/class-group/class-group.controller.d.ts +3 -3
- package/dist/class-group/class-group.service.d.ts +3 -3
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +12 -20
- package/dist/course/course.service.js.map +1 -1
- package/dist/enterprise/enterprise.controller.d.ts +72 -0
- package/dist/enterprise/enterprise.controller.d.ts.map +1 -1
- package/dist/enterprise/enterprise.controller.js +10 -0
- package/dist/enterprise/enterprise.controller.js.map +1 -1
- package/dist/enterprise/enterprise.service.d.ts +78 -0
- package/dist/enterprise/enterprise.service.d.ts.map +1 -1
- package/dist/enterprise/enterprise.service.js +413 -40
- package/dist/enterprise/enterprise.service.js.map +1 -1
- package/dist/enterprise/training/training-admin.controller.d.ts +6 -3
- package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
- package/dist/enterprise/training/training-admin.controller.js +10 -6
- package/dist/enterprise/training/training-admin.controller.js.map +1 -1
- package/dist/enterprise/training/training-admin.service.d.ts +8 -2
- package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-admin.service.js +108 -52
- package/dist/enterprise/training/training-admin.service.js.map +1 -1
- package/dist/enterprise/training/training-viewer.controller.d.ts +3 -0
- package/dist/enterprise/training/training-viewer.controller.d.ts.map +1 -1
- package/dist/evaluation/evaluation.controller.d.ts +4 -4
- package/dist/evaluation/evaluation.service.d.ts +4 -4
- package/dist/instructor/dto/create-instructor-skill.dto.d.ts +0 -4
- package/dist/instructor/dto/create-instructor-skill.dto.d.ts.map +1 -1
- package/dist/instructor/dto/create-instructor-skill.dto.js +0 -21
- package/dist/instructor/dto/create-instructor-skill.dto.js.map +1 -1
- package/dist/instructor/dto/update-instructor-skill.dto.d.ts +0 -4
- package/dist/instructor/dto/update-instructor-skill.dto.d.ts.map +1 -1
- package/dist/instructor/dto/update-instructor-skill.dto.js +0 -22
- package/dist/instructor/dto/update-instructor-skill.dto.js.map +1 -1
- package/dist/instructor/instructor-skill.controller.d.ts +4 -4
- package/dist/instructor/instructor-skill.service.d.ts +4 -7
- package/dist/instructor/instructor-skill.service.d.ts.map +1 -1
- package/dist/instructor/instructor-skill.service.js +2 -89
- package/dist/instructor/instructor-skill.service.js.map +1 -1
- package/dist/instructor/instructor.controller.d.ts +20 -0
- package/dist/instructor/instructor.controller.d.ts.map +1 -1
- package/dist/instructor/instructor.controller.js +19 -0
- package/dist/instructor/instructor.controller.js.map +1 -1
- package/dist/instructor/instructor.service.d.ts +25 -0
- package/dist/instructor/instructor.service.d.ts.map +1 -1
- package/dist/instructor/instructor.service.js +70 -18
- package/dist/instructor/instructor.service.js.map +1 -1
- package/dist/lms.module.d.ts.map +1 -1
- package/dist/lms.module.js.map +1 -1
- package/hedhog/data/route.yaml +23 -1
- package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +42 -24
- package/hedhog/frontend/app/_components/create-lms-instructor-sheet.tsx.ejs +591 -0
- package/hedhog/frontend/app/certificates/issued/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/certificates/models/page.tsx.ejs +7 -2
- package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +17 -17
- package/hedhog/frontend/app/classes/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/courses/[id]/_components/CourseClassificationCard.tsx.ejs +3 -33
- package/hedhog/frontend/app/courses/[id]/_components/CourseContentCard.tsx.ejs +9 -9
- package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +109 -0
- package/hedhog/frontend/app/courses/[id]/_components/CourseMultiEntityPicker.tsx.ejs +42 -15
- package/hedhog/frontend/app/courses/[id]/_components/CourseRelationsCard.tsx.ejs +76 -81
- package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +60 -0
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +3 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-scheduled-classes-tab.tsx.ejs +406 -0
- 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.tsx.ejs +134 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +113 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +314 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +174 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +242 -33
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +228 -152
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +185 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +71 -31
- package/hedhog/frontend/app/courses/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +37 -41
- package/hedhog/frontend/app/enterprise/_components/enterprise-activity-timeline.tsx.ejs +87 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-admin-create-sheet.tsx.ejs +4 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-administrators-tab.tsx.ejs +31 -5
- package/hedhog/frontend/app/enterprise/_components/enterprise-classes-tab.tsx.ejs +79 -20
- package/hedhog/frontend/app/enterprise/_components/enterprise-company-identity-card.tsx.ejs +11 -2
- package/hedhog/frontend/app/enterprise/_components/enterprise-course-edit-sheet.tsx.ejs +201 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-courses-tab.tsx.ejs +55 -24
- package/hedhog/frontend/app/enterprise/_components/enterprise-detail-sheet.tsx.ejs +430 -296
- package/hedhog/frontend/app/enterprise/_components/enterprise-mocks.ts.ejs +277 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-overview-analytics.tsx.ejs +205 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-person-edit-sheet.tsx.ejs +97 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-sheet.tsx.ejs +82 -57
- package/hedhog/frontend/app/enterprise/_components/enterprise-student-create-sheet.tsx.ejs +4 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-students-tab.tsx.ejs +60 -22
- package/hedhog/frontend/app/enterprise/_components/enterprise-types.ts.ejs +54 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-user-create-sheet.tsx.ejs +211 -0
- package/hedhog/frontend/app/enterprise/page.tsx.ejs +39 -7
- package/hedhog/frontend/app/evaluations/_components/evaluation-topic-form-sheet.tsx.ejs +1 -1
- package/hedhog/frontend/app/exams/[id]/questions/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/exams/page.tsx.ejs +12 -3
- package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +51 -104
- package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +712 -427
- package/hedhog/frontend/app/instructors/page.tsx.ejs +77 -53
- package/hedhog/frontend/app/paths/page.tsx.ejs +14 -5
- 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/evaluations/page.tsx.ejs +6 -1
- 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 +8 -3
- package/hedhog/frontend/messages/en.json +394 -55
- package/hedhog/frontend/messages/pt.json +389 -48
- 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/enterprise_student_license_event.yaml +30 -0
- package/hedhog/table/instructor_qualification.yaml +1 -1
- package/hedhog/table/instructor_skill.yaml +0 -11
- package/package.json +8 -8
- package/src/course/course.service.ts +12 -24
- package/src/enterprise/enterprise.controller.ts +5 -0
- package/src/enterprise/enterprise.service.ts +507 -29
- package/src/enterprise/training/training-admin.controller.ts +4 -0
- package/src/enterprise/training/training-admin.service.ts +115 -51
- package/src/instructor/dto/create-instructor-skill.dto.ts +0 -17
- package/src/instructor/dto/update-instructor-skill.dto.ts +0 -18
- package/src/instructor/instructor-skill.service.ts +2 -97
- package/src/instructor/instructor.controller.ts +16 -0
- package/src/instructor/instructor.service.ts +85 -10
- package/src/lms.module.ts +1 -0
|
@@ -2452,13 +2452,13 @@ export default function TurmaDetalhePage() {
|
|
|
2452
2452
|
},
|
|
2453
2453
|
{
|
|
2454
2454
|
key: 'next-session',
|
|
2455
|
-
title: '
|
|
2455
|
+
title: t('kpis.nextClass'),
|
|
2456
2456
|
value: nextSession
|
|
2457
2457
|
? format(nextSessionStartsAt!, 'dd/MM', { locale: dateLocale })
|
|
2458
|
-
: '
|
|
2458
|
+
: t('kpis.noClass'),
|
|
2459
2459
|
description: nextSession
|
|
2460
2460
|
? `${nextSession.horaInicio} - ${nextSession.horaFim}`
|
|
2461
|
-
: '
|
|
2461
|
+
: t('kpis.createNext'),
|
|
2462
2462
|
icon: Clock,
|
|
2463
2463
|
iconContainerClassName: 'bg-emerald-500/10 text-emerald-700',
|
|
2464
2464
|
accentClassName: 'from-emerald-500/25 via-green-500/10 to-transparent',
|
|
@@ -2466,9 +2466,9 @@ export default function TurmaDetalhePage() {
|
|
|
2466
2466
|
},
|
|
2467
2467
|
{
|
|
2468
2468
|
key: 'calendar',
|
|
2469
|
-
title: '
|
|
2469
|
+
title: t('kpis.calendar'),
|
|
2470
2470
|
value: totalSessionsCount,
|
|
2471
|
-
description:
|
|
2471
|
+
description: t('kpis.completed', { count: completedSessionsCount }),
|
|
2472
2472
|
icon: CalendarIcon,
|
|
2473
2473
|
iconContainerClassName: 'bg-violet-500/10 text-violet-700',
|
|
2474
2474
|
accentClassName: 'from-violet-500/25 via-violet-500/10 to-transparent',
|
|
@@ -2582,7 +2582,7 @@ export default function TurmaDetalhePage() {
|
|
|
2582
2582
|
variant: 'outline',
|
|
2583
2583
|
},
|
|
2584
2584
|
{
|
|
2585
|
-
label: '
|
|
2585
|
+
label: t('actions.editClass'),
|
|
2586
2586
|
onClick: () => setEditSheetOpen(true),
|
|
2587
2587
|
variant: 'default',
|
|
2588
2588
|
},
|
|
@@ -2660,7 +2660,7 @@ export default function TurmaDetalhePage() {
|
|
|
2660
2660
|
key={i}
|
|
2661
2661
|
className="overflow-hidden border-border/70 py-0"
|
|
2662
2662
|
>
|
|
2663
|
-
<div className="h-1 w-full bg-
|
|
2663
|
+
<div className="h-1 w-full bg-linear-to-r from-slate-300/70 via-slate-200 to-transparent" />
|
|
2664
2664
|
<CardContent className="p-4">
|
|
2665
2665
|
<Skeleton className="mb-2 h-8 w-16" />
|
|
2666
2666
|
<Skeleton className="h-4 w-28" />
|
|
@@ -2803,7 +2803,7 @@ export default function TurmaDetalhePage() {
|
|
|
2803
2803
|
#
|
|
2804
2804
|
</TableHead>
|
|
2805
2805
|
<TableHead>Sessão</TableHead>
|
|
2806
|
-
<TableHead className="w-
|
|
2806
|
+
<TableHead className="w-30">Data</TableHead>
|
|
2807
2807
|
<TableHead className="w-[105px]">Horário</TableHead>
|
|
2808
2808
|
<TableHead className="w-[90px]">Tipo</TableHead>
|
|
2809
2809
|
<TableHead>Instrutor</TableHead>
|
|
@@ -2814,7 +2814,7 @@ export default function TurmaDetalhePage() {
|
|
|
2814
2814
|
Materiais
|
|
2815
2815
|
</TableHead>
|
|
2816
2816
|
<TableHead className="w-[90px]">Link</TableHead>
|
|
2817
|
-
<TableHead className="w-
|
|
2817
|
+
<TableHead className="w-11" />
|
|
2818
2818
|
</TableRow>
|
|
2819
2819
|
</TableHeader>
|
|
2820
2820
|
<TableBody>
|
|
@@ -3359,7 +3359,7 @@ export default function TurmaDetalhePage() {
|
|
|
3359
3359
|
src={getPersonAvatarUrl(aluno.avatarId)}
|
|
3360
3360
|
alt={aluno.nome}
|
|
3361
3361
|
/>
|
|
3362
|
-
<AvatarFallback className="bg-
|
|
3362
|
+
<AvatarFallback className="bg-linear-to-br from-blue-100 to-blue-200 text-[11px] font-medium text-blue-700">
|
|
3363
3363
|
{getPersonInitials(aluno.nome)}
|
|
3364
3364
|
</AvatarFallback>
|
|
3365
3365
|
</Avatar>
|
|
@@ -3616,7 +3616,7 @@ export default function TurmaDetalhePage() {
|
|
|
3616
3616
|
{tClasses(`type.${aula.tipo}`)}
|
|
3617
3617
|
</Badge>
|
|
3618
3618
|
</TableCell>
|
|
3619
|
-
<TableCell className="max-w-
|
|
3619
|
+
<TableCell className="max-w-45 truncate text-sm text-muted-foreground">
|
|
3620
3620
|
{aula.meetingUrl || aula.local || '—'}
|
|
3621
3621
|
</TableCell>
|
|
3622
3622
|
<TableCell className="text-sm text-muted-foreground">
|
|
@@ -3857,7 +3857,7 @@ export default function TurmaDetalhePage() {
|
|
|
3857
3857
|
<Table>
|
|
3858
3858
|
<TableHeader>
|
|
3859
3859
|
<TableRow className="bg-muted/40 hover:bg-muted/40">
|
|
3860
|
-
<TableHead className="sticky left-0 z-10 min-w-
|
|
3860
|
+
<TableHead className="sticky left-0 z-10 min-w-65 bg-muted/40 font-semibold">
|
|
3861
3861
|
{t('tabs.students')}
|
|
3862
3862
|
</TableHead>
|
|
3863
3863
|
{aulasState.map((aula) => {
|
|
@@ -3886,14 +3886,14 @@ export default function TurmaDetalhePage() {
|
|
|
3886
3886
|
key={aluno.id}
|
|
3887
3887
|
className="hover:bg-muted/30"
|
|
3888
3888
|
>
|
|
3889
|
-
<TableCell className="sticky left-0 z-10 min-w-
|
|
3889
|
+
<TableCell className="sticky left-0 z-10 min-w-65 border-r border-border/40 bg-background">
|
|
3890
3890
|
<div className="flex min-w-0 items-center gap-3">
|
|
3891
3891
|
<Avatar className="size-8 shrink-0">
|
|
3892
3892
|
<AvatarImage
|
|
3893
3893
|
src={getPersonAvatarUrl(aluno.avatarId)}
|
|
3894
3894
|
alt={aluno.nome}
|
|
3895
3895
|
/>
|
|
3896
|
-
<AvatarFallback className="bg-
|
|
3896
|
+
<AvatarFallback className="bg-linear-to-br from-blue-100 to-blue-200 text-[11px] font-medium text-blue-700">
|
|
3897
3897
|
{getPersonInitials(aluno.nome)}
|
|
3898
3898
|
</AvatarFallback>
|
|
3899
3899
|
</Avatar>
|
|
@@ -4195,7 +4195,7 @@ export default function TurmaDetalhePage() {
|
|
|
4195
4195
|
globalLinkTitleEditedRef.current =
|
|
4196
4196
|
e.target.value.length > 0;
|
|
4197
4197
|
}}
|
|
4198
|
-
placeholder=
|
|
4198
|
+
placeholder={t('links.studyRefPlaceholder')}
|
|
4199
4199
|
/>
|
|
4200
4200
|
</Field>
|
|
4201
4201
|
<div className="flex gap-2">
|
|
@@ -4615,7 +4615,7 @@ export default function TurmaDetalhePage() {
|
|
|
4615
4615
|
src={getPersonAvatarUrl(selectedStudentProfile.avatarId)}
|
|
4616
4616
|
alt={selectedStudentProfile.nome}
|
|
4617
4617
|
/>
|
|
4618
|
-
<AvatarFallback className="bg-
|
|
4618
|
+
<AvatarFallback className="bg-linear-to-br from-blue-100 to-blue-200 text-xs font-medium text-blue-700">
|
|
4619
4619
|
{getPersonInitials(selectedStudentProfile.nome)}
|
|
4620
4620
|
</AvatarFallback>
|
|
4621
4621
|
</Avatar>
|
|
@@ -5655,7 +5655,7 @@ export default function TurmaDetalhePage() {
|
|
|
5655
5655
|
linkTitleEditedRef.current =
|
|
5656
5656
|
e.target.value.length > 0;
|
|
5657
5657
|
}}
|
|
5658
|
-
placeholder=
|
|
5658
|
+
placeholder={t('links.lessonSlidesPlaceholder')}
|
|
5659
5659
|
/>
|
|
5660
5660
|
</Field>
|
|
5661
5661
|
<div className="flex gap-2">
|
|
@@ -95,6 +95,7 @@ import {
|
|
|
95
95
|
import { useTranslations } from 'next-intl';
|
|
96
96
|
import { useRouter } from 'next/navigation';
|
|
97
97
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
98
|
+
import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
|
|
98
99
|
import type { DateRange } from 'react-day-picker';
|
|
99
100
|
import { Controller, useForm, useWatch } from 'react-hook-form';
|
|
100
101
|
import { toast } from 'sonner';
|
|
@@ -700,7 +701,11 @@ export default function TurmasPage() {
|
|
|
700
701
|
|
|
701
702
|
// Pagination
|
|
702
703
|
const [currentPage, setCurrentPage] = useState(1);
|
|
703
|
-
const [pageSize, setPageSize] =
|
|
704
|
+
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
705
|
+
storageKey: 'pagination:global:pageSize',
|
|
706
|
+
defaultValue: 12,
|
|
707
|
+
allowedValues: PAGE_SIZES,
|
|
708
|
+
});
|
|
704
709
|
|
|
705
710
|
// Double-click tracking
|
|
706
711
|
const clickTimers = useRef<Map<number, ReturnType<typeof setTimeout>>>(
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
SelectTrigger,
|
|
14
14
|
SelectValue,
|
|
15
15
|
} from '@/components/ui/select';
|
|
16
|
-
import {
|
|
16
|
+
import { Settings2 } from 'lucide-react';
|
|
17
17
|
import type { UseFormReturn } from 'react-hook-form';
|
|
18
18
|
|
|
19
19
|
import { CourseSectionCard } from './CourseSectionCard';
|
|
@@ -33,23 +33,6 @@ type CourseClassificationCardProps = {
|
|
|
33
33
|
offeringTypes: readonly SelectOption[];
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
function ColorPreview({ color, label }: { color: string; label: string }) {
|
|
37
|
-
return (
|
|
38
|
-
<div className="flex items-center gap-2 rounded-lg border border-border/60 bg-muted/20 px-2.5 py-1.5">
|
|
39
|
-
<span
|
|
40
|
-
className="h-4 w-4 shrink-0 rounded-full border border-black/10"
|
|
41
|
-
style={{ backgroundColor: color }}
|
|
42
|
-
/>
|
|
43
|
-
<div className="min-w-0">
|
|
44
|
-
<p className="text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
|
|
45
|
-
{label}
|
|
46
|
-
</p>
|
|
47
|
-
<p className="truncate text-xs font-medium text-foreground">{color}</p>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
36
|
export function CourseClassificationCard({
|
|
54
37
|
form,
|
|
55
38
|
t,
|
|
@@ -57,10 +40,6 @@ export function CourseClassificationCard({
|
|
|
57
40
|
statuses,
|
|
58
41
|
offeringTypes,
|
|
59
42
|
}: CourseClassificationCardProps) {
|
|
60
|
-
const watchedPrimary = form.watch('primaryColor');
|
|
61
|
-
const watchedSecondary = form.watch('secondaryColor');
|
|
62
|
-
const watchedOfferingType = form.watch('tipoOferta');
|
|
63
|
-
|
|
64
43
|
return (
|
|
65
44
|
<CourseSectionCard
|
|
66
45
|
title="Classificação e configuração"
|
|
@@ -156,7 +135,7 @@ export function CourseClassificationCard({
|
|
|
156
135
|
<FormItem>
|
|
157
136
|
<FormLabel>{t('form.fields.primaryColor.label')}</FormLabel>
|
|
158
137
|
<FormControl>
|
|
159
|
-
<div className="flex items-center gap-2
|
|
138
|
+
<div className="flex items-center gap-2">
|
|
160
139
|
<Input
|
|
161
140
|
type="color"
|
|
162
141
|
value={field.value}
|
|
@@ -183,7 +162,7 @@ export function CourseClassificationCard({
|
|
|
183
162
|
<FormItem>
|
|
184
163
|
<FormLabel>{t('form.fields.secondaryColor.label')}</FormLabel>
|
|
185
164
|
<FormControl>
|
|
186
|
-
<div className="flex items-center gap-2
|
|
165
|
+
<div className="flex items-center gap-2">
|
|
187
166
|
<Input
|
|
188
167
|
type="color"
|
|
189
168
|
value={field.value}
|
|
@@ -202,15 +181,6 @@ export function CourseClassificationCard({
|
|
|
202
181
|
</FormItem>
|
|
203
182
|
)}
|
|
204
183
|
/>
|
|
205
|
-
|
|
206
|
-
<div className="space-y-2 rounded-lg border border-border/60 bg-linear-to-br from-muted/30 to-background p-3">
|
|
207
|
-
<div className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
|
208
|
-
<Palette className="h-3.5 w-3.5" />
|
|
209
|
-
Preview
|
|
210
|
-
</div>
|
|
211
|
-
<ColorPreview color={watchedPrimary} label="Primária" />
|
|
212
|
-
<ColorPreview color={watchedSecondary} label="Secundária" />
|
|
213
|
-
</div>
|
|
214
184
|
</div>
|
|
215
185
|
</CourseSectionCard>
|
|
216
186
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RichTextEditor } from '@/components/rich-text-editor';
|
|
1
2
|
import {
|
|
2
3
|
FormControl,
|
|
3
4
|
FormField,
|
|
@@ -5,7 +6,6 @@ import {
|
|
|
5
6
|
FormLabel,
|
|
6
7
|
FormMessage,
|
|
7
8
|
} from '@/components/ui/form';
|
|
8
|
-
import { Textarea } from '@/components/ui/textarea';
|
|
9
9
|
import { FileText } from 'lucide-react';
|
|
10
10
|
import type { UseFormReturn } from 'react-hook-form';
|
|
11
11
|
|
|
@@ -31,10 +31,10 @@ export function CourseContentCard({ form }: CourseContentCardProps) {
|
|
|
31
31
|
<FormItem>
|
|
32
32
|
<FormLabel>Objetivos do curso</FormLabel>
|
|
33
33
|
<FormControl>
|
|
34
|
-
<
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
<RichTextEditor
|
|
35
|
+
value={field.value || ''}
|
|
36
|
+
onChange={field.onChange}
|
|
37
|
+
className="w-full max-w-full"
|
|
38
38
|
/>
|
|
39
39
|
</FormControl>
|
|
40
40
|
<FormMessage />
|
|
@@ -49,10 +49,10 @@ export function CourseContentCard({ form }: CourseContentCardProps) {
|
|
|
49
49
|
<FormItem>
|
|
50
50
|
<FormLabel>Público-alvo</FormLabel>
|
|
51
51
|
<FormControl>
|
|
52
|
-
<
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
<RichTextEditor
|
|
53
|
+
value={field.value || ''}
|
|
54
|
+
onChange={field.onChange}
|
|
55
|
+
className="w-full max-w-full"
|
|
56
56
|
/>
|
|
57
57
|
</FormControl>
|
|
58
58
|
<FormMessage />
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { RichTextEditor } from '@/components/rich-text-editor';
|
|
2
|
+
import {
|
|
3
|
+
FormControl,
|
|
4
|
+
FormField,
|
|
5
|
+
FormItem,
|
|
6
|
+
FormLabel,
|
|
7
|
+
FormMessage,
|
|
8
|
+
} from '@/components/ui/form';
|
|
9
|
+
import { Input } from '@/components/ui/input';
|
|
10
|
+
import { Hash, NotebookPen } from 'lucide-react';
|
|
11
|
+
import type { UseFormReturn } from 'react-hook-form';
|
|
12
|
+
|
|
13
|
+
import { CourseSectionCard } from './CourseSectionCard';
|
|
14
|
+
import type { CourseEditFormValues, TranslationFn } from './course-edit-types';
|
|
15
|
+
|
|
16
|
+
type CourseMainInfoCardProps = {
|
|
17
|
+
form: UseFormReturn<CourseEditFormValues>;
|
|
18
|
+
t: TranslationFn;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function CourseMainInfoCard({ form, t }: CourseMainInfoCardProps) {
|
|
22
|
+
return (
|
|
23
|
+
<CourseSectionCard
|
|
24
|
+
title={t('form.sections.basicInfo')}
|
|
25
|
+
description="Os identificadores e a comunicação principal do curso ficam aqui."
|
|
26
|
+
icon={NotebookPen}
|
|
27
|
+
>
|
|
28
|
+
<div className="grid gap-3 md:grid-cols-2">
|
|
29
|
+
<FormField
|
|
30
|
+
control={form.control}
|
|
31
|
+
name="slug"
|
|
32
|
+
render={({ field }) => (
|
|
33
|
+
<FormItem>
|
|
34
|
+
<FormLabel>{t('form.fields.slug.label')}</FormLabel>
|
|
35
|
+
<FormControl>
|
|
36
|
+
<div className="relative">
|
|
37
|
+
<Hash className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
|
38
|
+
<Input
|
|
39
|
+
{...field}
|
|
40
|
+
className="pl-9 font-mono"
|
|
41
|
+
placeholder={t('form.fields.slug.placeholder')}
|
|
42
|
+
onChange={(event) =>
|
|
43
|
+
field.onChange(
|
|
44
|
+
String(event.target.value || '').toLowerCase()
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
</FormControl>
|
|
50
|
+
<FormMessage />
|
|
51
|
+
</FormItem>
|
|
52
|
+
)}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<FormField
|
|
56
|
+
control={form.control}
|
|
57
|
+
name="nomeInterno"
|
|
58
|
+
render={({ field }) => (
|
|
59
|
+
<FormItem>
|
|
60
|
+
<FormLabel>{t('form.fields.internalName.label')}</FormLabel>
|
|
61
|
+
<FormControl>
|
|
62
|
+
<Input
|
|
63
|
+
{...field}
|
|
64
|
+
placeholder={t('form.fields.internalName.placeholder')}
|
|
65
|
+
/>
|
|
66
|
+
</FormControl>
|
|
67
|
+
<FormMessage />
|
|
68
|
+
</FormItem>
|
|
69
|
+
)}
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
<FormField
|
|
73
|
+
control={form.control}
|
|
74
|
+
name="tituloComercial"
|
|
75
|
+
render={({ field }) => (
|
|
76
|
+
<FormItem className="md:col-span-2">
|
|
77
|
+
<FormLabel>{t('form.fields.title.label')}</FormLabel>
|
|
78
|
+
<FormControl>
|
|
79
|
+
<Input
|
|
80
|
+
{...field}
|
|
81
|
+
placeholder={t('form.fields.title.placeholder')}
|
|
82
|
+
/>
|
|
83
|
+
</FormControl>
|
|
84
|
+
<FormMessage />
|
|
85
|
+
</FormItem>
|
|
86
|
+
)}
|
|
87
|
+
/>
|
|
88
|
+
|
|
89
|
+
<FormField
|
|
90
|
+
control={form.control}
|
|
91
|
+
name="descricaoPublica"
|
|
92
|
+
render={({ field }) => (
|
|
93
|
+
<FormItem className="md:col-span-2">
|
|
94
|
+
<FormLabel>{t('form.fields.description.label')}</FormLabel>
|
|
95
|
+
<FormControl>
|
|
96
|
+
<RichTextEditor
|
|
97
|
+
value={field.value}
|
|
98
|
+
onChange={field.onChange}
|
|
99
|
+
className="w-full max-w-full"
|
|
100
|
+
/>
|
|
101
|
+
</FormControl>
|
|
102
|
+
<FormMessage />
|
|
103
|
+
</FormItem>
|
|
104
|
+
)}
|
|
105
|
+
/>
|
|
106
|
+
</div>
|
|
107
|
+
</CourseSectionCard>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
|
2
|
+
import { Badge } from '@/components/ui/badge';
|
|
2
3
|
import { Button } from '@/components/ui/button';
|
|
3
4
|
import { EntityPicker } from '@/components/ui/entity-picker';
|
|
4
|
-
import { Badge } from '@/components/ui/badge';
|
|
5
5
|
import { cn } from '@/lib/utils';
|
|
6
|
-
import { Grip, Plus, X } from 'lucide-react';
|
|
6
|
+
import { Grip, Pencil, Plus, X } from 'lucide-react';
|
|
7
7
|
import { useMemo, useState } from 'react';
|
|
8
8
|
|
|
9
9
|
import type { PickerOption } from './course-edit-types';
|
|
@@ -28,6 +28,7 @@ type CourseMultiEntityPickerProps = {
|
|
|
28
28
|
}>;
|
|
29
29
|
mapSearchToCreateValues?: (search: string) => Record<string, string>;
|
|
30
30
|
onChange: (nextValue: string[]) => void;
|
|
31
|
+
onEditSelected?: (option: PickerOption) => void;
|
|
31
32
|
emptyHint?: string;
|
|
32
33
|
renderOptionMeta?: boolean;
|
|
33
34
|
variant?: 'default' | 'instructor';
|
|
@@ -57,6 +58,7 @@ export function CourseMultiEntityPicker({
|
|
|
57
58
|
createFields,
|
|
58
59
|
mapSearchToCreateValues,
|
|
59
60
|
onChange,
|
|
61
|
+
onEditSelected,
|
|
60
62
|
emptyHint,
|
|
61
63
|
renderOptionMeta = false,
|
|
62
64
|
variant = 'default',
|
|
@@ -192,18 +194,33 @@ export function CourseMultiEntityPicker({
|
|
|
192
194
|
</div>
|
|
193
195
|
</div>
|
|
194
196
|
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
197
|
+
<div className="flex items-center gap-1">
|
|
198
|
+
{onEditSelected ? (
|
|
199
|
+
<Button
|
|
200
|
+
type="button"
|
|
201
|
+
variant="ghost"
|
|
202
|
+
size="icon"
|
|
203
|
+
className="h-8 w-8 rounded-lg text-muted-foreground hover:text-foreground"
|
|
204
|
+
onClick={() => onEditSelected(option)}
|
|
205
|
+
aria-label={`Editar ${option.label}`}
|
|
206
|
+
>
|
|
207
|
+
<Pencil className="h-4 w-4" />
|
|
208
|
+
</Button>
|
|
209
|
+
) : null}
|
|
210
|
+
|
|
211
|
+
<Button
|
|
212
|
+
type="button"
|
|
213
|
+
variant="ghost"
|
|
214
|
+
size="icon"
|
|
215
|
+
className="h-8 w-8 rounded-lg text-muted-foreground hover:text-foreground"
|
|
216
|
+
onClick={() =>
|
|
217
|
+
onChange(value.filter((item) => item !== option.value))
|
|
218
|
+
}
|
|
219
|
+
aria-label={`Remover ${option.label}`}
|
|
220
|
+
>
|
|
221
|
+
<X className="h-4 w-4" />
|
|
222
|
+
</Button>
|
|
223
|
+
</div>
|
|
207
224
|
</div>
|
|
208
225
|
) : (
|
|
209
226
|
<Badge
|
|
@@ -211,7 +228,17 @@ export function CourseMultiEntityPicker({
|
|
|
211
228
|
variant="secondary"
|
|
212
229
|
className="flex items-center gap-1.5 rounded-full border border-border/60 bg-background px-3 py-1.5 text-xs font-medium text-foreground"
|
|
213
230
|
>
|
|
214
|
-
<span className="max-w-
|
|
231
|
+
<span className="max-w-45 truncate">{option.label}</span>
|
|
232
|
+
{onEditSelected ? (
|
|
233
|
+
<button
|
|
234
|
+
type="button"
|
|
235
|
+
className="cursor-pointer text-muted-foreground transition-colors hover:text-foreground"
|
|
236
|
+
onClick={() => onEditSelected(option)}
|
|
237
|
+
aria-label={`Editar ${option.label}`}
|
|
238
|
+
>
|
|
239
|
+
<Pencil className="h-3.5 w-3.5" />
|
|
240
|
+
</button>
|
|
241
|
+
) : null}
|
|
215
242
|
<button
|
|
216
243
|
type="button"
|
|
217
244
|
className="cursor-pointer text-muted-foreground transition-colors hover:text-foreground"
|