@hed-hog/lms 0.0.328 → 0.0.330

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.
Files changed (52) hide show
  1. package/dist/instructor/instructor.service.d.ts.map +1 -1
  2. package/dist/instructor/instructor.service.js +22 -16
  3. package/dist/instructor/instructor.service.js.map +1 -1
  4. package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +18 -8
  5. package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +7 -5
  6. package/hedhog/frontend/app/_components/create-lms-person-sheet.tsx.ejs +5 -9
  7. package/hedhog/frontend/app/_components/create-lms-student-person-sheet.tsx.ejs +5 -9
  8. package/hedhog/frontend/app/certificates/models/LeftPanel.tsx.ejs +15 -14
  9. package/hedhog/frontend/app/certificates/models/RightPanel.tsx.ejs +66 -29
  10. package/hedhog/frontend/app/certificates/models/TemplateEditorPage.tsx.ejs +4 -2
  11. package/hedhog/frontend/app/certificates/models/TopBar.tsx.ejs +44 -34
  12. package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +10 -10
  13. package/hedhog/frontend/app/classes/page.tsx.ejs +23 -15
  14. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +5 -3
  15. package/hedhog/frontend/app/courses/[id]/structure/_components/confirm-dialog.tsx.ejs +5 -3
  16. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-panel.tsx.ejs +9 -7
  17. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-skeleton.tsx.ejs +3 -1
  18. package/hedhog/frontend/app/courses/[id]/structure/_components/drag-handle.tsx.ejs +4 -2
  19. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +24 -23
  20. package/hedhog/frontend/app/courses/[id]/structure/_components/multi-select-bar.tsx.ejs +21 -19
  21. package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +7 -5
  22. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +18 -16
  23. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +13 -11
  24. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-session.tsx.ejs +5 -3
  25. package/hedhog/frontend/app/courses/[id]/structure/_components/use-course-structure-shortcuts.ts.ejs +14 -9
  26. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +42 -25
  27. package/hedhog/frontend/app/enterprise/_components/enterprise-admin-create-sheet.tsx.ejs +3 -1
  28. package/hedhog/frontend/app/enterprise/_components/enterprise-administrators-tab.tsx.ejs +10 -8
  29. package/hedhog/frontend/app/enterprise/_components/enterprise-classes-tab.tsx.ejs +22 -20
  30. package/hedhog/frontend/app/enterprise/_components/enterprise-course-create-sheet.tsx.ejs +3 -3
  31. package/hedhog/frontend/app/enterprise/_components/enterprise-courses-tab.tsx.ejs +21 -19
  32. package/hedhog/frontend/app/enterprise/_components/enterprise-sheet.tsx.ejs +34 -36
  33. package/hedhog/frontend/app/enterprise/_components/enterprise-student-create-sheet.tsx.ejs +3 -1
  34. package/hedhog/frontend/app/enterprise/_components/enterprise-students-tab.tsx.ejs +7 -5
  35. package/hedhog/frontend/app/enterprise/page.tsx.ejs +106 -54
  36. package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +79 -59
  37. package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +92 -26
  38. package/hedhog/frontend/app/instructors/page.tsx.ejs +4 -2
  39. package/hedhog/frontend/messages/en.json +619 -13
  40. package/hedhog/frontend/messages/pt.json +619 -13
  41. package/package.json +7 -7
  42. package/src/instructor/instructor.service.ts +22 -19
  43. package/hedhog/frontend/app/_components/create-lms-instructor-sheet.tsx.ejs +0 -591
  44. package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +0 -109
  45. package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +0 -60
  46. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +0 -134
  47. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +0 -113
  48. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +0 -314
  49. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +0 -174
  50. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +0 -185
  51. package/hedhog/frontend/app/enterprise/_components/enterprise-mocks.ts.ejs +0 -277
  52. package/hedhog/frontend/app/enterprise/_components/enterprise-user-create-sheet.tsx.ejs +0 -207
@@ -1,277 +0,0 @@
1
- import type {
2
- EnterpriseAccount,
3
- EnterpriseClass,
4
- EnterpriseCourse,
5
- EnterpriseUser,
6
- } from './enterprise-types';
7
-
8
- // ── CRM Accounts (picker options) ─────────────────────────────────────────────
9
-
10
- export const MOCK_CRM_ACCOUNTS = [
11
- { id: 101, name: 'Techcorp Brasil Ltda' },
12
- { id: 102, name: 'Grupo Atlas S.A.' },
13
- { id: 103, name: 'Horizonte Engenharia Ltda' },
14
- { id: 104, name: 'MedPlus Saúde S.A.' },
15
- { id: 105, name: 'Agro Prime Comércio Ltda' },
16
- { id: 106, name: 'LogTech Transportes Ltda' },
17
- { id: 107, name: 'Inova Tech S.A.' },
18
- { id: 108, name: 'Dinâmica Consultoria Ltda' },
19
- ];
20
-
21
- // ── Accounts ───────────────────────────────────────────────────────────────────
22
-
23
- export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
24
- {
25
- id: 1,
26
- name: 'Techcorp Brasil',
27
- slug: 'techcorp-brasil',
28
- status: 'active',
29
- crmAccountId: 101,
30
- crmAccountName: 'Techcorp Brasil Ltda',
31
- portalEnabled: true,
32
- usersCount: 120,
33
- studentsCount: 104,
34
- managersCount: 14,
35
- adminsCount: 2,
36
- coursesCount: 8,
37
- classesCount: 3,
38
- licenseLimit: 150,
39
- notes: null,
40
- createdAt: '2026-01-01T10:00:00Z',
41
- updatedAt: '2026-04-10T08:30:00Z',
42
- },
43
- {
44
- id: 2,
45
- name: 'Grupo Financeiro Atlas',
46
- slug: 'grupo-financeiro-atlas',
47
- status: 'active',
48
- crmAccountId: 102,
49
- crmAccountName: 'Grupo Atlas S.A.',
50
- portalEnabled: true,
51
- usersCount: 250,
52
- studentsCount: 220,
53
- managersCount: 28,
54
- adminsCount: 2,
55
- coursesCount: 14,
56
- classesCount: 5,
57
- licenseLimit: 300,
58
- notes: null,
59
- createdAt: '2026-02-01T09:00:00Z',
60
- updatedAt: '2026-04-15T11:00:00Z',
61
- },
62
- {
63
- id: 3,
64
- name: 'Construtora Horizonte',
65
- slug: 'construtora-horizonte',
66
- status: 'active',
67
- crmAccountId: null,
68
- crmAccountName: null,
69
- portalEnabled: false,
70
- usersCount: 60,
71
- studentsCount: 52,
72
- managersCount: 6,
73
- adminsCount: 1,
74
- coursesCount: 4,
75
- classesCount: 2,
76
- licenseLimit: 80,
77
- notes: null,
78
- createdAt: '2026-03-01T08:00:00Z',
79
- updatedAt: '2026-04-01T09:00:00Z',
80
- },
81
- {
82
- id: 4,
83
- name: 'MedPlus Saúde',
84
- slug: 'medplus-saude',
85
- status: 'trial',
86
- crmAccountId: 104,
87
- crmAccountName: 'MedPlus Saúde S.A.',
88
- portalEnabled: true,
89
- usersCount: 30,
90
- studentsCount: 28,
91
- managersCount: 2,
92
- adminsCount: 1,
93
- coursesCount: 3,
94
- classesCount: 1,
95
- licenseLimit: 50,
96
- notes: null,
97
- createdAt: '2026-04-01T11:00:00Z',
98
- updatedAt: '2026-04-18T14:00:00Z',
99
- },
100
- {
101
- id: 5,
102
- name: 'Agro Prime',
103
- slug: 'agro-prime',
104
- status: 'inactive',
105
- crmAccountId: null,
106
- crmAccountName: null,
107
- portalEnabled: false,
108
- usersCount: 0,
109
- studentsCount: 0,
110
- managersCount: 0,
111
- adminsCount: 0,
112
- coursesCount: 0,
113
- classesCount: 0,
114
- licenseLimit: null,
115
- notes: null,
116
- createdAt: '2025-09-01T14:00:00Z',
117
- updatedAt: '2026-02-28T18:00:00Z',
118
- },
119
- {
120
- id: 6,
121
- name: 'LogTech Transportes',
122
- slug: 'logtech-transportes',
123
- status: 'active',
124
- crmAccountId: 106,
125
- crmAccountName: 'LogTech Transportes Ltda',
126
- portalEnabled: true,
127
- usersCount: 100,
128
- studentsCount: 88,
129
- managersCount: 10,
130
- adminsCount: 2,
131
- coursesCount: 6,
132
- classesCount: 2,
133
- licenseLimit: 120,
134
- notes: null,
135
- createdAt: '2026-01-15T09:30:00Z',
136
- updatedAt: '2026-04-12T10:00:00Z',
137
- },
138
- ];
139
-
140
- // ── Users (linked to account id=1) ─────────────────────────────────────────────
141
-
142
- export const MOCK_ENTERPRISE_USERS: EnterpriseUser[] = [
143
- {
144
- id: 1,
145
- userId: 201,
146
- name: 'Ana Beatriz Souza',
147
- email: 'ana.souza@techcorp.com.br',
148
- role: 'enterprise_admin',
149
- status: 'active',
150
- lastAccessAt: '2026-04-20T14:32:00Z',
151
- },
152
- {
153
- id: 2,
154
- userId: 202,
155
- name: 'Carlos Eduardo Lima',
156
- email: 'carlos.lima@techcorp.com.br',
157
- role: 'hr_manager',
158
- status: 'active',
159
- lastAccessAt: '2026-04-19T09:15:00Z',
160
- },
161
- {
162
- id: 3,
163
- userId: 203,
164
- name: 'Fernanda Oliveira',
165
- email: 'fernanda.oliveira@techcorp.com.br',
166
- role: 'student',
167
- status: 'active',
168
- lastAccessAt: '2026-04-18T16:00:00Z',
169
- },
170
- {
171
- id: 4,
172
- userId: 204,
173
- name: 'Ricardo Mendes',
174
- email: 'ricardo.mendes@techcorp.com.br',
175
- role: 'student',
176
- status: 'active',
177
- lastAccessAt: '2026-04-17T11:45:00Z',
178
- },
179
- {
180
- id: 5,
181
- userId: 205,
182
- name: 'Juliana Castro',
183
- email: 'juliana.castro@techcorp.com.br',
184
- role: 'viewer',
185
- status: 'inactive',
186
- lastAccessAt: null,
187
- },
188
- {
189
- id: 6,
190
- userId: 206,
191
- name: 'Marcos Vinicius Santos',
192
- email: 'marcos.santos@techcorp.com.br',
193
- role: 'student',
194
- status: 'pending',
195
- lastAccessAt: null,
196
- },
197
- ];
198
-
199
- // ── Courses (linked to account id=1) ──────────────────────────────────────────
200
-
201
- export const MOCK_ENTERPRISE_COURSES: EnterpriseCourse[] = [
202
- {
203
- id: 10,
204
- title: 'Liderança e Gestão de Equipes',
205
- slug: 'lideranca-gestao-equipes',
206
- status: 'published',
207
- modality: 'Online',
208
- enrolledCount: 45,
209
- completionRate: 72,
210
- contractedAt: '2026-01-05T00:00:00Z',
211
- },
212
- {
213
- id: 11,
214
- title: 'Compliance e Ética Corporativa',
215
- slug: 'compliance-etica-corporativa',
216
- status: 'published',
217
- modality: 'Híbrido',
218
- enrolledCount: 104,
219
- completionRate: 88,
220
- contractedAt: '2026-01-05T00:00:00Z',
221
- },
222
- {
223
- id: 12,
224
- title: 'Segurança da Informação',
225
- slug: 'seguranca-informacao',
226
- status: 'published',
227
- modality: 'Online',
228
- enrolledCount: 98,
229
- completionRate: 61,
230
- contractedAt: '2026-02-01T00:00:00Z',
231
- },
232
- {
233
- id: 13,
234
- title: 'Agile & Scrum na Prática',
235
- slug: 'agile-scrum-pratica',
236
- status: 'draft',
237
- modality: 'Presencial',
238
- enrolledCount: 0,
239
- completionRate: 0,
240
- contractedAt: '2026-03-10T00:00:00Z',
241
- },
242
- ];
243
-
244
- // ── Classes / Turmas (linked to account id=1) ──────────────────────────────────
245
-
246
- export const MOCK_ENTERPRISE_CLASSES: EnterpriseClass[] = [
247
- {
248
- id: 20,
249
- code: 'T2026-LG-01',
250
- courseTitle: 'Liderança e Gestão de Equipes',
251
- startDate: '2026-03-01',
252
- endDate: '2026-06-30',
253
- enrolledCount: 45,
254
- capacity: 50,
255
- status: 'ongoing',
256
- },
257
- {
258
- id: 21,
259
- code: 'T2026-CE-01',
260
- courseTitle: 'Compliance e Ética Corporativa',
261
- startDate: '2026-01-10',
262
- endDate: '2026-04-10',
263
- enrolledCount: 104,
264
- capacity: 120,
265
- status: 'completed',
266
- },
267
- {
268
- id: 22,
269
- code: 'T2026-SI-01',
270
- courseTitle: 'Segurança da Informação',
271
- startDate: '2026-04-15',
272
- endDate: null,
273
- enrolledCount: 98,
274
- capacity: 100,
275
- status: 'open',
276
- },
277
- ];
@@ -1,207 +0,0 @@
1
- 'use client';
2
-
3
- import { Button } from '@/components/ui/button';
4
- import {
5
- Form,
6
- FormControl,
7
- FormDescription,
8
- FormField,
9
- FormItem,
10
- FormLabel,
11
- FormMessage,
12
- } from '@/components/ui/form';
13
- import { Input } from '@/components/ui/input';
14
- import {
15
- Select,
16
- SelectContent,
17
- SelectItem,
18
- SelectTrigger,
19
- SelectValue,
20
- } from '@/components/ui/select';
21
- import {
22
- Sheet,
23
- SheetContent,
24
- SheetFooter,
25
- SheetHeader,
26
- SheetTitle,
27
- } from '@/components/ui/sheet';
28
- import { zodResolver } from '@hookform/resolvers/zod';
29
- import { Loader2 } from 'lucide-react';
30
- import { useEffect } from 'react';
31
- import { useForm } from 'react-hook-form';
32
- import { z } from 'zod';
33
- import type { EnterpriseUser, EnterpriseUserRole } from './enterprise-types';
34
-
35
- // ── Schema ─────────────────────────────────────────────────────────────────────
36
-
37
- const userCreateSchema = z.object({
38
- name: z.string().trim().min(1, 'Name is required.'),
39
- email: z
40
- .string()
41
- .trim()
42
- .min(1, 'Email is required.')
43
- .email('Enter a valid email address.'),
44
- role: z.enum(['student', 'hr_manager', 'enterprise_admin', 'viewer']),
45
- });
46
-
47
- type UserCreateValues = z.infer<typeof userCreateSchema>;
48
-
49
- const DEFAULT_VALUES: UserCreateValues = {
50
- name: '',
51
- email: '',
52
- role: 'student',
53
- };
54
-
55
- // ── Props ─────────────────────────────────────────────────────────────────────
56
-
57
- export interface EnterpriseUserCreateSheetProps {
58
- open: boolean;
59
- onOpenChange: (open: boolean) => void;
60
- onCreated?: (user: EnterpriseUser) => void;
61
- }
62
-
63
- // ── Component ─────────────────────────────────────────────────────────────────
64
-
65
- export function EnterpriseUserCreateSheet({
66
- open,
67
- onOpenChange,
68
- onCreated,
69
- }: EnterpriseUserCreateSheetProps) {
70
- const form = useForm<UserCreateValues>({
71
- resolver: zodResolver(userCreateSchema),
72
- defaultValues: DEFAULT_VALUES,
73
- });
74
-
75
- // Reset form whenever the sheet closes
76
- useEffect(() => {
77
- if (!open) {
78
- form.reset(DEFAULT_VALUES);
79
- }
80
- }, [open, form]);
81
-
82
- function handleOpenChange(nextOpen: boolean) {
83
- if (!nextOpen) form.reset(DEFAULT_VALUES);
84
- onOpenChange(nextOpen);
85
- }
86
-
87
- async function onSubmit(values: UserCreateValues) {
88
- // Optimistic mock creation — replace with real API call when available
89
- const newUser: EnterpriseUser = {
90
- id: Date.now(),
91
- userId: Date.now() + 1,
92
- name: values.name,
93
- email: values.email,
94
- role: values.role as EnterpriseUserRole,
95
- status: 'pending',
96
- lastAccessAt: null,
97
- };
98
- onCreated?.(newUser);
99
- handleOpenChange(false);
100
- }
101
-
102
- const saving = form.formState.isSubmitting;
103
-
104
- return (
105
- <Sheet open={open} onOpenChange={handleOpenChange}>
106
- <SheetContent side="right" className="flex flex-col gap-0 sm:max-w-md">
107
- <SheetHeader className="border-b px-6 py-4">
108
- <SheetTitle>New user</SheetTitle>
109
- </SheetHeader>
110
-
111
- <Form {...form}>
112
- <form
113
- onSubmit={form.handleSubmit(onSubmit)}
114
- className="flex flex-1 flex-col overflow-hidden"
115
- >
116
- <div className="flex-1 space-y-5 overflow-y-auto px-6 py-5">
117
- {/* Name */}
118
- <FormField
119
- control={form.control}
120
- name="name"
121
- render={({ field }) => (
122
- <FormItem>
123
- <FormLabel>Full name</FormLabel>
124
- <FormControl>
125
- <Input placeholder="e.g. Ana Beatriz Souza" {...field} />
126
- </FormControl>
127
- <FormMessage />
128
- </FormItem>
129
- )}
130
- />
131
-
132
- {/* Email */}
133
- <FormField
134
- control={form.control}
135
- name="email"
136
- render={({ field }) => (
137
- <FormItem>
138
- <FormLabel>Email</FormLabel>
139
- <FormControl>
140
- <Input
141
- type="email"
142
- placeholder="user@company.com"
143
- {...field}
144
- />
145
- </FormControl>
146
- <FormDescription>
147
- An invite will be sent to this address.
148
- </FormDescription>
149
- <FormMessage />
150
- </FormItem>
151
- )}
152
- />
153
-
154
- {/* Role */}
155
- <FormField
156
- control={form.control}
157
- name="role"
158
- render={({ field }) => (
159
- <FormItem>
160
- <FormLabel>Role</FormLabel>
161
- <Select value={field.value} onValueChange={field.onChange}>
162
- <FormControl>
163
- <SelectTrigger className="w-full">
164
- <SelectValue placeholder="Select a role" />
165
- </SelectTrigger>
166
- </FormControl>
167
- <SelectContent>
168
- <SelectItem value="enterprise_admin">
169
- Admin — full account management
170
- </SelectItem>
171
- <SelectItem value="hr_manager">
172
- HR / Manager — manages learners and reports
173
- </SelectItem>
174
- <SelectItem value="student">
175
- Student — access to assigned courses
176
- </SelectItem>
177
- <SelectItem value="viewer">
178
- Viewer — read-only access
179
- </SelectItem>
180
- </SelectContent>
181
- </Select>
182
- <FormMessage />
183
- </FormItem>
184
- )}
185
- />
186
- </div>
187
-
188
- <SheetFooter className="border-t px-6 py-4">
189
- <Button
190
- type="button"
191
- variant="outline"
192
- onClick={() => handleOpenChange(false)}
193
- disabled={saving}
194
- >
195
- Cancel
196
- </Button>
197
- <Button type="submit" disabled={saving}>
198
- {saving && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
199
- Create user
200
- </Button>
201
- </SheetFooter>
202
- </form>
203
- </Form>
204
- </SheetContent>
205
- </Sheet>
206
- );
207
- }