@hed-hog/lms 0.0.314 → 0.0.315
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/class-group/class-group.controller.d.ts +2 -2
- package/dist/class-group/class-group.service.d.ts +2 -2
- package/dist/enterprise/dto/enterprise-profile.dto.d.ts +13 -0
- package/dist/enterprise/dto/enterprise-profile.dto.d.ts.map +1 -0
- package/dist/enterprise/dto/enterprise-profile.dto.js +3 -0
- package/dist/enterprise/dto/enterprise-profile.dto.js.map +1 -0
- package/dist/enterprise/enterprise.controller.d.ts +3 -0
- package/dist/enterprise/enterprise.controller.d.ts.map +1 -1
- package/dist/enterprise/enterprise.controller.js +14 -0
- package/dist/enterprise/enterprise.controller.js.map +1 -1
- package/dist/enterprise/enterprise.service.d.ts +3 -0
- package/dist/enterprise/enterprise.service.d.ts.map +1 -1
- package/dist/enterprise/enterprise.service.js +128 -1
- package/dist/enterprise/enterprise.service.js.map +1 -1
- package/dist/instructor/instructor.controller.d.ts +23 -0
- package/dist/instructor/instructor.controller.d.ts.map +1 -1
- package/dist/instructor/instructor.controller.js +41 -0
- package/dist/instructor/instructor.controller.js.map +1 -1
- package/dist/instructor/instructor.service.d.ts +25 -0
- package/dist/instructor/instructor.service.d.ts.map +1 -1
- package/dist/instructor/instructor.service.js +126 -8
- package/dist/instructor/instructor.service.js.map +1 -1
- package/hedhog/data/menu.yaml +23 -7
- package/hedhog/data/role.yaml +9 -1
- package/hedhog/data/route.yaml +54 -0
- package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +2 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/confirm-dialog.tsx.ejs +44 -44
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +362 -362
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-panel.tsx.ejs +111 -111
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +134 -134
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +113 -113
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +314 -314
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +62 -62
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +173 -173
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-handle.tsx.ejs +58 -58
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +51 -51
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +276 -276
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +1216 -1216
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +1824 -1824
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-session.tsx.ejs +443 -443
- package/hedhog/frontend/app/courses/[id]/structure/_components/highlighted-text.tsx.ejs +40 -40
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +185 -185
- package/hedhog/frontend/app/courses/[id]/structure/_components/multi-select-bar.tsx.ejs +264 -264
- package/hedhog/frontend/app/courses/[id]/structure/_components/search-filter.tsx.ejs +95 -95
- package/hedhog/frontend/app/courses/[id]/structure/_components/session-picker-dialog.tsx.ejs +73 -73
- package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +136 -136
- package/hedhog/frontend/app/courses/[id]/structure/_components/sortable-tree-row.tsx.ejs +80 -80
- package/hedhog/frontend/app/courses/[id]/structure/_components/store.ts.ejs +949 -949
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-context-menu.tsx.ejs +525 -525
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-helpers.ts.ejs +181 -181
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-course.tsx.ejs +51 -51
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +271 -271
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-session.tsx.ejs +167 -167
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row.tsx.ejs +108 -108
- package/hedhog/frontend/app/courses/[id]/structure/_components/use-course-structure-shortcuts.ts.ejs +318 -318
- package/hedhog/frontend/app/courses/[id]/structure/page.tsx.ejs +10 -10
- package/hedhog/frontend/app/enterprise/_components/enterprise-course-create-sheet.tsx.ejs +2 -1
- package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +438 -0
- package/hedhog/frontend/app/instructors/_components/instructor-types.ts.ejs +40 -0
- package/hedhog/frontend/app/instructors/page.tsx.ejs +696 -0
- package/hedhog/frontend/app/training/page.tsx.ejs +2339 -0
- package/hedhog/table/enterprise_user.yaml +1 -1
- package/package.json +8 -8
- package/src/enterprise/dto/enterprise-profile.dto.ts +17 -0
- package/src/enterprise/enterprise.controller.ts +9 -1
- package/src/enterprise/enterprise.service.ts +147 -4
- package/src/instructor/instructor.controller.ts +36 -9
- package/src/instructor/instructor.service.ts +140 -10
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { cn } from '@/lib/utils';
|
|
4
|
-
import { getTextSegments } from './tree-helpers';
|
|
5
|
-
|
|
6
|
-
interface HighlightedTextProps {
|
|
7
|
-
text: string;
|
|
8
|
-
query: string;
|
|
9
|
-
className?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Renders `text` with the first occurrence of `query` visually highlighted.
|
|
14
|
-
* Falls back to plain text when query is empty or no match is found.
|
|
15
|
-
*/
|
|
16
|
-
export function HighlightedText({ text, query, className }: HighlightedTextProps) {
|
|
17
|
-
const segments = getTextSegments(text, query);
|
|
18
|
-
|
|
19
|
-
if (segments.length === 1 && !segments[0]?.highlight) {
|
|
20
|
-
return <span className={className}>{text}</span>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<span className={className}>
|
|
25
|
-
{segments.map((seg, i) =>
|
|
26
|
-
seg.highlight ? (
|
|
27
|
-
<mark
|
|
28
|
-
key={i}
|
|
29
|
-
className={cn(
|
|
30
|
-
'bg-yellow-300/70 dark:bg-yellow-500/40 text-current rounded-[2px] px-[1px]'
|
|
31
|
-
)}
|
|
32
|
-
>
|
|
33
|
-
{seg.text}
|
|
34
|
-
</mark>
|
|
35
|
-
) : (
|
|
36
|
-
<span key={i}>{seg.text}</span>
|
|
37
|
-
)
|
|
38
|
-
)}
|
|
39
|
-
</span>
|
|
40
|
-
);
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
import { getTextSegments } from './tree-helpers';
|
|
5
|
+
|
|
6
|
+
interface HighlightedTextProps {
|
|
7
|
+
text: string;
|
|
8
|
+
query: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Renders `text` with the first occurrence of `query` visually highlighted.
|
|
14
|
+
* Falls back to plain text when query is empty or no match is found.
|
|
15
|
+
*/
|
|
16
|
+
export function HighlightedText({ text, query, className }: HighlightedTextProps) {
|
|
17
|
+
const segments = getTextSegments(text, query);
|
|
18
|
+
|
|
19
|
+
if (segments.length === 1 && !segments[0]?.highlight) {
|
|
20
|
+
return <span className={className}>{text}</span>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<span className={className}>
|
|
25
|
+
{segments.map((seg, i) =>
|
|
26
|
+
seg.highlight ? (
|
|
27
|
+
<mark
|
|
28
|
+
key={i}
|
|
29
|
+
className={cn(
|
|
30
|
+
'bg-yellow-300/70 dark:bg-yellow-500/40 text-current rounded-[2px] px-[1px]'
|
|
31
|
+
)}
|
|
32
|
+
>
|
|
33
|
+
{seg.text}
|
|
34
|
+
</mark>
|
|
35
|
+
) : (
|
|
36
|
+
<span key={i}>{seg.text}</span>
|
|
37
|
+
)
|
|
38
|
+
)}
|
|
39
|
+
</span>
|
|
40
|
+
);
|
|
41
41
|
}
|
|
@@ -1,185 +1,185 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock Data — LMS Course Structure
|
|
3
|
-
*
|
|
4
|
-
* ⚠️ TEMPORARY — replace when integrating with the real API.
|
|
5
|
-
*
|
|
6
|
-
* TODO[API]: Remove this file entirely once `useCourseStructure` fetches data
|
|
7
|
-
* from GET /lms/courses/:id/structure. The Zustand store should then
|
|
8
|
-
* be seeded with the server response instead of these constants.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type {
|
|
12
|
-
Course,
|
|
13
|
-
Lesson,
|
|
14
|
-
LessonStatus,
|
|
15
|
-
LessonType,
|
|
16
|
-
Session,
|
|
17
|
-
VideoProvider,
|
|
18
|
-
Visibility,
|
|
19
|
-
} from './types';
|
|
20
|
-
|
|
21
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
-
// Mock Data — LMS Course Structure
|
|
23
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
-
|
|
25
|
-
export const MOCK_COURSE: Course = {
|
|
26
|
-
id: 'course-1',
|
|
27
|
-
code: 'REACT-ADV',
|
|
28
|
-
name: 'React Avancado',
|
|
29
|
-
title: 'React Avancado',
|
|
30
|
-
description:
|
|
31
|
-
'Domine os conceitos avancados do React: hooks, patterns, performance e gerenciamento de estado moderno.',
|
|
32
|
-
slug: 'react-avancado',
|
|
33
|
-
published: true,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Session config: title + how many lessons each gets
|
|
37
|
-
const SESSION_CONFIG: { title: string; lessonCount: number }[] = [
|
|
38
|
-
{ title: 'Boas-vindas ao curso', lessonCount: 5 },
|
|
39
|
-
{ title: 'Hooks Avancados useReducer e useContext', lessonCount: 32 },
|
|
40
|
-
{ title: 'Patterns de Composicao', lessonCount: 31 },
|
|
41
|
-
{ title: 'Gerenciamento de Estado com Zustand', lessonCount: 8 },
|
|
42
|
-
{ title: 'Performance e Otimizacao', lessonCount: 30 },
|
|
43
|
-
{ title: 'React Server Components', lessonCount: 10 },
|
|
44
|
-
{ title: 'Data Fetching Moderno', lessonCount: 9 },
|
|
45
|
-
{ title: 'Roteamento Avancado com Next.js', lessonCount: 7 },
|
|
46
|
-
{ title: 'Formularios e Validacao com RHF', lessonCount: 11 },
|
|
47
|
-
{ title: 'Autenticacao e Seguranca', lessonCount: 9 },
|
|
48
|
-
{ title: 'Testing com React Testing Library', lessonCount: 12 },
|
|
49
|
-
{ title: 'Acessibilidade a11y', lessonCount: 6 },
|
|
50
|
-
{ title: 'Internacionalizacao i18n', lessonCount: 7 },
|
|
51
|
-
{ title: 'Animacoes com Framer Motion', lessonCount: 8 },
|
|
52
|
-
{ title: 'Arquitetura de Projetos Escalaveis', lessonCount: 10 },
|
|
53
|
-
{ title: 'Design Systems e Storybook', lessonCount: 8 },
|
|
54
|
-
{ title: 'Deploy CI/CD e DevOps', lessonCount: 7 },
|
|
55
|
-
{ title: 'Monorepos e Micro-frontends', lessonCount: 6 },
|
|
56
|
-
{ title: 'Debugging Avancado', lessonCount: 6 },
|
|
57
|
-
{ title: 'Projeto Final App Completo', lessonCount: 5 },
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
export const MOCK_SESSIONS: Session[] = SESSION_CONFIG.map((s, i) => ({
|
|
61
|
-
id: `s${i + 1}`,
|
|
62
|
-
code: `S${String(i + 1).padStart(2, '0')}`,
|
|
63
|
-
title: s.title,
|
|
64
|
-
duration: s.lessonCount * 12,
|
|
65
|
-
order: i,
|
|
66
|
-
}));
|
|
67
|
-
|
|
68
|
-
// Lesson title patterns
|
|
69
|
-
const TITLE_PATTERNS = [
|
|
70
|
-
'Introducao e objetivos',
|
|
71
|
-
'Conceitos fundamentais',
|
|
72
|
-
'Configuracao do ambiente',
|
|
73
|
-
'Pratica guiada passo a passo',
|
|
74
|
-
'Exercicio: implementacao',
|
|
75
|
-
'Quiz de revisao',
|
|
76
|
-
'Caso de uso real',
|
|
77
|
-
'Implementacao completa',
|
|
78
|
-
'Debugging e troubleshooting',
|
|
79
|
-
'Otimizacoes e boas praticas',
|
|
80
|
-
'Desafio pratico',
|
|
81
|
-
'Revisao do modulo',
|
|
82
|
-
'Q e A e duvidas frequentes',
|
|
83
|
-
'Proximos passos',
|
|
84
|
-
];
|
|
85
|
-
|
|
86
|
-
const LESSON_STATUSES: LessonStatus[] = [
|
|
87
|
-
'preparada',
|
|
88
|
-
'gravada',
|
|
89
|
-
'editada',
|
|
90
|
-
'finalizada',
|
|
91
|
-
'publicada',
|
|
92
|
-
];
|
|
93
|
-
|
|
94
|
-
const VISIBILITIES: Visibility[] = [
|
|
95
|
-
'publico',
|
|
96
|
-
'publico',
|
|
97
|
-
'privado',
|
|
98
|
-
'restrito',
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
const LESSON_TYPES: LessonType[] = [
|
|
102
|
-
'video',
|
|
103
|
-
'video',
|
|
104
|
-
'video',
|
|
105
|
-
'post',
|
|
106
|
-
'video',
|
|
107
|
-
'video',
|
|
108
|
-
'questao',
|
|
109
|
-
'exercicio',
|
|
110
|
-
];
|
|
111
|
-
const PROVIDERS: VideoProvider[] = [
|
|
112
|
-
'youtube',
|
|
113
|
-
'vimeo',
|
|
114
|
-
'bunny',
|
|
115
|
-
'youtube',
|
|
116
|
-
'youtube',
|
|
117
|
-
];
|
|
118
|
-
|
|
119
|
-
let _lid = 0;
|
|
120
|
-
|
|
121
|
-
export const MOCK_LESSONS: Lesson[] = SESSION_CONFIG.flatMap((s, si) =>
|
|
122
|
-
Array.from({ length: s.lessonCount }, (_, li) => {
|
|
123
|
-
_lid += 1;
|
|
124
|
-
const type = LESSON_TYPES[_lid % LESSON_TYPES.length] as LessonType;
|
|
125
|
-
const isVideo = type === 'video';
|
|
126
|
-
const provider = PROVIDERS[_lid % PROVIDERS.length] as VideoProvider;
|
|
127
|
-
const baseTitle = TITLE_PATTERNS[li % TITLE_PATTERNS.length] as string;
|
|
128
|
-
const title =
|
|
129
|
-
li < TITLE_PATTERNS.length
|
|
130
|
-
? baseTitle
|
|
131
|
-
: baseTitle +
|
|
132
|
-
' parte ' +
|
|
133
|
-
String(Math.floor(li / TITLE_PATTERNS.length) + 1);
|
|
134
|
-
|
|
135
|
-
const hasResource = li % 4 === 0;
|
|
136
|
-
|
|
137
|
-
const status = LESSON_STATUSES[
|
|
138
|
-
_lid % LESSON_STATUSES.length
|
|
139
|
-
] as LessonStatus;
|
|
140
|
-
const visibility = VISIBILITIES[_lid % VISIBILITIES.length] as Visibility;
|
|
141
|
-
|
|
142
|
-
const lesson: Lesson = {
|
|
143
|
-
id: `l${_lid}`,
|
|
144
|
-
code: `A${String(_lid).padStart(3, '0')}`,
|
|
145
|
-
title,
|
|
146
|
-
type,
|
|
147
|
-
status,
|
|
148
|
-
visibility,
|
|
149
|
-
duration: 8 + (_lid % 32),
|
|
150
|
-
publicDescription: `Aprenda ${s.title.toLowerCase()} de forma pratica nesta aula.`,
|
|
151
|
-
privateDescription: li % 7 === 0 ? 'Revisar antes de publicar.' : '',
|
|
152
|
-
sessionId: `s${si + 1}`,
|
|
153
|
-
order: li,
|
|
154
|
-
resources: hasResource
|
|
155
|
-
? [
|
|
156
|
-
{
|
|
157
|
-
id: `r${_lid}`,
|
|
158
|
-
name: `material-${String(_lid).padStart(3, '0')}.pdf`,
|
|
159
|
-
size: `${1 + (_lid % 5)}.${_lid % 9} MB`,
|
|
160
|
-
type: 'application/pdf',
|
|
161
|
-
public: _lid % 2 === 0,
|
|
162
|
-
url: `https://www.w3.org/WAI/WCAG21/Techniques/pdf/PDF1.pdf`,
|
|
163
|
-
},
|
|
164
|
-
]
|
|
165
|
-
: [],
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
if (isVideo) {
|
|
169
|
-
lesson.videoProvider = provider;
|
|
170
|
-
lesson.videoUrl = `https://example.com/video/${_lid}`;
|
|
171
|
-
lesson.autoDuration = _lid % 3 !== 0;
|
|
172
|
-
if (li === 0) {
|
|
173
|
-
lesson.transcription = `Transcricao completa da primeira aula de "${s.title}". Lorem ipsum dolor sit amet, consectetur adipiscing elit.`;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (type === 'questao') {
|
|
177
|
-
lesson.linkedExam = `exam-${_lid}`;
|
|
178
|
-
}
|
|
179
|
-
if (type === 'post') {
|
|
180
|
-
lesson.postContent = `Conteudo detalhado sobre ${s.title.toLowerCase()}...`;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return lesson;
|
|
184
|
-
})
|
|
185
|
-
);
|
|
1
|
+
/**
|
|
2
|
+
* Mock Data — LMS Course Structure
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ TEMPORARY — replace when integrating with the real API.
|
|
5
|
+
*
|
|
6
|
+
* TODO[API]: Remove this file entirely once `useCourseStructure` fetches data
|
|
7
|
+
* from GET /lms/courses/:id/structure. The Zustand store should then
|
|
8
|
+
* be seeded with the server response instead of these constants.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
Course,
|
|
13
|
+
Lesson,
|
|
14
|
+
LessonStatus,
|
|
15
|
+
LessonType,
|
|
16
|
+
Session,
|
|
17
|
+
VideoProvider,
|
|
18
|
+
Visibility,
|
|
19
|
+
} from './types';
|
|
20
|
+
|
|
21
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
// Mock Data — LMS Course Structure
|
|
23
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
export const MOCK_COURSE: Course = {
|
|
26
|
+
id: 'course-1',
|
|
27
|
+
code: 'REACT-ADV',
|
|
28
|
+
name: 'React Avancado',
|
|
29
|
+
title: 'React Avancado',
|
|
30
|
+
description:
|
|
31
|
+
'Domine os conceitos avancados do React: hooks, patterns, performance e gerenciamento de estado moderno.',
|
|
32
|
+
slug: 'react-avancado',
|
|
33
|
+
published: true,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Session config: title + how many lessons each gets
|
|
37
|
+
const SESSION_CONFIG: { title: string; lessonCount: number }[] = [
|
|
38
|
+
{ title: 'Boas-vindas ao curso', lessonCount: 5 },
|
|
39
|
+
{ title: 'Hooks Avancados useReducer e useContext', lessonCount: 32 },
|
|
40
|
+
{ title: 'Patterns de Composicao', lessonCount: 31 },
|
|
41
|
+
{ title: 'Gerenciamento de Estado com Zustand', lessonCount: 8 },
|
|
42
|
+
{ title: 'Performance e Otimizacao', lessonCount: 30 },
|
|
43
|
+
{ title: 'React Server Components', lessonCount: 10 },
|
|
44
|
+
{ title: 'Data Fetching Moderno', lessonCount: 9 },
|
|
45
|
+
{ title: 'Roteamento Avancado com Next.js', lessonCount: 7 },
|
|
46
|
+
{ title: 'Formularios e Validacao com RHF', lessonCount: 11 },
|
|
47
|
+
{ title: 'Autenticacao e Seguranca', lessonCount: 9 },
|
|
48
|
+
{ title: 'Testing com React Testing Library', lessonCount: 12 },
|
|
49
|
+
{ title: 'Acessibilidade a11y', lessonCount: 6 },
|
|
50
|
+
{ title: 'Internacionalizacao i18n', lessonCount: 7 },
|
|
51
|
+
{ title: 'Animacoes com Framer Motion', lessonCount: 8 },
|
|
52
|
+
{ title: 'Arquitetura de Projetos Escalaveis', lessonCount: 10 },
|
|
53
|
+
{ title: 'Design Systems e Storybook', lessonCount: 8 },
|
|
54
|
+
{ title: 'Deploy CI/CD e DevOps', lessonCount: 7 },
|
|
55
|
+
{ title: 'Monorepos e Micro-frontends', lessonCount: 6 },
|
|
56
|
+
{ title: 'Debugging Avancado', lessonCount: 6 },
|
|
57
|
+
{ title: 'Projeto Final App Completo', lessonCount: 5 },
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
export const MOCK_SESSIONS: Session[] = SESSION_CONFIG.map((s, i) => ({
|
|
61
|
+
id: `s${i + 1}`,
|
|
62
|
+
code: `S${String(i + 1).padStart(2, '0')}`,
|
|
63
|
+
title: s.title,
|
|
64
|
+
duration: s.lessonCount * 12,
|
|
65
|
+
order: i,
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
// Lesson title patterns
|
|
69
|
+
const TITLE_PATTERNS = [
|
|
70
|
+
'Introducao e objetivos',
|
|
71
|
+
'Conceitos fundamentais',
|
|
72
|
+
'Configuracao do ambiente',
|
|
73
|
+
'Pratica guiada passo a passo',
|
|
74
|
+
'Exercicio: implementacao',
|
|
75
|
+
'Quiz de revisao',
|
|
76
|
+
'Caso de uso real',
|
|
77
|
+
'Implementacao completa',
|
|
78
|
+
'Debugging e troubleshooting',
|
|
79
|
+
'Otimizacoes e boas praticas',
|
|
80
|
+
'Desafio pratico',
|
|
81
|
+
'Revisao do modulo',
|
|
82
|
+
'Q e A e duvidas frequentes',
|
|
83
|
+
'Proximos passos',
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
const LESSON_STATUSES: LessonStatus[] = [
|
|
87
|
+
'preparada',
|
|
88
|
+
'gravada',
|
|
89
|
+
'editada',
|
|
90
|
+
'finalizada',
|
|
91
|
+
'publicada',
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
const VISIBILITIES: Visibility[] = [
|
|
95
|
+
'publico',
|
|
96
|
+
'publico',
|
|
97
|
+
'privado',
|
|
98
|
+
'restrito',
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const LESSON_TYPES: LessonType[] = [
|
|
102
|
+
'video',
|
|
103
|
+
'video',
|
|
104
|
+
'video',
|
|
105
|
+
'post',
|
|
106
|
+
'video',
|
|
107
|
+
'video',
|
|
108
|
+
'questao',
|
|
109
|
+
'exercicio',
|
|
110
|
+
];
|
|
111
|
+
const PROVIDERS: VideoProvider[] = [
|
|
112
|
+
'youtube',
|
|
113
|
+
'vimeo',
|
|
114
|
+
'bunny',
|
|
115
|
+
'youtube',
|
|
116
|
+
'youtube',
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
let _lid = 0;
|
|
120
|
+
|
|
121
|
+
export const MOCK_LESSONS: Lesson[] = SESSION_CONFIG.flatMap((s, si) =>
|
|
122
|
+
Array.from({ length: s.lessonCount }, (_, li) => {
|
|
123
|
+
_lid += 1;
|
|
124
|
+
const type = LESSON_TYPES[_lid % LESSON_TYPES.length] as LessonType;
|
|
125
|
+
const isVideo = type === 'video';
|
|
126
|
+
const provider = PROVIDERS[_lid % PROVIDERS.length] as VideoProvider;
|
|
127
|
+
const baseTitle = TITLE_PATTERNS[li % TITLE_PATTERNS.length] as string;
|
|
128
|
+
const title =
|
|
129
|
+
li < TITLE_PATTERNS.length
|
|
130
|
+
? baseTitle
|
|
131
|
+
: baseTitle +
|
|
132
|
+
' parte ' +
|
|
133
|
+
String(Math.floor(li / TITLE_PATTERNS.length) + 1);
|
|
134
|
+
|
|
135
|
+
const hasResource = li % 4 === 0;
|
|
136
|
+
|
|
137
|
+
const status = LESSON_STATUSES[
|
|
138
|
+
_lid % LESSON_STATUSES.length
|
|
139
|
+
] as LessonStatus;
|
|
140
|
+
const visibility = VISIBILITIES[_lid % VISIBILITIES.length] as Visibility;
|
|
141
|
+
|
|
142
|
+
const lesson: Lesson = {
|
|
143
|
+
id: `l${_lid}`,
|
|
144
|
+
code: `A${String(_lid).padStart(3, '0')}`,
|
|
145
|
+
title,
|
|
146
|
+
type,
|
|
147
|
+
status,
|
|
148
|
+
visibility,
|
|
149
|
+
duration: 8 + (_lid % 32),
|
|
150
|
+
publicDescription: `Aprenda ${s.title.toLowerCase()} de forma pratica nesta aula.`,
|
|
151
|
+
privateDescription: li % 7 === 0 ? 'Revisar antes de publicar.' : '',
|
|
152
|
+
sessionId: `s${si + 1}`,
|
|
153
|
+
order: li,
|
|
154
|
+
resources: hasResource
|
|
155
|
+
? [
|
|
156
|
+
{
|
|
157
|
+
id: `r${_lid}`,
|
|
158
|
+
name: `material-${String(_lid).padStart(3, '0')}.pdf`,
|
|
159
|
+
size: `${1 + (_lid % 5)}.${_lid % 9} MB`,
|
|
160
|
+
type: 'application/pdf',
|
|
161
|
+
public: _lid % 2 === 0,
|
|
162
|
+
url: `https://www.w3.org/WAI/WCAG21/Techniques/pdf/PDF1.pdf`,
|
|
163
|
+
},
|
|
164
|
+
]
|
|
165
|
+
: [],
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
if (isVideo) {
|
|
169
|
+
lesson.videoProvider = provider;
|
|
170
|
+
lesson.videoUrl = `https://example.com/video/${_lid}`;
|
|
171
|
+
lesson.autoDuration = _lid % 3 !== 0;
|
|
172
|
+
if (li === 0) {
|
|
173
|
+
lesson.transcription = `Transcricao completa da primeira aula de "${s.title}". Lorem ipsum dolor sit amet, consectetur adipiscing elit.`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (type === 'questao') {
|
|
177
|
+
lesson.linkedExam = `exam-${_lid}`;
|
|
178
|
+
}
|
|
179
|
+
if (type === 'post') {
|
|
180
|
+
lesson.postContent = `Conteudo detalhado sobre ${s.title.toLowerCase()}...`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return lesson;
|
|
184
|
+
})
|
|
185
|
+
);
|