@hed-hog/lms 0.0.365 → 0.0.370
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/certificate/certificate.controller.d.ts +1 -1
- package/dist/certificate/certificate.controller.d.ts.map +1 -1
- package/dist/certificate/certificate.controller.js +4 -2
- package/dist/certificate/certificate.controller.js.map +1 -1
- package/dist/certificate/certificate.service.d.ts +50 -0
- package/dist/certificate/certificate.service.d.ts.map +1 -1
- package/dist/certificate/certificate.service.js +73 -0
- package/dist/certificate/certificate.service.js.map +1 -1
- package/dist/class-group/class-group.controller.d.ts +1 -0
- package/dist/class-group/class-group.controller.d.ts.map +1 -1
- package/dist/class-group/class-group.service.d.ts +1 -0
- package/dist/class-group/class-group.service.d.ts.map +1 -1
- package/dist/course/course-ai-usage.service.d.ts +58 -0
- package/dist/course/course-ai-usage.service.d.ts.map +1 -0
- package/dist/course/course-ai-usage.service.js +176 -0
- package/dist/course/course-ai-usage.service.js.map +1 -0
- package/dist/course/course-audio-transcription.service.d.ts +65 -1
- package/dist/course/course-audio-transcription.service.d.ts.map +1 -1
- package/dist/course/course-audio-transcription.service.js +381 -29
- package/dist/course/course-audio-transcription.service.js.map +1 -1
- package/dist/course/course-export-scorm12.service.d.ts +3 -0
- package/dist/course/course-export-scorm12.service.d.ts.map +1 -1
- package/dist/course/course-export-scorm12.service.js +141 -6
- package/dist/course/course-export-scorm12.service.js.map +1 -1
- package/dist/course/course-export.service.d.ts.map +1 -1
- package/dist/course/course-export.service.js +2 -1
- package/dist/course/course-export.service.js.map +1 -1
- package/dist/course/course-lesson.controller.d.ts +25 -3
- package/dist/course/course-lesson.controller.d.ts.map +1 -1
- package/dist/course/course-lesson.controller.js +71 -8
- package/dist/course/course-lesson.controller.js.map +1 -1
- package/dist/course/course-structure.controller.d.ts +30 -7
- package/dist/course/course-structure.controller.d.ts.map +1 -1
- package/dist/course/course-structure.controller.js +37 -4
- package/dist/course/course-structure.controller.js.map +1 -1
- package/dist/course/course-structure.service.d.ts +37 -5
- package/dist/course/course-structure.service.d.ts.map +1 -1
- package/dist/course/course-structure.service.js +165 -20
- package/dist/course/course-structure.service.js.map +1 -1
- package/dist/course/course-transcription-translation.service.d.ts +31 -0
- package/dist/course/course-transcription-translation.service.d.ts.map +1 -0
- package/dist/course/course-transcription-translation.service.js +227 -0
- package/dist/course/course-transcription-translation.service.js.map +1 -0
- package/dist/course/course-video-agent-pipeline.service.d.ts +70 -0
- package/dist/course/course-video-agent-pipeline.service.d.ts.map +1 -0
- package/dist/course/course-video-agent-pipeline.service.js +398 -0
- package/dist/course/course-video-agent-pipeline.service.js.map +1 -0
- package/dist/course/course-video-hls.service.d.ts +14 -0
- package/dist/course/course-video-hls.service.d.ts.map +1 -1
- package/dist/course/course-video-hls.service.js +25 -8
- package/dist/course/course-video-hls.service.js.map +1 -1
- package/dist/course/course.controller.d.ts +2 -0
- package/dist/course/course.controller.d.ts.map +1 -1
- package/dist/course/course.module.d.ts.map +1 -1
- package/dist/course/course.module.js +9 -0
- package/dist/course/course.module.js.map +1 -1
- package/dist/course/course.service.d.ts +2 -0
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +36 -2
- package/dist/course/course.service.js.map +1 -1
- package/dist/course/dto/create-course-bulk-job.dto.d.ts +2 -1
- package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-bulk-job.dto.js +6 -1
- package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -1
- package/dist/course/dto/create-course-export.dto.d.ts +1 -0
- package/dist/course/dto/create-course-export.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-export.dto.js +6 -0
- package/dist/course/dto/create-course-export.dto.js.map +1 -1
- package/dist/course/ffmpeg.util.d.ts +10 -0
- package/dist/course/ffmpeg.util.d.ts.map +1 -0
- package/dist/course/ffmpeg.util.js +79 -0
- package/dist/course/ffmpeg.util.js.map +1 -0
- package/dist/course/lms-bulk-upload-automation.service.d.ts +3 -1
- package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload-automation.service.js +33 -16
- package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
- package/dist/course/lms-bulk-upload.controller.d.ts +3 -0
- package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.d.ts +3 -0
- package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.js +48 -29
- package/dist/course/lms-bulk-upload.service.js.map +1 -1
- package/dist/course/subtitle.util.d.ts +46 -0
- package/dist/course/subtitle.util.d.ts.map +1 -0
- package/dist/course/subtitle.util.js +206 -0
- package/dist/course/subtitle.util.js.map +1 -0
- package/dist/enterprise/training/training-admin.controller.d.ts +2 -0
- package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
- package/dist/enterprise/training/training-admin.service.d.ts +2 -0
- package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-student.service.d.ts +27 -0
- package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-student.service.js +197 -10
- package/dist/enterprise/training/training-student.service.js.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +3 -1
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +19 -5
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-map.module.d.ts.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-map.module.js +2 -1
- package/dist/lesson-xp-map/lesson-xp-map.module.js.map +1 -1
- package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
- package/dist/lms.module.d.ts.map +1 -1
- package/dist/lms.module.js +14 -0
- package/dist/lms.module.js.map +1 -1
- package/dist/platforma/dto/heartbeat.dto.d.ts +9 -0
- package/dist/platforma/dto/heartbeat.dto.d.ts.map +1 -0
- package/dist/platforma/dto/heartbeat.dto.js +50 -0
- package/dist/platforma/dto/heartbeat.dto.js.map +1 -0
- package/dist/platforma/handlers/emit-certificate.handler.d.ts +27 -0
- package/dist/platforma/handlers/emit-certificate.handler.d.ts.map +1 -0
- package/dist/platforma/handlers/emit-certificate.handler.js +117 -0
- package/dist/platforma/handlers/emit-certificate.handler.js.map +1 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts +31 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts.map +1 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.js +281 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.js.map +1 -0
- package/dist/platforma/platforma-heartbeat.service.d.ts +10 -0
- package/dist/platforma/platforma-heartbeat.service.d.ts.map +1 -0
- package/dist/platforma/platforma-heartbeat.service.js +50 -0
- package/dist/platforma/platforma-heartbeat.service.js.map +1 -0
- package/dist/platforma/platforma-performance.service.d.ts +121 -0
- package/dist/platforma/platforma-performance.service.d.ts.map +1 -0
- package/dist/platforma/platforma-performance.service.js +500 -0
- package/dist/platforma/platforma-performance.service.js.map +1 -0
- package/dist/platforma/platforma-search.service.d.ts +21 -0
- package/dist/platforma/platforma-search.service.d.ts.map +1 -0
- package/dist/platforma/platforma-search.service.js +64 -0
- package/dist/platforma/platforma-search.service.js.map +1 -0
- package/dist/platforma/platforma-video.service.d.ts +8 -0
- package/dist/platforma/platforma-video.service.d.ts.map +1 -1
- package/dist/platforma/platforma-video.service.js +45 -2
- package/dist/platforma/platforma-video.service.js.map +1 -1
- package/dist/platforma/platforma.controller.d.ts +213 -1
- package/dist/platforma/platforma.controller.d.ts.map +1 -1
- package/dist/platforma/platforma.controller.js +159 -2
- package/dist/platforma/platforma.controller.js.map +1 -1
- package/dist/realtime/lms-realtime.controller.d.ts +2 -0
- package/dist/realtime/lms-realtime.controller.d.ts.map +1 -1
- package/dist/realtime/lms-realtime.controller.js +31 -0
- package/dist/realtime/lms-realtime.controller.js.map +1 -1
- package/dist/realtime/lms-realtime.service.d.ts +1 -1
- package/dist/realtime/lms-realtime.service.d.ts.map +1 -1
- package/dist/realtime/lms-realtime.service.js.map +1 -1
- package/dist/training/dto/create-training.dto.d.ts +9 -0
- package/dist/training/dto/create-training.dto.d.ts.map +1 -1
- package/dist/training/dto/create-training.dto.js +45 -1
- package/dist/training/dto/create-training.dto.js.map +1 -1
- package/dist/training/training.controller.d.ts +144 -0
- package/dist/training/training.controller.d.ts.map +1 -1
- package/dist/training/training.service.d.ts +149 -0
- package/dist/training/training.service.d.ts.map +1 -1
- package/dist/training/training.service.js +332 -167
- package/dist/training/training.service.js.map +1 -1
- package/hedhog/data/image_type.yaml +10 -0
- package/hedhog/data/route.yaml +251 -0
- package/hedhog/data/setting_group.yaml +97 -0
- package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +139 -27
- package/hedhog/frontend/app/certificates/models/page.tsx.ejs +182 -29
- package/hedhog/frontend/app/classes/_components/classes-calendar-view.tsx.ejs +277 -0
- package/hedhog/frontend/app/classes/page.tsx.ejs +127 -20
- package/hedhog/frontend/app/courses/[id]/_components/CourseFlagsCard.tsx.ejs +69 -57
- package/hedhog/frontend/app/courses/[id]/_components/CourseIssuedCertificatesCard.tsx.ejs +168 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-ai-costs-tab.tsx.ejs +191 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +81 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +12 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +141 -30
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +13 -13
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +69 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +11 -23
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +267 -19
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +114 -86
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +239 -31
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +344 -59
- package/hedhog/frontend/app/courses/[id]/structure/_components/lesson-video-preview.tsx.ejs +200 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +1 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +3 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +1 -8
- package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +19 -7
- package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-ai-costs.ts.ejs +40 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +2 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +25 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +148 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-transcription-segments.ts.ejs +157 -8
- package/hedhog/frontend/app/courses/_components/CourseRowActions.tsx.ejs +1 -22
- package/hedhog/frontend/app/courses/page.tsx.ejs +66 -13
- package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +6 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-classes-calendar-tab.tsx.ejs +264 -0
- package/hedhog/frontend/app/enterprise/page.tsx.ejs +104 -47
- package/hedhog/frontend/app/exams/page.tsx.ejs +38 -4
- package/hedhog/frontend/app/instructors/page.tsx.ejs +87 -46
- package/hedhog/frontend/app/paths/page.tsx.ejs +650 -168
- package/hedhog/frontend/app/training/page.tsx.ejs +38 -4
- package/hedhog/frontend/messages/en.json +41 -12
- package/hedhog/frontend/messages/pt.json +44 -13
- package/hedhog/query/triggers.sql +33 -0
- package/hedhog/table/course_ai_usage.yaml +46 -0
- package/hedhog/table/course_enrollment.yaml +3 -0
- package/hedhog/table/course_lesson.yaml +3 -0
- package/hedhog/table/course_lesson_answer.yaml +37 -0
- package/hedhog/table/course_lesson_transcription_segment.yaml +8 -0
- package/hedhog/table/learning_path.yaml +6 -0
- package/hedhog/table/learning_path_module.yaml +22 -0
- package/hedhog/table/learning_path_step.yaml +9 -6
- package/hedhog/table/lesson_view_event.yaml +66 -0
- package/package.json +8 -7
- package/src/certificate/certificate.controller.ts +2 -0
- package/src/certificate/certificate.service.ts +99 -0
- package/src/course/course-ai-usage.service.ts +221 -0
- package/src/course/course-audio-transcription.service.ts +471 -43
- package/src/course/course-export-scorm12.service.ts +149 -5
- package/src/course/course-export.service.ts +1 -0
- package/src/course/course-lesson.controller.ts +59 -6
- package/src/course/course-structure.controller.ts +19 -1
- package/src/course/course-structure.service.ts +184 -10
- package/src/course/course-transcription-translation.service.ts +293 -0
- package/src/course/course-video-agent-pipeline.service.ts +471 -0
- package/src/course/course-video-hls.service.ts +30 -10
- package/src/course/course.module.ts +9 -0
- package/src/course/course.service.ts +46 -1
- package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
- package/src/course/dto/create-course-export.dto.ts +6 -0
- package/src/course/ffmpeg.util.ts +65 -0
- package/src/course/lms-bulk-upload-automation.service.ts +33 -8
- package/src/course/lms-bulk-upload.service.ts +20 -1
- package/src/course/subtitle.util.ts +220 -0
- package/src/enterprise/training/training-student.service.ts +224 -4
- package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +14 -0
- package/src/lesson-xp-map/lesson-xp-map.module.ts +2 -1
- package/src/lms.module.ts +14 -0
- package/src/platforma/dto/heartbeat.dto.ts +30 -0
- package/src/platforma/handlers/emit-certificate.handler.ts +117 -0
- package/src/platforma/handlers/lesson-heartbeat.handler.ts +343 -0
- package/src/platforma/platforma-heartbeat.service.ts +33 -0
- package/src/platforma/platforma-performance.service.ts +606 -0
- package/src/platforma/platforma-search.service.ts +48 -0
- package/src/platforma/platforma-video.service.ts +59 -3
- package/src/platforma/platforma.controller.ts +130 -0
- package/src/realtime/lms-realtime.controller.ts +27 -1
- package/src/realtime/lms-realtime.service.ts +2 -1
- package/src/training/dto/create-training.dto.ts +36 -0
- package/src/training/training.service.ts +360 -163
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Badge } from '@/components/ui/badge';
|
|
4
|
+
import {
|
|
5
|
+
addDays,
|
|
6
|
+
addMonths,
|
|
7
|
+
eachDayOfInterval,
|
|
8
|
+
format,
|
|
9
|
+
isAfter,
|
|
10
|
+
isBefore,
|
|
11
|
+
isSameDay,
|
|
12
|
+
isSameMonth,
|
|
13
|
+
isToday,
|
|
14
|
+
parseISO,
|
|
15
|
+
startOfMonth,
|
|
16
|
+
startOfWeek,
|
|
17
|
+
subMonths,
|
|
18
|
+
} from 'date-fns';
|
|
19
|
+
import { ptBR } from 'date-fns/locale/pt-BR';
|
|
20
|
+
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
21
|
+
import { useLocale } from 'next-intl';
|
|
22
|
+
import { useState } from 'react';
|
|
23
|
+
import { useRouter } from 'next/navigation';
|
|
24
|
+
|
|
25
|
+
interface Turma {
|
|
26
|
+
id: number;
|
|
27
|
+
codigo: string;
|
|
28
|
+
curso: string;
|
|
29
|
+
dataInicio: string;
|
|
30
|
+
dataFim: string;
|
|
31
|
+
status: 'aberta' | 'em_andamento' | 'concluida' | 'cancelada';
|
|
32
|
+
professor: string;
|
|
33
|
+
vagas: number;
|
|
34
|
+
matriculados: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const STATUS_COLORS: Record<string, string> = {
|
|
38
|
+
aberta:
|
|
39
|
+
'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300',
|
|
40
|
+
em_andamento:
|
|
41
|
+
'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300',
|
|
42
|
+
concluida:
|
|
43
|
+
'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300',
|
|
44
|
+
cancelada: 'bg-muted text-muted-foreground line-through',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const STATUS_LABELS: Record<string, string> = {
|
|
48
|
+
aberta: 'Aberta',
|
|
49
|
+
em_andamento: 'Em andamento',
|
|
50
|
+
concluida: 'Concluída',
|
|
51
|
+
cancelada: 'Cancelada',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const DAY_HEADERS_PT = ['Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb', 'Dom'];
|
|
55
|
+
const DAY_HEADERS_EN = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
|
56
|
+
|
|
57
|
+
function parseDate(value: string | null | undefined): Date | null {
|
|
58
|
+
if (!value) return null;
|
|
59
|
+
try {
|
|
60
|
+
const d = parseISO(String(value).slice(0, 10));
|
|
61
|
+
return isNaN(d.getTime()) ? null : d;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isTurmaActiveOnDay(turma: Turma, day: Date): boolean {
|
|
68
|
+
const start = parseDate(turma.dataInicio);
|
|
69
|
+
const end = parseDate(turma.dataFim);
|
|
70
|
+
if (!start) return false;
|
|
71
|
+
const dayStart = new Date(day.getFullYear(), day.getMonth(), day.getDate());
|
|
72
|
+
const startDay = new Date(
|
|
73
|
+
start.getFullYear(),
|
|
74
|
+
start.getMonth(),
|
|
75
|
+
start.getDate()
|
|
76
|
+
);
|
|
77
|
+
const endDay = end
|
|
78
|
+
? new Date(end.getFullYear(), end.getMonth(), end.getDate())
|
|
79
|
+
: startDay;
|
|
80
|
+
return (
|
|
81
|
+
(isSameDay(dayStart, startDay) || isAfter(dayStart, startDay)) &&
|
|
82
|
+
(isSameDay(dayStart, endDay) || isBefore(dayStart, endDay))
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function ClassesCalendarView({ turmas }: { turmas: Turma[] }) {
|
|
87
|
+
const router = useRouter();
|
|
88
|
+
const locale = useLocale();
|
|
89
|
+
const dateLocale = locale.startsWith('pt') ? ptBR : undefined;
|
|
90
|
+
const dayHeaders = locale.startsWith('pt') ? DAY_HEADERS_PT : DAY_HEADERS_EN;
|
|
91
|
+
|
|
92
|
+
const [currentDate, setCurrentDate] = useState(() => new Date());
|
|
93
|
+
const [selectedDay, setSelectedDay] = useState<Date | null>(null);
|
|
94
|
+
|
|
95
|
+
const monthStart = startOfMonth(currentDate);
|
|
96
|
+
const gridStart = startOfWeek(monthStart, { weekStartsOn: 1 });
|
|
97
|
+
const days = eachDayOfInterval({
|
|
98
|
+
start: gridStart,
|
|
99
|
+
end: addDays(gridStart, 41),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const getTurmasForDay = (day: Date) =>
|
|
103
|
+
turmas.filter((t) => isTurmaActiveOnDay(t, day));
|
|
104
|
+
|
|
105
|
+
const selectedDayTurmas = selectedDay ? getTurmasForDay(selectedDay) : [];
|
|
106
|
+
|
|
107
|
+
const monthLabel = format(
|
|
108
|
+
currentDate,
|
|
109
|
+
locale.startsWith('pt') ? "MMMM 'de' yyyy" : 'MMMM yyyy',
|
|
110
|
+
{ locale: dateLocale }
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div className="space-y-4 pb-6">
|
|
115
|
+
{/* Month navigation */}
|
|
116
|
+
<div className="flex items-center justify-between rounded-xl border bg-muted/20 px-3 py-2">
|
|
117
|
+
<button
|
|
118
|
+
type="button"
|
|
119
|
+
onClick={() => {
|
|
120
|
+
setCurrentDate((d) => subMonths(d, 1));
|
|
121
|
+
setSelectedDay(null);
|
|
122
|
+
}}
|
|
123
|
+
className="flex size-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
|
124
|
+
aria-label="Mês anterior"
|
|
125
|
+
>
|
|
126
|
+
<ChevronLeft className="size-4" />
|
|
127
|
+
</button>
|
|
128
|
+
<span className="text-sm font-semibold capitalize">{monthLabel}</span>
|
|
129
|
+
<button
|
|
130
|
+
type="button"
|
|
131
|
+
onClick={() => {
|
|
132
|
+
setCurrentDate((d) => addMonths(d, 1));
|
|
133
|
+
setSelectedDay(null);
|
|
134
|
+
}}
|
|
135
|
+
className="flex size-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
|
136
|
+
aria-label="Próximo mês"
|
|
137
|
+
>
|
|
138
|
+
<ChevronRight className="size-4" />
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
{/* Day headers */}
|
|
143
|
+
<div className="grid grid-cols-7 text-center">
|
|
144
|
+
{dayHeaders.map((h) => (
|
|
145
|
+
<div
|
|
146
|
+
key={h}
|
|
147
|
+
className="pb-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground"
|
|
148
|
+
>
|
|
149
|
+
{h}
|
|
150
|
+
</div>
|
|
151
|
+
))}
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
{/* Calendar grid */}
|
|
155
|
+
<div className="grid grid-cols-7 gap-px overflow-hidden rounded-lg border bg-border/40">
|
|
156
|
+
{days.map((day) => {
|
|
157
|
+
const dayTurmas = getTurmasForDay(day);
|
|
158
|
+
const isCurrentMonth = isSameMonth(day, currentDate);
|
|
159
|
+
const isSelected = selectedDay ? isSameDay(day, selectedDay) : false;
|
|
160
|
+
const todayDay = isToday(day);
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<button
|
|
164
|
+
key={day.toISOString()}
|
|
165
|
+
type="button"
|
|
166
|
+
onClick={() => setSelectedDay(isSelected ? null : day)}
|
|
167
|
+
className={[
|
|
168
|
+
'flex min-h-16 flex-col gap-0.5 bg-background p-1 text-left transition-colors hover:bg-muted/40',
|
|
169
|
+
!isCurrentMonth && 'opacity-40',
|
|
170
|
+
isSelected && 'ring-2 ring-inset ring-primary',
|
|
171
|
+
]
|
|
172
|
+
.filter(Boolean)
|
|
173
|
+
.join(' ')}
|
|
174
|
+
>
|
|
175
|
+
<span
|
|
176
|
+
className={[
|
|
177
|
+
'flex size-5 items-center justify-center self-end rounded-full text-[11px] font-medium',
|
|
178
|
+
todayDay
|
|
179
|
+
? 'bg-primary text-primary-foreground'
|
|
180
|
+
: 'text-foreground',
|
|
181
|
+
].join(' ')}
|
|
182
|
+
>
|
|
183
|
+
{format(day, 'd')}
|
|
184
|
+
</span>
|
|
185
|
+
<div className="flex min-h-0 flex-col gap-0.5 overflow-hidden">
|
|
186
|
+
{dayTurmas.slice(0, 3).map((turma) => (
|
|
187
|
+
<span
|
|
188
|
+
key={turma.id}
|
|
189
|
+
className={[
|
|
190
|
+
'truncate rounded px-1 text-[9px] font-medium leading-4',
|
|
191
|
+
STATUS_COLORS[turma.status] ?? STATUS_COLORS.aberta,
|
|
192
|
+
].join(' ')}
|
|
193
|
+
>
|
|
194
|
+
{turma.curso}
|
|
195
|
+
</span>
|
|
196
|
+
))}
|
|
197
|
+
{dayTurmas.length > 3 && (
|
|
198
|
+
<span className="px-1 text-[9px] text-muted-foreground">
|
|
199
|
+
+{dayTurmas.length - 3}
|
|
200
|
+
</span>
|
|
201
|
+
)}
|
|
202
|
+
</div>
|
|
203
|
+
</button>
|
|
204
|
+
);
|
|
205
|
+
})}
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
{/* Selected day detail */}
|
|
209
|
+
{selectedDay && (
|
|
210
|
+
<div className="space-y-2 rounded-xl border bg-muted/20 p-3">
|
|
211
|
+
<p className="text-xs font-semibold text-muted-foreground">
|
|
212
|
+
{format(
|
|
213
|
+
selectedDay,
|
|
214
|
+
locale.startsWith('pt') ? "d 'de' MMMM" : 'MMMM d',
|
|
215
|
+
{ locale: dateLocale }
|
|
216
|
+
)}
|
|
217
|
+
</p>
|
|
218
|
+
{selectedDayTurmas.length === 0 ? (
|
|
219
|
+
<p className="text-sm text-muted-foreground">
|
|
220
|
+
Nenhuma turma neste dia.
|
|
221
|
+
</p>
|
|
222
|
+
) : (
|
|
223
|
+
<div className="space-y-1.5">
|
|
224
|
+
{selectedDayTurmas.map((turma) => (
|
|
225
|
+
<button
|
|
226
|
+
key={turma.id}
|
|
227
|
+
type="button"
|
|
228
|
+
onClick={() => router.push(`/lms/classes/${turma.id}`)}
|
|
229
|
+
className="flex w-full items-center gap-3 rounded-lg border bg-background px-3 py-2 text-left transition-colors hover:bg-muted/50"
|
|
230
|
+
>
|
|
231
|
+
<div className="min-w-0 flex-1">
|
|
232
|
+
<p className="truncate text-sm font-medium">{turma.curso}</p>
|
|
233
|
+
<p className="truncate text-xs text-muted-foreground">
|
|
234
|
+
{[turma.codigo, turma.professor !== '-' ? turma.professor : null]
|
|
235
|
+
.filter(Boolean)
|
|
236
|
+
.join(' • ')}
|
|
237
|
+
</p>
|
|
238
|
+
</div>
|
|
239
|
+
<div className="flex shrink-0 flex-col items-end gap-1">
|
|
240
|
+
<Badge
|
|
241
|
+
variant="outline"
|
|
242
|
+
className={[
|
|
243
|
+
'px-1.5 py-0 text-[10px]',
|
|
244
|
+
STATUS_COLORS[turma.status],
|
|
245
|
+
].join(' ')}
|
|
246
|
+
>
|
|
247
|
+
{STATUS_LABELS[turma.status] ?? turma.status}
|
|
248
|
+
</Badge>
|
|
249
|
+
<span className="text-[10px] text-muted-foreground">
|
|
250
|
+
{turma.matriculados}/{turma.vagas}
|
|
251
|
+
</span>
|
|
252
|
+
</div>
|
|
253
|
+
</button>
|
|
254
|
+
))}
|
|
255
|
+
</div>
|
|
256
|
+
)}
|
|
257
|
+
</div>
|
|
258
|
+
)}
|
|
259
|
+
|
|
260
|
+
{/* Legend */}
|
|
261
|
+
<div className="flex flex-wrap gap-3">
|
|
262
|
+
{Object.entries(STATUS_LABELS).map(([status, label]) => (
|
|
263
|
+
<div key={status} className="flex items-center gap-1.5">
|
|
264
|
+
<span
|
|
265
|
+
className={[
|
|
266
|
+
'rounded px-1.5 py-0.5 text-[10px] font-medium',
|
|
267
|
+
STATUS_COLORS[status],
|
|
268
|
+
].join(' ')}
|
|
269
|
+
>
|
|
270
|
+
{label}
|
|
271
|
+
</span>
|
|
272
|
+
</div>
|
|
273
|
+
))}
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
);
|
|
277
|
+
}
|
|
@@ -7,8 +7,17 @@ import {
|
|
|
7
7
|
PageHeader,
|
|
8
8
|
PaginationFooter,
|
|
9
9
|
SearchBar,
|
|
10
|
-
ViewModeToggle,
|
|
11
10
|
} from '@/components/entity-list';
|
|
11
|
+
import {
|
|
12
|
+
Tooltip,
|
|
13
|
+
TooltipContent,
|
|
14
|
+
TooltipProvider,
|
|
15
|
+
TooltipTrigger,
|
|
16
|
+
} from '@/components/ui/tooltip';
|
|
17
|
+
import {
|
|
18
|
+
ToggleGroup,
|
|
19
|
+
ToggleGroupItem,
|
|
20
|
+
} from '@/components/ui/toggle-group';
|
|
12
21
|
import { Badge } from '@/components/ui/badge';
|
|
13
22
|
import { Button } from '@/components/ui/button';
|
|
14
23
|
import { Card, CardContent } from '@/components/ui/card';
|
|
@@ -39,10 +48,13 @@ import { motion } from 'framer-motion';
|
|
|
39
48
|
import {
|
|
40
49
|
AlertTriangle,
|
|
41
50
|
BarChart3,
|
|
51
|
+
CalendarDays,
|
|
42
52
|
CalendarIcon,
|
|
43
53
|
Clock,
|
|
44
54
|
Eye,
|
|
55
|
+
LayoutGrid,
|
|
45
56
|
Laptop,
|
|
57
|
+
List,
|
|
46
58
|
Loader2,
|
|
47
59
|
MapPin,
|
|
48
60
|
Monitor,
|
|
@@ -59,6 +71,7 @@ import { useRouter } from 'next/navigation';
|
|
|
59
71
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
60
72
|
import { toast } from 'sonner';
|
|
61
73
|
import { ClassFormSheet } from '../_components/class-form-sheet';
|
|
74
|
+
import { ClassesCalendarView } from './_components/classes-calendar-view';
|
|
62
75
|
|
|
63
76
|
// ── Types ─────────────────────────────────────────────────────────────────────
|
|
64
77
|
|
|
@@ -229,7 +242,7 @@ function mapApiClass(item: ApiClass): Turma {
|
|
|
229
242
|
};
|
|
230
243
|
}
|
|
231
244
|
|
|
232
|
-
type ViewMode = 'cards' | 'list';
|
|
245
|
+
type ViewMode = 'cards' | 'list' | 'calendar';
|
|
233
246
|
|
|
234
247
|
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
235
248
|
|
|
@@ -269,7 +282,7 @@ const TIPO_ICON: Record<string, LucideIcon> = {
|
|
|
269
282
|
hibrida: Laptop,
|
|
270
283
|
};
|
|
271
284
|
|
|
272
|
-
const
|
|
285
|
+
const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
|
|
273
286
|
|
|
274
287
|
// ── Animations ────────────────────────────────────────────────────────────────
|
|
275
288
|
|
|
@@ -306,15 +319,49 @@ export default function TurmasPage() {
|
|
|
306
319
|
const [viewMode, setViewMode] = usePersistedViewMode<ViewMode>({
|
|
307
320
|
storageKey: 'lms:classes:view-mode',
|
|
308
321
|
defaultValue: 'cards',
|
|
309
|
-
allowedValues: ['cards', 'list'],
|
|
322
|
+
allowedValues: ['cards', 'list', 'calendar'],
|
|
310
323
|
});
|
|
311
324
|
|
|
312
325
|
// Pagination
|
|
313
326
|
const [currentPage, setCurrentPage] = useState(1);
|
|
327
|
+
|
|
328
|
+
const { data: generalSettings } = useQuery<{
|
|
329
|
+
data: Array<{ slug: string; value: string }>;
|
|
330
|
+
}>({
|
|
331
|
+
queryKey: ['setting-group-general'],
|
|
332
|
+
queryFn: async () => {
|
|
333
|
+
const response = await request<{
|
|
334
|
+
data: Array<{ slug: string; value: string }>;
|
|
335
|
+
}>({
|
|
336
|
+
url: '/setting/group/general',
|
|
337
|
+
method: 'GET',
|
|
338
|
+
});
|
|
339
|
+
return response.data;
|
|
340
|
+
},
|
|
341
|
+
staleTime: 5 * 60 * 1000,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const pageSizeOptions = useMemo(() => {
|
|
345
|
+
const setting = generalSettings?.data?.find(
|
|
346
|
+
(s) => s.slug === 'pagination-page-sizes'
|
|
347
|
+
);
|
|
348
|
+
if (!setting?.value) return DEFAULT_PAGE_SIZES;
|
|
349
|
+
try {
|
|
350
|
+
const parsed = JSON.parse(setting.value) as string[];
|
|
351
|
+
const sizes = parsed
|
|
352
|
+
.map(Number)
|
|
353
|
+
.filter((n) => !isNaN(n) && n > 0)
|
|
354
|
+
.sort((a, b) => a - b);
|
|
355
|
+
return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
|
|
356
|
+
} catch {
|
|
357
|
+
return DEFAULT_PAGE_SIZES;
|
|
358
|
+
}
|
|
359
|
+
}, [generalSettings]);
|
|
360
|
+
|
|
314
361
|
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
315
362
|
storageKey: 'pagination:global:pageSize',
|
|
316
363
|
defaultValue: 12,
|
|
317
|
-
allowedValues:
|
|
364
|
+
allowedValues: pageSizeOptions,
|
|
318
365
|
});
|
|
319
366
|
|
|
320
367
|
const { data: coursesResponse } = useQuery<ApiCourseList>({
|
|
@@ -333,6 +380,9 @@ export default function TurmasPage() {
|
|
|
333
380
|
},
|
|
334
381
|
});
|
|
335
382
|
|
|
383
|
+
const effectivePage = viewMode === 'calendar' ? 1 : currentPage;
|
|
384
|
+
const effectivePageSize = viewMode === 'calendar' ? 500 : pageSize;
|
|
385
|
+
|
|
336
386
|
const {
|
|
337
387
|
data: classesResponse,
|
|
338
388
|
refetch: refetchClasses,
|
|
@@ -341,8 +391,8 @@ export default function TurmasPage() {
|
|
|
341
391
|
} = useQuery<ApiClassList>({
|
|
342
392
|
queryKey: [
|
|
343
393
|
'lms-classes-list',
|
|
344
|
-
|
|
345
|
-
|
|
394
|
+
effectivePage,
|
|
395
|
+
effectivePageSize,
|
|
346
396
|
buscaDebounced,
|
|
347
397
|
filtroStatusInput,
|
|
348
398
|
filtroTipoInput,
|
|
@@ -359,8 +409,8 @@ export default function TurmasPage() {
|
|
|
359
409
|
url: '/lms/classes',
|
|
360
410
|
method: 'GET',
|
|
361
411
|
params: {
|
|
362
|
-
page:
|
|
363
|
-
pageSize,
|
|
412
|
+
page: effectivePage,
|
|
413
|
+
pageSize: effectivePageSize,
|
|
364
414
|
...(buscaDebounced ? { search: buscaDebounced } : {}),
|
|
365
415
|
...(filtroStatusInput !== 'todos'
|
|
366
416
|
? { status: toApiStatus(filtroStatusInput) }
|
|
@@ -742,13 +792,62 @@ export default function TurmasPage() {
|
|
|
742
792
|
className: 'sm:w-56',
|
|
743
793
|
},
|
|
744
794
|
]}
|
|
745
|
-
|
|
746
|
-
<
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
795
|
+
actions={
|
|
796
|
+
<TooltipProvider>
|
|
797
|
+
<ToggleGroup
|
|
798
|
+
type="single"
|
|
799
|
+
value={viewMode}
|
|
800
|
+
onValueChange={(value) => {
|
|
801
|
+
if (
|
|
802
|
+
value === 'cards' ||
|
|
803
|
+
value === 'list' ||
|
|
804
|
+
value === 'calendar'
|
|
805
|
+
) {
|
|
806
|
+
setViewMode(value);
|
|
807
|
+
}
|
|
808
|
+
}}
|
|
809
|
+
variant="outline"
|
|
810
|
+
size="sm"
|
|
811
|
+
className="shrink-0"
|
|
812
|
+
>
|
|
813
|
+
<Tooltip>
|
|
814
|
+
<TooltipTrigger asChild>
|
|
815
|
+
<ToggleGroupItem
|
|
816
|
+
value="cards"
|
|
817
|
+
aria-label={t('viewMode.cards')}
|
|
818
|
+
className="cursor-pointer"
|
|
819
|
+
>
|
|
820
|
+
<LayoutGrid className="h-4 w-4" />
|
|
821
|
+
</ToggleGroupItem>
|
|
822
|
+
</TooltipTrigger>
|
|
823
|
+
<TooltipContent>{t('viewMode.cards')}</TooltipContent>
|
|
824
|
+
</Tooltip>
|
|
825
|
+
<Tooltip>
|
|
826
|
+
<TooltipTrigger asChild>
|
|
827
|
+
<ToggleGroupItem
|
|
828
|
+
value="list"
|
|
829
|
+
aria-label={t('viewMode.list')}
|
|
830
|
+
className="cursor-pointer"
|
|
831
|
+
>
|
|
832
|
+
<List className="h-4 w-4" />
|
|
833
|
+
</ToggleGroupItem>
|
|
834
|
+
</TooltipTrigger>
|
|
835
|
+
<TooltipContent>{t('viewMode.list')}</TooltipContent>
|
|
836
|
+
</Tooltip>
|
|
837
|
+
<Tooltip>
|
|
838
|
+
<TooltipTrigger asChild>
|
|
839
|
+
<ToggleGroupItem
|
|
840
|
+
value="calendar"
|
|
841
|
+
aria-label={t('viewMode.calendar')}
|
|
842
|
+
className="cursor-pointer"
|
|
843
|
+
>
|
|
844
|
+
<CalendarDays className="h-4 w-4" />
|
|
845
|
+
</ToggleGroupItem>
|
|
846
|
+
</TooltipTrigger>
|
|
847
|
+
<TooltipContent>{t('viewMode.calendar')}</TooltipContent>
|
|
848
|
+
</Tooltip>
|
|
849
|
+
</ToggleGroup>
|
|
850
|
+
</TooltipProvider>
|
|
752
851
|
}
|
|
753
852
|
/>
|
|
754
853
|
<div className="flex items-center justify-between gap-3">
|
|
@@ -774,7 +873,13 @@ export default function TurmasPage() {
|
|
|
774
873
|
|
|
775
874
|
{/* Classes list */}
|
|
776
875
|
{loading ? (
|
|
777
|
-
viewMode === '
|
|
876
|
+
viewMode === 'calendar' ? (
|
|
877
|
+
<div className="grid grid-cols-7 gap-px">
|
|
878
|
+
{Array.from({ length: 42 }).map((_, i) => (
|
|
879
|
+
<div key={i} className="h-16 animate-pulse rounded bg-muted/30" />
|
|
880
|
+
))}
|
|
881
|
+
</div>
|
|
882
|
+
) : viewMode === 'cards' ? (
|
|
778
883
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
779
884
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
780
885
|
<Card key={i} className="overflow-hidden border-border/70">
|
|
@@ -1018,7 +1123,7 @@ export default function TurmasPage() {
|
|
|
1018
1123
|
);
|
|
1019
1124
|
})}
|
|
1020
1125
|
</motion.div>
|
|
1021
|
-
) : (
|
|
1126
|
+
) : viewMode === 'list' ? (
|
|
1022
1127
|
<div className="overflow-hidden rounded-xl border border-border/70">
|
|
1023
1128
|
<Table>
|
|
1024
1129
|
<TableHeader>
|
|
@@ -1146,10 +1251,12 @@ export default function TurmasPage() {
|
|
|
1146
1251
|
</TableBody>
|
|
1147
1252
|
</Table>
|
|
1148
1253
|
</div>
|
|
1254
|
+
) : (
|
|
1255
|
+
<ClassesCalendarView turmas={visibleTurmas} />
|
|
1149
1256
|
)}
|
|
1150
1257
|
|
|
1151
1258
|
{/* Pagination footer */}
|
|
1152
|
-
{!loading && visibleTurmas.length > 0 && (
|
|
1259
|
+
{!loading && visibleTurmas.length > 0 && viewMode !== 'calendar' && (
|
|
1153
1260
|
<div className="mt-6">
|
|
1154
1261
|
<PaginationFooter
|
|
1155
1262
|
currentPage={currentPage}
|
|
@@ -1160,7 +1267,7 @@ export default function TurmasPage() {
|
|
|
1160
1267
|
setPageSize(value);
|
|
1161
1268
|
setCurrentPage(1);
|
|
1162
1269
|
}}
|
|
1163
|
-
pageSizeOptions={
|
|
1270
|
+
pageSizeOptions={pageSizeOptions}
|
|
1164
1271
|
/>
|
|
1165
1272
|
</div>
|
|
1166
1273
|
)}
|
|
@@ -17,10 +17,13 @@ import type { UseFormReturn } from 'react-hook-form';
|
|
|
17
17
|
import { CourseSectionCard } from './CourseSectionCard';
|
|
18
18
|
import type { CourseEditFormValues, TranslationFn } from './course-edit-types';
|
|
19
19
|
|
|
20
|
+
type CourseFlag = 'certificado' | 'destaque' | 'listado';
|
|
21
|
+
|
|
20
22
|
type CourseFlagsCardProps = {
|
|
21
23
|
form: UseFormReturn<CourseEditFormValues>;
|
|
22
24
|
t: TranslationFn;
|
|
23
25
|
compact?: boolean;
|
|
26
|
+
flags?: CourseFlag[];
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
function FlagRow({
|
|
@@ -53,10 +56,13 @@ function FlagRow({
|
|
|
53
56
|
);
|
|
54
57
|
}
|
|
55
58
|
|
|
59
|
+
const DEFAULT_FLAGS: CourseFlag[] = ['certificado', 'destaque', 'listado'];
|
|
60
|
+
|
|
56
61
|
export function CourseFlagsCard({
|
|
57
62
|
form,
|
|
58
63
|
t,
|
|
59
64
|
compact = false,
|
|
65
|
+
flags = DEFAULT_FLAGS,
|
|
60
66
|
}: CourseFlagsCardProps) {
|
|
61
67
|
return (
|
|
62
68
|
<CourseSectionCard
|
|
@@ -66,65 +72,71 @@ export function CourseFlagsCard({
|
|
|
66
72
|
compact={compact}
|
|
67
73
|
>
|
|
68
74
|
<div className="space-y-3">
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
{flags.includes('certificado') && (
|
|
76
|
+
<FormField
|
|
77
|
+
control={form.control}
|
|
78
|
+
name="certificado"
|
|
79
|
+
render={({ field }) => (
|
|
80
|
+
<FormItem>
|
|
81
|
+
<FormLabel className="sr-only">
|
|
82
|
+
{t('form.flags.certificate.label')}
|
|
83
|
+
</FormLabel>
|
|
84
|
+
<FormControl>
|
|
85
|
+
<FlagRow
|
|
86
|
+
title={t('form.flags.certificate.label')}
|
|
87
|
+
description={t('form.flags.certificate.description')}
|
|
88
|
+
checked={field.value}
|
|
89
|
+
onCheckedChange={field.onChange}
|
|
90
|
+
/>
|
|
91
|
+
</FormControl>
|
|
92
|
+
</FormItem>
|
|
93
|
+
)}
|
|
94
|
+
/>
|
|
95
|
+
)}
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
{flags.includes('destaque') && (
|
|
98
|
+
<FormField
|
|
99
|
+
control={form.control}
|
|
100
|
+
name="destaque"
|
|
101
|
+
render={({ field }) => (
|
|
102
|
+
<FormItem>
|
|
103
|
+
<FormLabel className="sr-only">
|
|
104
|
+
{t('form.flags.featured.label')}
|
|
105
|
+
</FormLabel>
|
|
106
|
+
<FormControl>
|
|
107
|
+
<FlagRow
|
|
108
|
+
title={t('form.flags.featured.label')}
|
|
109
|
+
description={t('form.flags.featured.description')}
|
|
110
|
+
checked={field.value}
|
|
111
|
+
onCheckedChange={field.onChange}
|
|
112
|
+
/>
|
|
113
|
+
</FormControl>
|
|
114
|
+
</FormItem>
|
|
115
|
+
)}
|
|
116
|
+
/>
|
|
117
|
+
)}
|
|
108
118
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
119
|
+
{flags.includes('listado') && (
|
|
120
|
+
<FormField
|
|
121
|
+
control={form.control}
|
|
122
|
+
name="listado"
|
|
123
|
+
render={({ field }) => (
|
|
124
|
+
<FormItem>
|
|
125
|
+
<FormLabel className="sr-only">
|
|
126
|
+
{t('form.flags.listed.label')}
|
|
127
|
+
</FormLabel>
|
|
128
|
+
<FormControl>
|
|
129
|
+
<FlagRow
|
|
130
|
+
title={t('form.flags.listed.label')}
|
|
131
|
+
description={t('form.flags.listed.description')}
|
|
132
|
+
checked={field.value}
|
|
133
|
+
onCheckedChange={field.onChange}
|
|
134
|
+
/>
|
|
135
|
+
</FormControl>
|
|
136
|
+
</FormItem>
|
|
137
|
+
)}
|
|
138
|
+
/>
|
|
139
|
+
)}
|
|
128
140
|
</div>
|
|
129
141
|
</CourseSectionCard>
|
|
130
142
|
);
|