@hed-hog/lms 0.0.364 → 0.0.365
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/bitcode-wallet/bitcode-wallet.service.d.ts +1 -0
- package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -1
- package/dist/bitcode-wallet/bitcode-wallet.service.js +22 -3
- package/dist/bitcode-wallet/bitcode-wallet.service.js.map +1 -1
- package/dist/course/course-export-scorm12-worker.service.d.ts +21 -0
- package/dist/course/course-export-scorm12-worker.service.d.ts.map +1 -0
- package/dist/course/course-export-scorm12-worker.service.js +109 -0
- package/dist/course/course-export-scorm12-worker.service.js.map +1 -0
- package/dist/course/course-export-scorm12.service.d.ts +42 -0
- package/dist/course/course-export-scorm12.service.d.ts.map +1 -0
- package/dist/course/course-export-scorm12.service.js +628 -0
- package/dist/course/course-export-scorm12.service.js.map +1 -0
- package/dist/course/course-export.service.d.ts +84 -0
- package/dist/course/course-export.service.d.ts.map +1 -0
- package/dist/course/course-export.service.js +237 -0
- package/dist/course/course-export.service.js.map +1 -0
- package/dist/course/course-structure.controller.d.ts +17 -9
- package/dist/course/course-structure.controller.d.ts.map +1 -1
- package/dist/course/course-structure.controller.js +17 -4
- package/dist/course/course-structure.controller.js.map +1 -1
- package/dist/course/course-structure.service.d.ts +12 -4
- package/dist/course/course-structure.service.d.ts.map +1 -1
- package/dist/course/course-structure.service.js +98 -23
- package/dist/course/course-structure.service.js.map +1 -1
- package/dist/course/course-video-hls.service.d.ts +57 -0
- package/dist/course/course-video-hls.service.d.ts.map +1 -0
- package/dist/course/course-video-hls.service.js +767 -0
- package/dist/course/course-video-hls.service.js.map +1 -0
- package/dist/course/course.controller.d.ts +45 -13
- package/dist/course/course.controller.d.ts.map +1 -1
- package/dist/course/course.controller.js +40 -26
- package/dist/course/course.controller.js.map +1 -1
- package/dist/course/course.mcp-tools.js +1 -1
- package/dist/course/course.mcp-tools.js.map +1 -1
- package/dist/course/course.module.d.ts.map +1 -1
- package/dist/course/course.module.js +11 -0
- package/dist/course/course.module.js.map +1 -1
- package/dist/course/course.service.d.ts +6 -9
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +57 -48
- package/dist/course/course.service.js.map +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.d.ts +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.d.ts.map +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.js +1 -0
- package/dist/course/dto/cleanup-course-storage.dto.js.map +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.d.ts +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.d.ts.map +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.js +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.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 +14 -0
- package/dist/course/dto/create-course-export.dto.d.ts.map +1 -0
- package/dist/course/dto/create-course-export.dto.js +71 -0
- package/dist/course/dto/create-course-export.dto.js.map +1 -0
- package/dist/course/dto/create-course-structure-lesson.dto.d.ts +2 -2
- package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-structure-lesson.dto.js +3 -2
- package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
- package/dist/course/lms-bulk-upload-automation.service.d.ts +16 -1
- package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload-automation.service.js +102 -8
- package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
- package/dist/course/lms-bulk-upload-infra.service.d.ts +1 -0
- package/dist/course/lms-bulk-upload-infra.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload-infra.service.js +32 -8
- package/dist/course/lms-bulk-upload-infra.service.js.map +1 -1
- package/dist/course/lms-bulk-upload.controller.d.ts +30 -3
- package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.controller.js +43 -2
- package/dist/course/lms-bulk-upload.controller.js.map +1 -1
- package/dist/course/lms-bulk-upload.service.d.ts +11 -0
- package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.js +59 -6
- package/dist/course/lms-bulk-upload.service.js.map +1 -1
- package/dist/course/lms-setting.controller.d.ts +2 -1
- package/dist/course/lms-setting.controller.d.ts.map +1 -1
- package/dist/course/lms-setting.controller.js +4 -2
- package/dist/course/lms-setting.controller.js.map +1 -1
- package/dist/course/scorm12-schemas.d.ts +4 -0
- package/dist/course/scorm12-schemas.d.ts.map +1 -0
- package/dist/course/scorm12-schemas.js +9 -0
- package/dist/course/scorm12-schemas.js.map +1 -0
- package/dist/enterprise/training/training-student.service.d.ts +51 -0
- package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-student.service.js +217 -4
- package/dist/enterprise/training/training-student.service.js.map +1 -1
- package/dist/evaluation/evaluation.service.d.ts +18 -0
- package/dist/evaluation/evaluation.service.d.ts.map +1 -1
- package/dist/evaluation/evaluation.service.js +125 -0
- package/dist/evaluation/evaluation.service.js.map +1 -1
- package/dist/exam/dto/create-standalone-question.dto.d.ts +12 -0
- package/dist/exam/dto/create-standalone-question.dto.d.ts.map +1 -0
- package/dist/exam/dto/create-standalone-question.dto.js +70 -0
- package/dist/exam/dto/create-standalone-question.dto.js.map +1 -0
- package/dist/exam/exam.module.d.ts.map +1 -1
- package/dist/exam/exam.module.js +2 -1
- package/dist/exam/exam.module.js.map +1 -1
- package/dist/exam/exam.service.d.ts +21 -0
- package/dist/exam/exam.service.d.ts.map +1 -1
- package/dist/exam/exam.service.js +80 -0
- package/dist/exam/exam.service.js.map +1 -1
- package/dist/exam/question.controller.d.ts +27 -0
- package/dist/exam/question.controller.d.ts.map +1 -0
- package/dist/exam/question.controller.js +53 -0
- package/dist/exam/question.controller.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +4 -0
- 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 +161 -25
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
- package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
- package/dist/lms-commerce-access.subscriber.d.ts +11 -0
- package/dist/lms-commerce-access.subscriber.d.ts.map +1 -0
- package/dist/lms-commerce-access.subscriber.js +74 -0
- package/dist/lms-commerce-access.subscriber.js.map +1 -0
- package/dist/lms.module.d.ts.map +1 -1
- package/dist/lms.module.js +6 -5
- package/dist/lms.module.js.map +1 -1
- package/dist/platforma/platforma-video.service.d.ts +39 -0
- package/dist/platforma/platforma-video.service.d.ts.map +1 -0
- package/dist/platforma/platforma-video.service.js +301 -0
- package/dist/platforma/platforma-video.service.js.map +1 -0
- package/dist/platforma/platforma.controller.d.ts +95 -1
- package/dist/platforma/platforma.controller.d.ts.map +1 -1
- package/dist/platforma/platforma.controller.js +160 -2
- package/dist/platforma/platforma.controller.js.map +1 -1
- package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts +5 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts.map +1 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.js +26 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.js.map +1 -0
- package/dist/student-xp/student-xp.controller.d.ts +15 -0
- package/dist/student-xp/student-xp.controller.d.ts.map +1 -1
- package/dist/student-xp/student-xp.controller.js +24 -0
- package/dist/student-xp/student-xp.controller.js.map +1 -1
- package/dist/student-xp/student-xp.service.d.ts +16 -0
- package/dist/student-xp/student-xp.service.d.ts.map +1 -1
- package/dist/student-xp/student-xp.service.js +51 -1
- package/dist/student-xp/student-xp.service.js.map +1 -1
- package/hedhog/data/evaluation_topic.yaml +17 -0
- package/hedhog/data/menu.yaml +0 -17
- package/hedhog/data/queue_definition.yaml +48 -0
- package/hedhog/data/route.yaml +94 -124
- package/hedhog/data/setting_group.yaml +19 -19
- package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +337 -41
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +69 -4
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +420 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +308 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +17 -15
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +51 -63
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +8 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +31 -8
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +16 -9
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +201 -401
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +378 -690
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -2
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +3 -9
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -1
- package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +6 -10
- package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +49 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -3
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +0 -1
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +106 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +28 -1
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-lms-settings-query.ts.ejs +0 -2
- package/hedhog/frontend/app/courses/page.tsx.ejs +45 -0
- package/hedhog/frontend/messages/en.json +26 -28
- package/hedhog/frontend/messages/pt.json +26 -28
- package/hedhog/table/course_export.yaml +62 -0
- package/package.json +13 -9
- package/src/bitcode-wallet/bitcode-wallet.service.ts +43 -4
- package/src/course/course-export-scorm12-worker.service.ts +124 -0
- package/src/course/course-export-scorm12.service.ts +668 -0
- package/src/course/course-export.service.ts +280 -0
- package/src/course/course-structure.controller.ts +14 -2
- package/src/course/course-structure.service.ts +100 -7
- package/src/course/course-video-hls.service.ts +946 -0
- package/src/course/course.controller.ts +33 -19
- package/src/course/course.mcp-tools.ts +1 -1
- package/src/course/course.module.ts +11 -0
- package/src/course/course.service.ts +73 -60
- package/src/course/dto/cleanup-course-storage.dto.ts +1 -0
- package/src/course/dto/cleanup-upload-history.dto.ts +1 -1
- package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
- package/src/course/dto/create-course-export.dto.ts +56 -0
- package/src/course/dto/create-course-structure-lesson.dto.ts +4 -3
- package/src/course/lms-bulk-upload-automation.service.ts +153 -6
- package/src/course/lms-bulk-upload-infra.service.ts +39 -6
- package/src/course/lms-bulk-upload.controller.ts +32 -2
- package/src/course/lms-bulk-upload.service.ts +70 -7
- package/src/course/lms-setting.controller.ts +4 -2
- package/src/course/scorm12-schemas.ts +9 -0
- package/src/enterprise/training/training-student.service.ts +221 -2
- package/src/evaluation/evaluation.service.ts +123 -0
- package/src/exam/dto/create-standalone-question.dto.ts +66 -0
- package/src/exam/exam.module.ts +2 -1
- package/src/exam/exam.service.ts +86 -0
- package/src/exam/question.controller.ts +28 -0
- package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +205 -31
- package/src/lms-commerce-access.subscriber.ts +88 -0
- package/src/lms.module.ts +6 -5
- package/src/platforma/platforma-video.service.ts +346 -0
- package/src/platforma/platforma.controller.ts +95 -1
- package/src/platforma/platforma.service.ts +268 -268
- package/src/student-xp/dto/grant-skill-card-xp.dto.ts +10 -0
- package/src/student-xp/student-xp.controller.ts +18 -2
- package/src/student-xp/student-xp.service.ts +84 -2
- package/hedhog/data/video_resolution_profile.yaml +0 -7
- package/hedhog/frontend/app/video-resolution-profiles/page.tsx.ejs +0 -607
- package/hedhog/table/course_video_resolution_profile.yaml +0 -22
- package/hedhog/table/video_resolution_profile.yaml +0 -18
- package/src/video-resolution-profile/dto/create-video-resolution-profile.dto.ts +0 -16
- package/src/video-resolution-profile/dto/update-video-resolution-profile.dto.ts +0 -16
- package/src/video-resolution-profile/video-resolution-profile.controller.ts +0 -62
- package/src/video-resolution-profile/video-resolution-profile.mcp-tools.ts +0 -128
- package/src/video-resolution-profile/video-resolution-profile.module.ts +0 -13
- package/src/video-resolution-profile/video-resolution-profile.service.ts +0 -117
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { toast } from 'sonner';
|
|
5
|
+
import {
|
|
6
|
+
AlignLeft,
|
|
7
|
+
AlignRight,
|
|
8
|
+
Download,
|
|
9
|
+
FileArchive,
|
|
10
|
+
Info,
|
|
11
|
+
Loader2,
|
|
12
|
+
Monitor,
|
|
13
|
+
Moon,
|
|
14
|
+
PieChart,
|
|
15
|
+
Sun,
|
|
16
|
+
Type,
|
|
17
|
+
} from 'lucide-react';
|
|
18
|
+
import { cn } from '@/lib/utils';
|
|
19
|
+
import { Alert, AlertDescription } from '@/components/ui/alert';
|
|
20
|
+
import { Badge } from '@/components/ui/badge';
|
|
21
|
+
import { Button } from '@/components/ui/button';
|
|
22
|
+
import { Label } from '@/components/ui/label';
|
|
23
|
+
import { ResizableSheetContent } from '@/components/ui/resizable-sheet-content';
|
|
24
|
+
import {
|
|
25
|
+
Sheet,
|
|
26
|
+
SheetDescription,
|
|
27
|
+
SheetFooter,
|
|
28
|
+
SheetHeader,
|
|
29
|
+
SheetTitle,
|
|
30
|
+
} from '@/components/ui/sheet';
|
|
31
|
+
import {
|
|
32
|
+
ScormVisualSettings,
|
|
33
|
+
useCreateCourseExportMutation,
|
|
34
|
+
} from '../_data/use-course-exports';
|
|
35
|
+
|
|
36
|
+
// ── Color presets ────────────────────────────────────────────
|
|
37
|
+
const PRESET_COLORS = [
|
|
38
|
+
'#2563eb',
|
|
39
|
+
'#4338ca',
|
|
40
|
+
'#7c3aed',
|
|
41
|
+
'#e11d48',
|
|
42
|
+
'#ea580c',
|
|
43
|
+
'#059669',
|
|
44
|
+
'#0891b2',
|
|
45
|
+
'#475569',
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const DEFAULT_VISUAL: Required<ScormVisualSettings> = {
|
|
49
|
+
primaryColor: '#2563eb',
|
|
50
|
+
fontFamily: 'system',
|
|
51
|
+
fontSize: 'md',
|
|
52
|
+
sidebarWidth: 280,
|
|
53
|
+
sidebarPosition: 'left',
|
|
54
|
+
progressStyle: 'bar',
|
|
55
|
+
sidebarTheme: 'light',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ── Segmented control ────────────────────────────────────────
|
|
59
|
+
type SegOption<T extends string> = {
|
|
60
|
+
label: string;
|
|
61
|
+
value: T;
|
|
62
|
+
icon?: React.ReactNode;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
function Seg<T extends string>({
|
|
66
|
+
value,
|
|
67
|
+
onChange,
|
|
68
|
+
options,
|
|
69
|
+
}: {
|
|
70
|
+
value: T;
|
|
71
|
+
onChange: (v: T) => void;
|
|
72
|
+
options: SegOption<T>[];
|
|
73
|
+
}) {
|
|
74
|
+
return (
|
|
75
|
+
<div className="flex rounded-md border overflow-hidden bg-background">
|
|
76
|
+
{options.map((opt, i) => (
|
|
77
|
+
<button
|
|
78
|
+
key={opt.value}
|
|
79
|
+
type="button"
|
|
80
|
+
onClick={() => onChange(opt.value)}
|
|
81
|
+
className={cn(
|
|
82
|
+
'flex items-center gap-1.5 flex-1 justify-center px-2.5 py-1.5 text-xs font-medium transition-colors',
|
|
83
|
+
i < options.length - 1 && 'border-r',
|
|
84
|
+
value === opt.value
|
|
85
|
+
? 'bg-primary text-primary-foreground'
|
|
86
|
+
: 'text-muted-foreground hover:bg-muted/60',
|
|
87
|
+
)}
|
|
88
|
+
>
|
|
89
|
+
{opt.icon}
|
|
90
|
+
{opt.label}
|
|
91
|
+
</button>
|
|
92
|
+
))}
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ── Props ─────────────────────────────────────────────────────
|
|
98
|
+
interface CourseExportSheetProps {
|
|
99
|
+
open: boolean;
|
|
100
|
+
onOpenChange: (open: boolean) => void;
|
|
101
|
+
courseId: string;
|
|
102
|
+
sessionCount: number;
|
|
103
|
+
videoLessonCount: number;
|
|
104
|
+
estimatedSizeMb?: number | null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function formatMb(mb: number): string {
|
|
108
|
+
if (mb >= 1024) return `${(mb / 1024).toFixed(1)} GB`;
|
|
109
|
+
return `${mb.toFixed(0)} MB`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ── Component ─────────────────────────────────────────────────
|
|
113
|
+
export function CourseExportSheet({
|
|
114
|
+
open,
|
|
115
|
+
onOpenChange,
|
|
116
|
+
courseId,
|
|
117
|
+
sessionCount,
|
|
118
|
+
videoLessonCount,
|
|
119
|
+
estimatedSizeMb,
|
|
120
|
+
}: CourseExportSheetProps) {
|
|
121
|
+
const [visual, setVisual] = useState<Required<ScormVisualSettings>>(DEFAULT_VISUAL);
|
|
122
|
+
const createExport = useCreateCourseExportMutation(courseId);
|
|
123
|
+
|
|
124
|
+
const setV = <K extends keyof ScormVisualSettings>(
|
|
125
|
+
key: K,
|
|
126
|
+
value: Required<ScormVisualSettings>[K],
|
|
127
|
+
) => setVisual((prev) => ({ ...prev, [key]: value }));
|
|
128
|
+
|
|
129
|
+
const handleConfirm = async () => {
|
|
130
|
+
try {
|
|
131
|
+
await createExport.mutateAsync({
|
|
132
|
+
format: 'scorm_1_2',
|
|
133
|
+
visualSettings: visual,
|
|
134
|
+
});
|
|
135
|
+
onOpenChange(false);
|
|
136
|
+
toast.success(
|
|
137
|
+
'Exportação SCORM 1.2 iniciada. Acompanhe o progresso nas notificações.',
|
|
138
|
+
);
|
|
139
|
+
} catch {
|
|
140
|
+
toast.error('Erro ao iniciar exportação. Tente novamente.');
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<Sheet open={open} onOpenChange={onOpenChange}>
|
|
146
|
+
<ResizableSheetContent
|
|
147
|
+
sheetId="lms-course-export-scorm12-sheet"
|
|
148
|
+
defaultWidth={540}
|
|
149
|
+
minWidth={420}
|
|
150
|
+
maxWidth={780}
|
|
151
|
+
>
|
|
152
|
+
<SheetHeader>
|
|
153
|
+
<SheetTitle className="flex items-center gap-2">
|
|
154
|
+
<FileArchive className="size-4" />
|
|
155
|
+
Exportar para SCORM 1.2
|
|
156
|
+
</SheetTitle>
|
|
157
|
+
<SheetDescription>
|
|
158
|
+
Gera um pacote SCORM 1.2 com as aulas de vídeo do curso. O
|
|
159
|
+
processamento é feito em background.
|
|
160
|
+
</SheetDescription>
|
|
161
|
+
</SheetHeader>
|
|
162
|
+
|
|
163
|
+
<div className="flex flex-col gap-4 px-4 py-4">
|
|
164
|
+
|
|
165
|
+
{/* ── Stats ── */}
|
|
166
|
+
<div className="rounded-lg border bg-muted/30 p-3 flex flex-col gap-2">
|
|
167
|
+
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
|
|
168
|
+
Conteúdo a exportar
|
|
169
|
+
</p>
|
|
170
|
+
<div className="flex flex-wrap gap-2">
|
|
171
|
+
<Badge variant="secondary">
|
|
172
|
+
{sessionCount} {sessionCount === 1 ? 'sessão' : 'sessões'}
|
|
173
|
+
</Badge>
|
|
174
|
+
<Badge variant="secondary">
|
|
175
|
+
{videoLessonCount}{' '}
|
|
176
|
+
{videoLessonCount === 1 ? 'aula de vídeo' : 'aulas de vídeo'}
|
|
177
|
+
</Badge>
|
|
178
|
+
{estimatedSizeMb != null && (
|
|
179
|
+
<Badge variant="outline">~{formatMb(estimatedSizeMb)}</Badge>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
{videoLessonCount === 0 && (
|
|
183
|
+
<p className="text-xs text-destructive mt-1">
|
|
184
|
+
Este curso não possui aulas de vídeo. Não é possível gerar o
|
|
185
|
+
pacote SCORM.
|
|
186
|
+
</p>
|
|
187
|
+
)}
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
{estimatedSizeMb != null && estimatedSizeMb > 500 && (
|
|
191
|
+
<Alert>
|
|
192
|
+
<Info className="size-4" />
|
|
193
|
+
<AlertDescription className="text-xs">
|
|
194
|
+
O pacote gerado pode ter aproximadamente{' '}
|
|
195
|
+
<strong>{formatMb(estimatedSizeMb)}</strong>. Certifique-se que
|
|
196
|
+
seu LMS suporta pacotes desse tamanho.
|
|
197
|
+
</AlertDescription>
|
|
198
|
+
</Alert>
|
|
199
|
+
)}
|
|
200
|
+
|
|
201
|
+
{/* ── Appearance ── */}
|
|
202
|
+
<div className="rounded-lg border overflow-hidden">
|
|
203
|
+
<div className="flex items-center gap-2 px-3 py-2.5 border-b bg-muted/20">
|
|
204
|
+
<Monitor className="size-4 text-muted-foreground" />
|
|
205
|
+
<span className="text-sm font-medium">Personalizar aparência</span>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
<div className="px-3 pt-3 pb-4 flex flex-col gap-4">
|
|
209
|
+
|
|
210
|
+
{/* Primary color */}
|
|
211
|
+
<div className="flex flex-col gap-2">
|
|
212
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
|
213
|
+
Cor Principal
|
|
214
|
+
</Label>
|
|
215
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
216
|
+
{PRESET_COLORS.map((c) => (
|
|
217
|
+
<button
|
|
218
|
+
key={c}
|
|
219
|
+
type="button"
|
|
220
|
+
onClick={() => setV('primaryColor', c)}
|
|
221
|
+
title={c}
|
|
222
|
+
className={cn(
|
|
223
|
+
'w-7 h-7 rounded-full border-2 transition-all hover:scale-110 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
224
|
+
visual.primaryColor === c
|
|
225
|
+
? 'border-foreground ring-2 ring-offset-1 ring-foreground/30 scale-110'
|
|
226
|
+
: 'border-transparent',
|
|
227
|
+
)}
|
|
228
|
+
style={{ background: c }}
|
|
229
|
+
/>
|
|
230
|
+
))}
|
|
231
|
+
{/* Custom color picker */}
|
|
232
|
+
<label className="cursor-pointer" title="Cor personalizada">
|
|
233
|
+
<input
|
|
234
|
+
type="color"
|
|
235
|
+
value={visual.primaryColor}
|
|
236
|
+
onChange={(e) => setV('primaryColor', e.target.value)}
|
|
237
|
+
className="sr-only"
|
|
238
|
+
/>
|
|
239
|
+
<div
|
|
240
|
+
className={cn(
|
|
241
|
+
'w-7 h-7 rounded-full border-2 border-dashed transition-all hover:scale-110',
|
|
242
|
+
!PRESET_COLORS.includes(visual.primaryColor)
|
|
243
|
+
? 'border-foreground ring-2 ring-offset-1 ring-foreground/30 scale-110'
|
|
244
|
+
: 'border-muted-foreground/50',
|
|
245
|
+
)}
|
|
246
|
+
style={{ background: visual.primaryColor }}
|
|
247
|
+
/>
|
|
248
|
+
</label>
|
|
249
|
+
</div>
|
|
250
|
+
<div className="flex items-center gap-1.5">
|
|
251
|
+
<div
|
|
252
|
+
className="w-3 h-3 rounded-sm border border-border/60 shrink-0"
|
|
253
|
+
style={{ background: visual.primaryColor }}
|
|
254
|
+
/>
|
|
255
|
+
<span className="text-xs font-mono text-muted-foreground">
|
|
256
|
+
{visual.primaryColor.toUpperCase()}
|
|
257
|
+
</span>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
{/* Font family */}
|
|
262
|
+
<div className="flex flex-col gap-2">
|
|
263
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide flex items-center gap-1.5">
|
|
264
|
+
<Type className="size-3" />
|
|
265
|
+
Fonte
|
|
266
|
+
</Label>
|
|
267
|
+
<Seg
|
|
268
|
+
value={visual.fontFamily as 'system' | 'humanist' | 'serif' | 'mono'}
|
|
269
|
+
onChange={(v) => setV('fontFamily', v)}
|
|
270
|
+
options={[
|
|
271
|
+
{ label: 'Sistema', value: 'system' as const },
|
|
272
|
+
{ label: 'Humanista', value: 'humanist' as const },
|
|
273
|
+
{ label: 'Serifada', value: 'serif' as const },
|
|
274
|
+
{ label: 'Mono', value: 'mono' as const },
|
|
275
|
+
]}
|
|
276
|
+
/>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
{/* Font size + Sidebar width */}
|
|
280
|
+
<div className="grid grid-cols-2 gap-3">
|
|
281
|
+
<div className="flex flex-col gap-2">
|
|
282
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
|
283
|
+
Tamanho da fonte
|
|
284
|
+
</Label>
|
|
285
|
+
<Seg
|
|
286
|
+
value={visual.fontSize as 'sm' | 'md' | 'lg'}
|
|
287
|
+
onChange={(v) => setV('fontSize', v)}
|
|
288
|
+
options={[
|
|
289
|
+
{ label: 'Peq.', value: 'sm' as const },
|
|
290
|
+
{ label: 'Méd.', value: 'md' as const },
|
|
291
|
+
{ label: 'Grd.', value: 'lg' as const },
|
|
292
|
+
]}
|
|
293
|
+
/>
|
|
294
|
+
</div>
|
|
295
|
+
<div className="flex flex-col gap-2">
|
|
296
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
|
297
|
+
Largura do painel —{' '}
|
|
298
|
+
<span className="text-foreground font-normal normal-case">
|
|
299
|
+
{visual.sidebarWidth}px
|
|
300
|
+
</span>
|
|
301
|
+
</Label>
|
|
302
|
+
<div className="flex items-center gap-2 pt-1">
|
|
303
|
+
<span className="text-xs text-muted-foreground">200</span>
|
|
304
|
+
<input
|
|
305
|
+
type="range"
|
|
306
|
+
min={200}
|
|
307
|
+
max={420}
|
|
308
|
+
step={10}
|
|
309
|
+
value={visual.sidebarWidth}
|
|
310
|
+
onChange={(e) => setV('sidebarWidth', Number(e.target.value))}
|
|
311
|
+
className="flex-1 h-1.5 rounded-full cursor-pointer accent-primary"
|
|
312
|
+
/>
|
|
313
|
+
<span className="text-xs text-muted-foreground">420</span>
|
|
314
|
+
</div>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
|
|
318
|
+
{/* Sidebar position + Progress style */}
|
|
319
|
+
<div className="grid grid-cols-2 gap-3">
|
|
320
|
+
<div className="flex flex-col gap-2">
|
|
321
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
|
322
|
+
Posição do painel
|
|
323
|
+
</Label>
|
|
324
|
+
<Seg
|
|
325
|
+
value={visual.sidebarPosition as 'left' | 'right'}
|
|
326
|
+
onChange={(v) => setV('sidebarPosition', v)}
|
|
327
|
+
options={[
|
|
328
|
+
{
|
|
329
|
+
label: 'Esq.',
|
|
330
|
+
value: 'left' as const,
|
|
331
|
+
icon: <AlignLeft className="size-3" />,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
label: 'Dir.',
|
|
335
|
+
value: 'right' as const,
|
|
336
|
+
icon: <AlignRight className="size-3" />,
|
|
337
|
+
},
|
|
338
|
+
]}
|
|
339
|
+
/>
|
|
340
|
+
</div>
|
|
341
|
+
<div className="flex flex-col gap-2">
|
|
342
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
|
343
|
+
Indicador de progresso
|
|
344
|
+
</Label>
|
|
345
|
+
<Seg
|
|
346
|
+
value={visual.progressStyle as 'bar' | 'pie'}
|
|
347
|
+
onChange={(v) => setV('progressStyle', v)}
|
|
348
|
+
options={[
|
|
349
|
+
{ label: 'Barra', value: 'bar' as const },
|
|
350
|
+
{
|
|
351
|
+
label: 'Pizza',
|
|
352
|
+
value: 'pie' as const,
|
|
353
|
+
icon: <PieChart className="size-3" />,
|
|
354
|
+
},
|
|
355
|
+
]}
|
|
356
|
+
/>
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
{/* Sidebar theme */}
|
|
361
|
+
<div className="flex flex-col gap-2">
|
|
362
|
+
<Label className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
|
|
363
|
+
Tema do painel
|
|
364
|
+
</Label>
|
|
365
|
+
<Seg
|
|
366
|
+
value={visual.sidebarTheme as 'light' | 'dark'}
|
|
367
|
+
onChange={(v) => setV('sidebarTheme', v)}
|
|
368
|
+
options={[
|
|
369
|
+
{
|
|
370
|
+
label: 'Claro',
|
|
371
|
+
value: 'light' as const,
|
|
372
|
+
icon: <Sun className="size-3" />,
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
label: 'Escuro',
|
|
376
|
+
value: 'dark' as const,
|
|
377
|
+
icon: <Moon className="size-3" />,
|
|
378
|
+
},
|
|
379
|
+
]}
|
|
380
|
+
/>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
|
|
385
|
+
{/* ── Info ── */}
|
|
386
|
+
<div className="rounded-lg border bg-muted/20 p-3">
|
|
387
|
+
<p className="text-xs text-muted-foreground">
|
|
388
|
+
<strong>Padrão SCORM 1.2</strong> — Compatível com a maioria dos
|
|
389
|
+
sistemas de gestão de aprendizagem (LMS). Os arquivos de vídeo são
|
|
390
|
+
incluídos no pacote e o progresso de cada aula é rastreado
|
|
391
|
+
automaticamente.
|
|
392
|
+
</p>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<SheetFooter>
|
|
397
|
+
<Button
|
|
398
|
+
variant="outline"
|
|
399
|
+
onClick={() => onOpenChange(false)}
|
|
400
|
+
disabled={createExport.isPending}
|
|
401
|
+
>
|
|
402
|
+
Cancelar
|
|
403
|
+
</Button>
|
|
404
|
+
<Button
|
|
405
|
+
onClick={handleConfirm}
|
|
406
|
+
disabled={createExport.isPending || videoLessonCount === 0}
|
|
407
|
+
className="gap-2"
|
|
408
|
+
>
|
|
409
|
+
{createExport.isPending ? (
|
|
410
|
+
<Loader2 className="size-4 animate-spin" />
|
|
411
|
+
) : (
|
|
412
|
+
<Download className="size-4" />
|
|
413
|
+
)}
|
|
414
|
+
Exportar SCORM 1.2
|
|
415
|
+
</Button>
|
|
416
|
+
</SheetFooter>
|
|
417
|
+
</ResizableSheetContent>
|
|
418
|
+
</Sheet>
|
|
419
|
+
);
|
|
420
|
+
}
|