@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
|
@@ -414,8 +414,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
414
414
|
key: 'storage',
|
|
415
415
|
label: 'Armazenamento',
|
|
416
416
|
value: formatBytes(data.storage.totalBytes),
|
|
417
|
-
toneClassName:
|
|
418
|
-
'border-cyan-500/15 bg-cyan-500/10 text-cyan-700 dark:text-cyan-300',
|
|
417
|
+
toneClassName: 'border-border/60 bg-muted/30 text-muted-foreground',
|
|
419
418
|
},
|
|
420
419
|
{
|
|
421
420
|
key: 'coverage',
|
|
@@ -424,22 +423,19 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
424
423
|
totalLessons > 0
|
|
425
424
|
? `${Math.round((videoCount / totalLessons) * 100)}% das aulas`
|
|
426
425
|
: '0% das aulas',
|
|
427
|
-
toneClassName:
|
|
428
|
-
'border-teal-500/15 bg-teal-500/10 text-teal-700 dark:text-teal-300',
|
|
426
|
+
toneClassName: 'border-border/60 bg-muted/30 text-muted-foreground',
|
|
429
427
|
},
|
|
430
428
|
{
|
|
431
429
|
key: 'images',
|
|
432
430
|
label: 'Imagens extraídas',
|
|
433
431
|
value: `${data.media.extractedImageCount}`,
|
|
434
|
-
toneClassName:
|
|
435
|
-
'border-amber-500/15 bg-amber-500/10 text-amber-700 dark:text-amber-300',
|
|
432
|
+
toneClassName: 'border-border/60 bg-muted/30 text-muted-foreground',
|
|
436
433
|
},
|
|
437
434
|
{
|
|
438
435
|
key: 'resources',
|
|
439
436
|
label: 'Arquivos de apoio',
|
|
440
437
|
value: `${data.resources.fileCount}`,
|
|
441
|
-
toneClassName:
|
|
442
|
-
'border-violet-500/15 bg-violet-500/10 text-violet-700 dark:text-violet-300',
|
|
438
|
+
toneClassName: 'border-border/60 bg-muted/30 text-muted-foreground',
|
|
443
439
|
},
|
|
444
440
|
];
|
|
445
441
|
|
|
@@ -569,7 +565,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
569
565
|
<div className="rounded-2xl border border-border/70 bg-linear-to-br from-background via-background to-muted/30 px-2.5 py-2 shadow-[0_14px_34px_-28px_rgba(15,23,42,0.45)] backdrop-blur-sm sm:px-3 sm:py-2.5">
|
|
570
566
|
<div className="flex flex-wrap items-start justify-between gap-3 border-b border-border/50 pb-2">
|
|
571
567
|
<div className="min-w-0">
|
|
572
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
568
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
573
569
|
Course overview
|
|
574
570
|
</div>
|
|
575
571
|
<div className="mt-1 text-sm font-semibold text-foreground">
|
|
@@ -609,14 +605,14 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
609
605
|
</div>
|
|
610
606
|
|
|
611
607
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
612
|
-
<CardHeader className="border-b border-border/70
|
|
608
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
613
609
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
614
610
|
<div className="flex min-w-0 items-start gap-3">
|
|
615
611
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-cyan-500/10 text-cyan-600 ring-1 ring-inset ring-cyan-500/15 dark:text-cyan-400">
|
|
616
612
|
<HardDrive className="size-4" />
|
|
617
613
|
</div>
|
|
618
614
|
<div className="min-w-0">
|
|
619
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
615
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
620
616
|
Storage footprint
|
|
621
617
|
</div>
|
|
622
618
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -628,15 +624,15 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
628
624
|
</CardDescription>
|
|
629
625
|
</div>
|
|
630
626
|
</div>
|
|
631
|
-
<div className="rounded-full border border-
|
|
627
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
632
628
|
{formatBytes(data.storage.totalBytes)}
|
|
633
629
|
</div>
|
|
634
630
|
</div>
|
|
635
631
|
</CardHeader>
|
|
636
632
|
<CardContent className="grid gap-3 px-2.5 py-2.5 sm:px-3 xl:grid-cols-[minmax(0,240px)_minmax(0,1fr)]">
|
|
637
633
|
<div className="grid gap-2">
|
|
638
|
-
<div className="rounded-2xl border border-
|
|
639
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.18em] text-
|
|
634
|
+
<div className="rounded-2xl border border-border/60 bg-muted/20 px-3 py-3 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:shadow-md">
|
|
635
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
|
640
636
|
Total armazenado
|
|
641
637
|
</div>
|
|
642
638
|
<div className="mt-2 text-2xl font-semibold tracking-tight text-foreground">
|
|
@@ -675,7 +671,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
675
671
|
return (
|
|
676
672
|
<div
|
|
677
673
|
key={category.key}
|
|
678
|
-
className="overflow-hidden rounded-2xl border border-border/60 bg-card/90 transition-all duration-200 hover:-translate-y-0.5 hover:border-
|
|
674
|
+
className="overflow-hidden rounded-2xl border border-border/60 bg-card/90 transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:bg-background/95 hover:shadow-md"
|
|
679
675
|
>
|
|
680
676
|
<div
|
|
681
677
|
className={`h-1.5 w-full bg-linear-to-r ${category.accentClassName}`}
|
|
@@ -794,14 +790,14 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
794
790
|
|
|
795
791
|
<div className="grid gap-3 xl:grid-cols-2">
|
|
796
792
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
797
|
-
<CardHeader className="border-b border-border/70
|
|
793
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
798
794
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
799
795
|
<div className="flex min-w-0 items-start gap-3">
|
|
800
796
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-sky-500/10 text-sky-600 ring-1 ring-inset ring-sky-500/15 dark:text-sky-400">
|
|
801
797
|
<Layers className="size-4" />
|
|
802
798
|
</div>
|
|
803
799
|
<div className="min-w-0">
|
|
804
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
800
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
805
801
|
Lesson mix
|
|
806
802
|
</div>
|
|
807
803
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -812,7 +808,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
812
808
|
</CardDescription>
|
|
813
809
|
</div>
|
|
814
810
|
</div>
|
|
815
|
-
<div className="rounded-full border border-
|
|
811
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
816
812
|
{totalLessons} aulas
|
|
817
813
|
</div>
|
|
818
814
|
</div>
|
|
@@ -886,7 +882,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
886
882
|
return (
|
|
887
883
|
<div
|
|
888
884
|
key={item.type}
|
|
889
|
-
className="flex items-center gap-3 rounded-xl border border-border/60 bg-muted/20 px-3 py-2.5 transition-all duration-200 hover:-translate-y-0.5 hover:border-
|
|
885
|
+
className="flex items-center gap-3 rounded-xl border border-border/60 bg-muted/20 px-3 py-2.5 transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:bg-background/95 hover:shadow-md"
|
|
890
886
|
>
|
|
891
887
|
<div
|
|
892
888
|
className="flex size-8 shrink-0 items-center justify-center rounded-lg"
|
|
@@ -926,16 +922,131 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
926
922
|
</CardContent>
|
|
927
923
|
</Card>
|
|
928
924
|
|
|
925
|
+
{/* Video pipeline */}
|
|
926
|
+
{videoCount > 0 && (
|
|
927
|
+
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
928
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
929
|
+
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
930
|
+
<div className="flex min-w-0 items-start gap-3">
|
|
931
|
+
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-violet-500/10 text-violet-600 ring-1 ring-inset ring-violet-500/15 dark:text-violet-400">
|
|
932
|
+
<Film className="size-4" />
|
|
933
|
+
</div>
|
|
934
|
+
<div className="min-w-0">
|
|
935
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
936
|
+
Video pipeline
|
|
937
|
+
</div>
|
|
938
|
+
<CardTitle className="mt-1 text-sm font-semibold">
|
|
939
|
+
{t('videoPipeline.title')}
|
|
940
|
+
</CardTitle>
|
|
941
|
+
<CardDescription className="mt-0.5">
|
|
942
|
+
{t('videoPipeline.description')}
|
|
943
|
+
</CardDescription>
|
|
944
|
+
</div>
|
|
945
|
+
</div>
|
|
946
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
947
|
+
{videoCount} vídeos
|
|
948
|
+
</div>
|
|
949
|
+
</div>
|
|
950
|
+
</CardHeader>
|
|
951
|
+
<CardContent className="flex flex-col gap-3 px-2.5 py-2.5 sm:px-3">
|
|
952
|
+
{(
|
|
953
|
+
[
|
|
954
|
+
{
|
|
955
|
+
key: 'total',
|
|
956
|
+
label: t('videoPipeline.total'),
|
|
957
|
+
value: videoCount,
|
|
958
|
+
total: videoCount,
|
|
959
|
+
color: '#8b5cf6',
|
|
960
|
+
bgColor: 'bg-violet-500/10',
|
|
961
|
+
textColor: 'text-violet-600 dark:text-violet-400',
|
|
962
|
+
icon: Clapperboard,
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
key: 'withVideo',
|
|
966
|
+
label: t('videoPipeline.withVideo'),
|
|
967
|
+
value: data.videos.withVideo,
|
|
968
|
+
total: videoCount,
|
|
969
|
+
color: '#a855f7',
|
|
970
|
+
bgColor: 'bg-purple-500/10',
|
|
971
|
+
textColor: 'text-purple-600 dark:text-purple-400',
|
|
972
|
+
icon: Film,
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
key: 'withProcessedVideo',
|
|
976
|
+
label: t('videoPipeline.withProcessedVideo'),
|
|
977
|
+
value: data.videos.withProcessedVideo,
|
|
978
|
+
total: videoCount,
|
|
979
|
+
color: '#d946ef',
|
|
980
|
+
bgColor: 'bg-fuchsia-500/10',
|
|
981
|
+
textColor: 'text-fuchsia-600 dark:text-fuchsia-400',
|
|
982
|
+
icon: Sparkles,
|
|
983
|
+
},
|
|
984
|
+
] as const
|
|
985
|
+
).map((stat) => {
|
|
986
|
+
const pct =
|
|
987
|
+
stat.total > 0
|
|
988
|
+
? Math.round((stat.value / stat.total) * 100)
|
|
989
|
+
: stat.key === 'total'
|
|
990
|
+
? 100
|
|
991
|
+
: 0;
|
|
992
|
+
const Icon = stat.icon;
|
|
993
|
+
return (
|
|
994
|
+
<div
|
|
995
|
+
key={stat.key}
|
|
996
|
+
className="flex flex-col gap-2 rounded-xl border border-transparent px-2 py-1 transition-all duration-200 hover:-translate-y-0.5 hover:border-border/60 hover:bg-background/70 hover:shadow-sm"
|
|
997
|
+
>
|
|
998
|
+
<div className="flex items-center gap-3">
|
|
999
|
+
<div
|
|
1000
|
+
className={`flex size-8 shrink-0 items-center justify-center rounded-lg ${stat.bgColor}`}
|
|
1001
|
+
>
|
|
1002
|
+
<Icon className={`size-4 ${stat.textColor}`} />
|
|
1003
|
+
</div>
|
|
1004
|
+
<div className="flex flex-1 items-center justify-between">
|
|
1005
|
+
<span className="text-sm font-medium text-foreground">
|
|
1006
|
+
{stat.label}
|
|
1007
|
+
</span>
|
|
1008
|
+
<div className="flex items-center gap-2">
|
|
1009
|
+
<span className="font-mono text-xs text-muted-foreground">
|
|
1010
|
+
{stat.value}/{stat.total}
|
|
1011
|
+
</span>
|
|
1012
|
+
<span
|
|
1013
|
+
className="rounded-full px-2 py-0.5 text-[10px] font-semibold transition-all duration-200 hover:shadow-sm"
|
|
1014
|
+
style={{
|
|
1015
|
+
backgroundColor: `${stat.color}20`,
|
|
1016
|
+
color: stat.color,
|
|
1017
|
+
}}
|
|
1018
|
+
>
|
|
1019
|
+
{pct}%
|
|
1020
|
+
</span>
|
|
1021
|
+
</div>
|
|
1022
|
+
</div>
|
|
1023
|
+
</div>
|
|
1024
|
+
<div className="ml-11 h-2 w-full overflow-hidden rounded-full bg-muted">
|
|
1025
|
+
<div
|
|
1026
|
+
className="h-full rounded-full transition-all duration-700 ease-out"
|
|
1027
|
+
style={{
|
|
1028
|
+
width: `${pct}%`,
|
|
1029
|
+
backgroundColor: stat.color,
|
|
1030
|
+
}}
|
|
1031
|
+
/>
|
|
1032
|
+
</div>
|
|
1033
|
+
</div>
|
|
1034
|
+
);
|
|
1035
|
+
})}
|
|
1036
|
+
</CardContent>
|
|
1037
|
+
</Card>
|
|
1038
|
+
)}
|
|
1039
|
+
|
|
929
1040
|
{/* Video coverage */}
|
|
930
1041
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
931
|
-
<CardHeader className="border-b border-border/70
|
|
1042
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
932
1043
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
933
1044
|
<div className="flex min-w-0 items-start gap-3">
|
|
934
1045
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-teal-500/10 text-teal-600 ring-1 ring-inset ring-teal-500/15 dark:text-teal-400">
|
|
935
1046
|
<Clapperboard className="size-4" />
|
|
936
1047
|
</div>
|
|
937
1048
|
<div className="min-w-0">
|
|
938
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
1049
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
939
1050
|
Video coverage
|
|
940
1051
|
</div>
|
|
941
1052
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -946,7 +1057,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
946
1057
|
</CardDescription>
|
|
947
1058
|
</div>
|
|
948
1059
|
</div>
|
|
949
|
-
<div className="rounded-full border border-
|
|
1060
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
950
1061
|
{videoCount} vídeos
|
|
951
1062
|
</div>
|
|
952
1063
|
</div>
|
|
@@ -1051,14 +1162,14 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
1051
1162
|
<div className="grid gap-3 xl:grid-cols-2">
|
|
1052
1163
|
{xpData.areas.length > 0 && (
|
|
1053
1164
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
1054
|
-
<CardHeader className="border-b border-border/70
|
|
1165
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
1055
1166
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
1056
1167
|
<div className="flex min-w-0 items-start gap-3">
|
|
1057
1168
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-teal-500/10 text-teal-600 ring-1 ring-inset ring-teal-500/15 dark:text-teal-400">
|
|
1058
1169
|
<Sparkles className="size-4" />
|
|
1059
1170
|
</div>
|
|
1060
1171
|
<div className="min-w-0">
|
|
1061
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
1172
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
1062
1173
|
Macro areas
|
|
1063
1174
|
</div>
|
|
1064
1175
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -1069,7 +1180,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
1069
1180
|
</CardDescription>
|
|
1070
1181
|
</div>
|
|
1071
1182
|
</div>
|
|
1072
|
-
<div className="rounded-full border border-
|
|
1183
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
1073
1184
|
{xpData.areas.length} áreas
|
|
1074
1185
|
</div>
|
|
1075
1186
|
</div>
|
|
@@ -1078,7 +1189,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
1078
1189
|
{xpData.areas.map((area, index) => (
|
|
1079
1190
|
<div
|
|
1080
1191
|
key={area.xpAreaId}
|
|
1081
|
-
className="flex items-center gap-3 rounded-xl border border-border/60 bg-muted/20 px-3 py-2.5 transition-all duration-200 hover:-translate-y-0.5 hover:border-
|
|
1192
|
+
className="flex items-center gap-3 rounded-xl border border-border/60 bg-muted/20 px-3 py-2.5 transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:bg-background/95 hover:shadow-md"
|
|
1082
1193
|
>
|
|
1083
1194
|
<div
|
|
1084
1195
|
className="flex size-6 shrink-0 items-center justify-center rounded-full text-[10px] font-bold text-white"
|
|
@@ -1109,14 +1220,14 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
1109
1220
|
|
|
1110
1221
|
{xpData.skills.length > 0 && (
|
|
1111
1222
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
1112
|
-
<CardHeader className="border-b border-border/70
|
|
1223
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
1113
1224
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
1114
1225
|
<div className="flex min-w-0 items-start gap-3">
|
|
1115
1226
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-orange-500/10 text-orange-600 ring-1 ring-inset ring-orange-500/15 dark:text-orange-400">
|
|
1116
1227
|
<Target className="size-4" />
|
|
1117
1228
|
</div>
|
|
1118
1229
|
<div className="min-w-0">
|
|
1119
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
1230
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
1120
1231
|
Skills
|
|
1121
1232
|
</div>
|
|
1122
1233
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -1127,7 +1238,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
1127
1238
|
</CardDescription>
|
|
1128
1239
|
</div>
|
|
1129
1240
|
</div>
|
|
1130
|
-
<div className="rounded-full border border-
|
|
1241
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
1131
1242
|
{xpData.skills.length} skills
|
|
1132
1243
|
</div>
|
|
1133
1244
|
</div>
|
|
@@ -1136,7 +1247,7 @@ export function CourseOverviewTab({ courseId, locale }: Props) {
|
|
|
1136
1247
|
{xpData.skills.map((skill, index) => (
|
|
1137
1248
|
<div
|
|
1138
1249
|
key={skill.xpSkillId}
|
|
1139
|
-
className="flex items-center gap-3 rounded-xl border border-border/60 bg-muted/20 px-3 py-2.5 transition-all duration-200 hover:-translate-y-0.5 hover:border-
|
|
1250
|
+
className="flex items-center gap-3 rounded-xl border border-border/60 bg-muted/20 px-3 py-2.5 transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:bg-background/95 hover:shadow-md"
|
|
1140
1251
|
>
|
|
1141
1252
|
<div
|
|
1142
1253
|
className="flex size-6 shrink-0 items-center justify-center rounded-full text-[10px] font-bold text-white"
|
package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs
CHANGED
|
@@ -262,7 +262,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
262
262
|
<div className="rounded-2xl border border-border/70 bg-linear-to-br from-background via-background to-muted/30 px-2.5 py-2 shadow-[0_14px_34px_-28px_rgba(15,23,42,0.45)] backdrop-blur-sm sm:px-3 sm:py-2.5">
|
|
263
263
|
<div className="flex flex-wrap items-start justify-between gap-3 border-b border-border/50 pb-2">
|
|
264
264
|
<div className="min-w-0">
|
|
265
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
265
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
266
266
|
Course XP overview
|
|
267
267
|
</div>
|
|
268
268
|
<div className="mt-1 text-sm font-semibold text-foreground">
|
|
@@ -301,14 +301,14 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
301
301
|
|
|
302
302
|
<div className="grid gap-3 xl:grid-cols-[minmax(0,1.06fr)_minmax(0,0.94fr)]">
|
|
303
303
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
304
|
-
<CardHeader className="border-b border-border/70
|
|
304
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
305
305
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
306
306
|
<div className="flex min-w-0 items-start gap-3">
|
|
307
307
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-teal-500/10 text-teal-600 ring-1 ring-inset ring-teal-500/15 dark:text-teal-400">
|
|
308
308
|
<ChartPie className="size-4" />
|
|
309
309
|
</div>
|
|
310
310
|
<div className="min-w-0">
|
|
311
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
311
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
312
312
|
Macro areas
|
|
313
313
|
</div>
|
|
314
314
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -319,7 +319,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
319
319
|
</CardDescription>
|
|
320
320
|
</div>
|
|
321
321
|
</div>
|
|
322
|
-
<div className="rounded-full border border-
|
|
322
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
323
323
|
{data.areas.length} áreas
|
|
324
324
|
</div>
|
|
325
325
|
</div>
|
|
@@ -388,7 +388,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
388
388
|
{areaData.map((item, index) => (
|
|
389
389
|
<div
|
|
390
390
|
key={item.xpAreaId}
|
|
391
|
-
className="rounded-2xl border border-border/60 bg-
|
|
391
|
+
className="rounded-2xl border border-border/60 bg-card/90 px-3 py-2 shadow-[0_14px_28px_-24px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
|
|
392
392
|
>
|
|
393
393
|
<div className="flex items-center gap-2">
|
|
394
394
|
<span
|
|
@@ -423,14 +423,14 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
423
423
|
</Card>
|
|
424
424
|
|
|
425
425
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
426
|
-
<CardHeader className="border-b border-border/70
|
|
426
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
427
427
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
428
428
|
<div className="flex min-w-0 items-start gap-3">
|
|
429
429
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-orange-500/10 text-orange-600 ring-1 ring-inset ring-orange-500/15 dark:text-orange-400">
|
|
430
430
|
<BarChart3 className="size-4" />
|
|
431
431
|
</div>
|
|
432
432
|
<div className="min-w-0">
|
|
433
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
433
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
434
434
|
Skill density
|
|
435
435
|
</div>
|
|
436
436
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -441,7 +441,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
441
441
|
</CardDescription>
|
|
442
442
|
</div>
|
|
443
443
|
</div>
|
|
444
|
-
<div className="rounded-full border border-
|
|
444
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
445
445
|
{data.skills.length} skills
|
|
446
446
|
</div>
|
|
447
447
|
</div>
|
|
@@ -518,7 +518,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
518
518
|
{skillData.map((item, index) => (
|
|
519
519
|
<div
|
|
520
520
|
key={item.xpSkillId}
|
|
521
|
-
className="rounded-2xl border border-border/60 bg-
|
|
521
|
+
className="rounded-2xl border border-border/60 bg-card/90 px-3 py-2 shadow-[0_14px_28px_-24px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
|
|
522
522
|
>
|
|
523
523
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
524
524
|
<div className="flex min-w-0 items-center gap-2">
|
|
@@ -556,14 +556,14 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
556
556
|
|
|
557
557
|
{learningTypeData.length > 0 && (
|
|
558
558
|
<Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
|
|
559
|
-
<CardHeader className="border-b border-border/70
|
|
559
|
+
<CardHeader className="border-b border-border/70 pt-2.5 pb-1.5!">
|
|
560
560
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
|
561
561
|
<div className="flex min-w-0 items-start gap-3">
|
|
562
562
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-violet-500/10 text-violet-600 ring-1 ring-inset ring-violet-500/15 dark:text-violet-400">
|
|
563
563
|
<Sparkles className="size-4" />
|
|
564
564
|
</div>
|
|
565
565
|
<div className="min-w-0">
|
|
566
|
-
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-
|
|
566
|
+
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
|
|
567
567
|
Learning mix
|
|
568
568
|
</div>
|
|
569
569
|
<CardTitle className="mt-1 text-sm font-semibold">
|
|
@@ -574,7 +574,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
574
574
|
</CardDescription>
|
|
575
575
|
</div>
|
|
576
576
|
</div>
|
|
577
|
-
<div className="rounded-full border border-
|
|
577
|
+
<div className="rounded-full border border-border/60 bg-muted/30 px-2.5 py-1 text-[10px] font-semibold text-muted-foreground shadow-sm">
|
|
578
578
|
{learningTypeData.length} tipos
|
|
579
579
|
</div>
|
|
580
580
|
</div>
|
|
@@ -583,7 +583,7 @@ export function CourseXpOverviewTab({ courseId, locale }: Props) {
|
|
|
583
583
|
{learningTypeData.map((item, index) => (
|
|
584
584
|
<div
|
|
585
585
|
key={item.xpLearningTypeId}
|
|
586
|
-
className="flex h-full flex-col justify-start gap-1.5 rounded-2xl border border-border/60 bg-
|
|
586
|
+
className="flex h-full flex-col justify-start gap-1.5 rounded-2xl border border-border/60 bg-card/90 px-3 py-2 shadow-[0_14px_28px_-24px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:border-border/80 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
|
|
587
587
|
>
|
|
588
588
|
<div className="flex flex-wrap items-center gap-2">
|
|
589
589
|
<div className="flex min-w-0 flex-1 items-center gap-2">
|
|
@@ -1,19 +1,60 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Badge } from '@/components/ui/badge';
|
|
4
|
+
import { Button } from '@/components/ui/button';
|
|
4
5
|
import { Separator } from '@/components/ui/separator';
|
|
5
|
-
import {
|
|
6
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
7
|
+
import { BookOpen, Globe, Hash, Loader2, Tag, Trash2 } from 'lucide-react';
|
|
8
|
+
import { toast } from 'sonner';
|
|
9
|
+
import { useDeleteCourseTranscriptionsMutation } from '../_data/use-transcription-segments';
|
|
6
10
|
import { useStructureStore } from './store';
|
|
7
11
|
|
|
8
12
|
export function DetailCourse() {
|
|
9
13
|
const course = useStructureStore((s) => s.course);
|
|
10
14
|
const sessions = useStructureStore((s) => s.sessions);
|
|
11
15
|
const lessons = useStructureStore((s) => s.lessons);
|
|
16
|
+
const showConfirm = useStructureStore((s) => s.showConfirm);
|
|
17
|
+
const courseId = useStructureStore((s) => s.courseId);
|
|
18
|
+
const queryClient = useQueryClient();
|
|
19
|
+
|
|
20
|
+
const { mutate: deleteCourseTranscriptions, isPending: isDeletingTranscriptions } =
|
|
21
|
+
useDeleteCourseTranscriptionsMutation(courseId);
|
|
12
22
|
|
|
13
23
|
const totalMinutes = lessons.reduce((sum, l) => sum + l.duration, 0);
|
|
14
24
|
const hours = Math.floor(totalMinutes / 60);
|
|
15
25
|
const minutes = totalMinutes % 60;
|
|
16
26
|
|
|
27
|
+
const handleDeleteAllTranscriptions = () => {
|
|
28
|
+
showConfirm({
|
|
29
|
+
title: 'Excluir todas as transcrições e traduções',
|
|
30
|
+
description:
|
|
31
|
+
'Isso remove permanentemente todas as transcrições e traduções de todas as aulas deste curso. Esta ação não pode ser desfeita.',
|
|
32
|
+
confirmText: 'Excluir tudo',
|
|
33
|
+
destructive: true,
|
|
34
|
+
onConfirm: () => {
|
|
35
|
+
deleteCourseTranscriptions({
|
|
36
|
+
onSuccess: (result) => {
|
|
37
|
+
toast.success(
|
|
38
|
+
`Transcrições removidas (${result.deleted} segmento(s) excluído(s)).`,
|
|
39
|
+
);
|
|
40
|
+
queryClient.invalidateQueries({
|
|
41
|
+
queryKey: ['course-content-overview', courseId],
|
|
42
|
+
});
|
|
43
|
+
queryClient.invalidateQueries({
|
|
44
|
+
queryKey: ['lesson-transcription-locales'],
|
|
45
|
+
});
|
|
46
|
+
queryClient.invalidateQueries({
|
|
47
|
+
queryKey: ['lesson-transcription-segments'],
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
onError: (err) => {
|
|
51
|
+
toast.error(err.message || 'Erro ao excluir as transcrições.');
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
17
58
|
return (
|
|
18
59
|
<div className="flex flex-col overflow-y-auto h-full">
|
|
19
60
|
{/* Header */}
|
|
@@ -78,6 +119,33 @@ export function DetailCourse() {
|
|
|
78
119
|
</div>
|
|
79
120
|
</>
|
|
80
121
|
)}
|
|
122
|
+
|
|
123
|
+
<Separator />
|
|
124
|
+
|
|
125
|
+
{/* Zona de perigo */}
|
|
126
|
+
<div className="rounded-lg border border-destructive/30 bg-destructive/5 p-3">
|
|
127
|
+
<p className="text-xs font-semibold text-destructive mb-1">
|
|
128
|
+
Zona de perigo
|
|
129
|
+
</p>
|
|
130
|
+
<p className="text-xs text-muted-foreground mb-3">
|
|
131
|
+
Remove permanentemente todas as transcrições e traduções de todas as
|
|
132
|
+
aulas deste curso.
|
|
133
|
+
</p>
|
|
134
|
+
<Button
|
|
135
|
+
variant="destructive"
|
|
136
|
+
size="sm"
|
|
137
|
+
className="w-full"
|
|
138
|
+
disabled={isDeletingTranscriptions}
|
|
139
|
+
onClick={handleDeleteAllTranscriptions}
|
|
140
|
+
>
|
|
141
|
+
{isDeletingTranscriptions ? (
|
|
142
|
+
<Loader2 className="size-4 mr-2 animate-spin" />
|
|
143
|
+
) : (
|
|
144
|
+
<Trash2 className="size-4 mr-2" />
|
|
145
|
+
)}
|
|
146
|
+
Excluir todas as transcrições e traduções
|
|
147
|
+
</Button>
|
|
148
|
+
</div>
|
|
81
149
|
</div>
|
|
82
150
|
</div>
|
|
83
151
|
);
|