@hed-hog/lms 0.0.305 → 0.0.309

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 (130) hide show
  1. package/dist/course/course-structure.controller.d.ts +60 -0
  2. package/dist/course/course-structure.controller.d.ts.map +1 -1
  3. package/dist/course/course-structure.controller.js +79 -0
  4. package/dist/course/course-structure.controller.js.map +1 -1
  5. package/dist/course/course-structure.service.d.ts +61 -1
  6. package/dist/course/course-structure.service.d.ts.map +1 -1
  7. package/dist/course/course-structure.service.js +326 -1
  8. package/dist/course/course-structure.service.js.map +1 -1
  9. package/dist/course/course.controller.d.ts +52 -4
  10. package/dist/course/course.controller.d.ts.map +1 -1
  11. package/dist/course/course.service.d.ts +52 -5
  12. package/dist/course/course.service.d.ts.map +1 -1
  13. package/dist/course/course.service.js +81 -60
  14. package/dist/course/course.service.js.map +1 -1
  15. package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
  16. package/dist/course/dto/create-course-structure-lesson.dto.js +5 -1
  17. package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
  18. package/dist/course/dto/create-course.dto.d.ts +1 -1
  19. package/dist/course/dto/create-course.dto.d.ts.map +1 -1
  20. package/dist/course/dto/create-course.dto.js +4 -1
  21. package/dist/course/dto/create-course.dto.js.map +1 -1
  22. package/dist/course/dto/move-lesson.dto.d.ts +10 -0
  23. package/dist/course/dto/move-lesson.dto.d.ts.map +1 -0
  24. package/dist/{enterprise/dto/add-enterprise-lead.dto.js → course/dto/move-lesson.dto.js} +12 -6
  25. package/dist/course/dto/move-lesson.dto.js.map +1 -0
  26. package/dist/course/dto/paste-lessons.dto.d.ts +4 -0
  27. package/dist/course/dto/paste-lessons.dto.d.ts.map +1 -0
  28. package/dist/course/dto/paste-lessons.dto.js +24 -0
  29. package/dist/course/dto/paste-lessons.dto.js.map +1 -0
  30. package/dist/course/dto/reorder-lessons.dto.d.ts +5 -0
  31. package/dist/course/dto/reorder-lessons.dto.d.ts.map +1 -0
  32. package/dist/course/dto/reorder-lessons.dto.js +24 -0
  33. package/dist/course/dto/reorder-lessons.dto.js.map +1 -0
  34. package/dist/course/dto/reorder-sessions.dto.d.ts +5 -0
  35. package/dist/course/dto/reorder-sessions.dto.d.ts.map +1 -0
  36. package/dist/course/dto/reorder-sessions.dto.js +24 -0
  37. package/dist/course/dto/reorder-sessions.dto.js.map +1 -0
  38. package/dist/training/training.controller.js +1 -1
  39. package/dist/training/training.controller.js.map +1 -1
  40. package/hedhog/data/dashboard_component.yaml +152 -152
  41. package/hedhog/data/dashboard_item.yaml +166 -166
  42. package/hedhog/data/image_type.yaml +20 -0
  43. package/hedhog/data/menu.yaml +2 -2
  44. package/hedhog/data/route.yaml +60 -6
  45. package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +146 -165
  46. package/hedhog/frontend/app/_components/course-avatar.tsx.ejs +70 -0
  47. package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +372 -22
  48. package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +437 -77
  49. package/hedhog/frontend/app/classes/page.tsx.ejs +311 -289
  50. package/hedhog/frontend/app/courses/[id]/_components/CourseCertificateCard.tsx.ejs +10 -7
  51. package/hedhog/frontend/app/courses/[id]/_components/CourseClassificationCard.tsx.ejs +23 -32
  52. package/hedhog/frontend/app/courses/[id]/_components/CourseContentCard.tsx.ejs +3 -9
  53. package/hedhog/frontend/app/courses/[id]/_components/CourseDangerZoneCard.tsx.ejs +26 -16
  54. package/hedhog/frontend/app/courses/[id]/_components/CourseFlagsCard.tsx.ejs +19 -5
  55. package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +10 -14
  56. package/hedhog/frontend/app/courses/[id]/_components/CourseMediaCard.tsx.ejs +131 -107
  57. package/hedhog/frontend/app/courses/[id]/_components/CourseRelationsCard.tsx.ejs +10 -7
  58. package/hedhog/frontend/app/courses/[id]/_components/CourseSectionCard.tsx.ejs +38 -19
  59. package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +1 -1
  60. package/hedhog/frontend/app/courses/[id]/_components/course-edit-types.ts.ejs +1 -1
  61. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +336 -1057
  62. package/hedhog/frontend/app/courses/[id]/structure/_components/confirm-dialog.tsx.ejs +45 -0
  63. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +362 -0
  64. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-panel.tsx.ejs +111 -0
  65. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-skeleton.tsx.ejs +64 -0
  66. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +134 -0
  67. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +113 -0
  68. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +314 -0
  69. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +62 -0
  70. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +174 -0
  71. package/hedhog/frontend/app/courses/[id]/structure/_components/drag-handle.tsx.ejs +58 -0
  72. package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +52 -0
  73. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +276 -0
  74. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +1216 -0
  75. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +1827 -0
  76. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-session.tsx.ejs +443 -0
  77. package/hedhog/frontend/app/courses/[id]/structure/_components/highlighted-text.tsx.ejs +41 -0
  78. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +184 -0
  79. package/hedhog/frontend/app/courses/[id]/structure/_components/multi-select-bar.tsx.ejs +264 -0
  80. package/hedhog/frontend/app/courses/[id]/structure/_components/search-filter.tsx.ejs +96 -0
  81. package/hedhog/frontend/app/courses/[id]/structure/_components/session-picker-dialog.tsx.ejs +74 -0
  82. package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +136 -0
  83. package/hedhog/frontend/app/courses/[id]/structure/_components/sortable-tree-row.tsx.ejs +80 -0
  84. package/hedhog/frontend/app/courses/[id]/structure/_components/store.ts.ejs +948 -0
  85. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-context-menu.tsx.ejs +525 -0
  86. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +150 -0
  87. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-helpers.ts.ejs +182 -0
  88. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-course.tsx.ejs +52 -0
  89. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +271 -0
  90. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-session.tsx.ejs +167 -0
  91. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row.tsx.ejs +108 -0
  92. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +122 -0
  93. package/hedhog/frontend/app/courses/[id]/structure/_components/use-course-structure-shortcuts.ts.ejs +318 -0
  94. package/hedhog/frontend/app/courses/[id]/structure/_components/use-tree-display-settings.ts.ejs +97 -0
  95. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +347 -0
  96. package/hedhog/frontend/app/courses/[id]/structure/_data/course-structure-contract.ts.ejs +195 -0
  97. package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +420 -0
  98. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +254 -0
  99. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +987 -0
  100. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-query.ts.ejs +86 -0
  101. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure.ts.ejs +160 -0
  102. package/hedhog/frontend/app/courses/[id]/structure/page.tsx.ejs +10 -3212
  103. package/hedhog/frontend/app/courses/page.tsx.ejs +45 -26
  104. package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +317 -317
  105. package/hedhog/frontend/app/enterprise/_components/enterprise-class-create-sheet.tsx.ejs +1 -0
  106. package/hedhog/frontend/app/enterprise/_components/enterprise-mocks.ts.ejs +12 -1
  107. package/hedhog/frontend/app/enterprise/_components/enterprise-related-tab.tsx.ejs +44 -7
  108. package/hedhog/frontend/app/enterprise/_components/enterprise-types.ts.ejs +96 -96
  109. package/hedhog/frontend/app/page.tsx.ejs +5 -5
  110. package/hedhog/frontend/app/{training → paths}/page.tsx.ejs +29 -7
  111. package/hedhog/frontend/messages/en.json +88 -10
  112. package/hedhog/frontend/messages/pt.json +88 -10
  113. package/hedhog/table/course.yaml +16 -16
  114. package/hedhog/table/image_type.yaml +14 -0
  115. package/package.json +6 -6
  116. package/src/class-group/class-group.service.ts +413 -413
  117. package/src/class-group/dto/create-class-group.dto.ts +77 -77
  118. package/src/course/course-structure.controller.ts +63 -0
  119. package/src/course/course-structure.service.ts +390 -3
  120. package/src/course/course.service.ts +214 -182
  121. package/src/course/dto/create-course-structure-lesson.dto.ts +3 -2
  122. package/src/course/dto/create-course.dto.ts +19 -16
  123. package/src/course/dto/move-lesson.dto.ts +17 -0
  124. package/src/course/dto/paste-lessons.dto.ts +9 -0
  125. package/src/course/dto/reorder-lessons.dto.ts +10 -0
  126. package/src/course/dto/reorder-sessions.dto.ts +10 -0
  127. package/src/training/training.controller.ts +1 -1
  128. package/dist/enterprise/dto/add-enterprise-lead.dto.d.ts +0 -4
  129. package/dist/enterprise/dto/add-enterprise-lead.dto.d.ts.map +0 -1
  130. package/dist/enterprise/dto/add-enterprise-lead.dto.js.map +0 -1
@@ -32,9 +32,11 @@ export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
32
32
  usersCount: 120,
33
33
  studentsCount: 104,
34
34
  managersCount: 14,
35
+ adminsCount: 2,
35
36
  coursesCount: 8,
36
37
  classesCount: 3,
37
38
  licenseLimit: 150,
39
+ notes: null,
38
40
  createdAt: '2026-01-01T10:00:00Z',
39
41
  updatedAt: '2026-04-10T08:30:00Z',
40
42
  },
@@ -49,9 +51,11 @@ export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
49
51
  usersCount: 250,
50
52
  studentsCount: 220,
51
53
  managersCount: 28,
54
+ adminsCount: 2,
52
55
  coursesCount: 14,
53
56
  classesCount: 5,
54
57
  licenseLimit: 300,
58
+ notes: null,
55
59
  createdAt: '2026-02-01T09:00:00Z',
56
60
  updatedAt: '2026-04-15T11:00:00Z',
57
61
  },
@@ -66,9 +70,11 @@ export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
66
70
  usersCount: 60,
67
71
  studentsCount: 52,
68
72
  managersCount: 6,
73
+ adminsCount: 1,
69
74
  coursesCount: 4,
70
75
  classesCount: 2,
71
76
  licenseLimit: 80,
77
+ notes: null,
72
78
  createdAt: '2026-03-01T08:00:00Z',
73
79
  updatedAt: '2026-04-01T09:00:00Z',
74
80
  },
@@ -83,9 +89,11 @@ export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
83
89
  usersCount: 30,
84
90
  studentsCount: 28,
85
91
  managersCount: 2,
92
+ adminsCount: 1,
86
93
  coursesCount: 3,
87
94
  classesCount: 1,
88
95
  licenseLimit: 50,
96
+ notes: null,
89
97
  createdAt: '2026-04-01T11:00:00Z',
90
98
  updatedAt: '2026-04-18T14:00:00Z',
91
99
  },
@@ -100,9 +108,11 @@ export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
100
108
  usersCount: 0,
101
109
  studentsCount: 0,
102
110
  managersCount: 0,
111
+ adminsCount: 0,
103
112
  coursesCount: 0,
104
113
  classesCount: 0,
105
114
  licenseLimit: null,
115
+ notes: null,
106
116
  createdAt: '2025-09-01T14:00:00Z',
107
117
  updatedAt: '2026-02-28T18:00:00Z',
108
118
  },
@@ -117,9 +127,11 @@ export const MOCK_ENTERPRISE_ACCOUNTS: EnterpriseAccount[] = [
117
127
  usersCount: 100,
118
128
  studentsCount: 88,
119
129
  managersCount: 10,
130
+ adminsCount: 2,
120
131
  coursesCount: 6,
121
132
  classesCount: 2,
122
133
  licenseLimit: 120,
134
+ notes: null,
123
135
  createdAt: '2026-01-15T09:30:00Z',
124
136
  updatedAt: '2026-04-12T10:00:00Z',
125
137
  },
@@ -263,4 +275,3 @@ export const MOCK_ENTERPRISE_CLASSES: EnterpriseClass[] = [
263
275
  status: 'open',
264
276
  },
265
277
  ];
266
-
@@ -117,17 +117,54 @@ export function RelatedTabToolbar<TOption extends object>({
117
117
  <div className="flex flex-wrap items-center gap-2">
118
118
  <EntityPicker<TOption & Record<string, unknown>>
119
119
  value={pickerValue}
120
- onChange={onPickerChange}
120
+ onChange={
121
+ onPickerChange as (
122
+ v: EntityPickerValue,
123
+ o: (TOption & Record<string, unknown>) | null
124
+ ) => void
125
+ }
121
126
  placeholder={pickerPlaceholder}
122
127
  entityLabel={pickerEntityLabel}
123
128
  showCreateButton={false}
124
129
  clearable
125
- loadOptions={loadPickerOptions}
126
- options={pickerOptions}
127
- getOptionValue={getPickerOptionValue}
128
- getOptionLabel={getPickerOptionLabel}
129
- getOptionDescription={getPickerOptionDescription}
130
- renderOption={renderPickerOption}
130
+ loadOptions={
131
+ loadPickerOptions as
132
+ | ((args: {
133
+ page: number;
134
+ pageSize: number;
135
+ search: string;
136
+ }) => Promise<
137
+ | EntityPickerLoadResult<TOption & Record<string, unknown>>
138
+ | (TOption & Record<string, unknown>)[]
139
+ >)
140
+ | undefined
141
+ }
142
+ options={
143
+ pickerOptions as (TOption & Record<string, unknown>)[] | undefined
144
+ }
145
+ getOptionValue={
146
+ getPickerOptionValue as (
147
+ o: TOption & Record<string, unknown>
148
+ ) => string | number | null | undefined
149
+ }
150
+ getOptionLabel={
151
+ getPickerOptionLabel as (
152
+ o: TOption & Record<string, unknown>
153
+ ) => string
154
+ }
155
+ getOptionDescription={
156
+ getPickerOptionDescription as
157
+ | ((o: TOption & Record<string, unknown>) => string | undefined)
158
+ | undefined
159
+ }
160
+ renderOption={
161
+ renderPickerOption as
162
+ | ((args: {
163
+ option: TOption & Record<string, unknown>;
164
+ isSelected: boolean;
165
+ }) => ReactNode)
166
+ | undefined
167
+ }
131
168
  buttonClassName="min-w-52 max-w-64"
132
169
  />
133
170
 
@@ -1,96 +1,96 @@
1
- // ── Primitive union types ──────────────────────────────────────────────────────
2
-
3
- export type EnterpriseStatus = 'active' | 'inactive' | 'suspended' | 'trial';
4
-
5
- export type EnterpriseUserRole =
6
- | 'hr_manager'
7
- | 'enterprise_admin'
8
- | 'viewer'
9
- | 'student';
10
-
11
- export type EnterpriseUserStatus = 'active' | 'inactive' | 'pending';
12
-
13
- // ── View models ────────────────────────────────────────────────────────────────
14
-
15
- export interface EnterpriseCrmAccount {
16
- id: number;
17
- name: string;
18
- tradeName: string | null;
19
- industry: string | null;
20
- website: string | null;
21
- lifecycleStage: string | null;
22
- }
23
-
24
- export interface EnterpriseAccount {
25
- id: number;
26
- name: string;
27
- slug: string;
28
- status: EnterpriseStatus;
29
- crmAccountId: number | null;
30
- crmAccountName: string | null;
31
- crmAccount?: EnterpriseCrmAccount | null;
32
- portalEnabled: boolean;
33
- usersCount: number;
34
- studentsCount: number;
35
- managersCount: number;
36
- adminsCount: number;
37
- coursesCount: number;
38
- classesCount: number;
39
- licenseLimit: number | null;
40
- notes: string | null;
41
- createdAt: string;
42
- updatedAt: string;
43
- }
44
-
45
- export interface EnterpriseUser {
46
- id: number;
47
- userId: number;
48
- name: string;
49
- email: string;
50
- role: EnterpriseUserRole;
51
- status: EnterpriseUserStatus;
52
- lastAccessAt: string | null;
53
- }
54
-
55
- export interface EnterpriseStudent {
56
- id: number;
57
- personId: number;
58
- name: string | null;
59
- email: string | null;
60
- status: EnterpriseUserStatus;
61
- createdAt: string | null;
62
- }
63
-
64
- export type EnterpriseCourseStatus = 'published' | 'draft' | 'archived';
65
- export type EnterpriseClassStatus =
66
- | 'open'
67
- | 'ongoing'
68
- | 'completed'
69
- | 'cancelled';
70
-
71
- export interface EnterpriseCourse {
72
- id: number;
73
- courseId?: number;
74
- title: string;
75
- slug: string | null;
76
- status: EnterpriseCourseStatus;
77
- level?: string | null;
78
- modality?: string;
79
- contractedAt?: string | null;
80
- enrolledCount: number;
81
- completionRate: number;
82
- }
83
-
84
- export interface EnterpriseClass {
85
- id: number;
86
- courseClassGroupId?: number;
87
- code: string | null;
88
- title?: string | null;
89
- courseTitle: string | null;
90
- startDate: string | null;
91
- endDate: string | null;
92
- capacity: number | null;
93
- enrolledCount: number;
94
- status: EnterpriseClassStatus;
95
- deliveryMode?: string | null;
96
- }
1
+ // ── Primitive union types ──────────────────────────────────────────────────────
2
+
3
+ export type EnterpriseStatus = 'active' | 'inactive' | 'suspended' | 'trial';
4
+
5
+ export type EnterpriseUserRole =
6
+ | 'hr_manager'
7
+ | 'enterprise_admin'
8
+ | 'viewer'
9
+ | 'student';
10
+
11
+ export type EnterpriseUserStatus = 'active' | 'inactive' | 'pending';
12
+
13
+ // ── View models ────────────────────────────────────────────────────────────────
14
+
15
+ export interface EnterpriseCrmAccount {
16
+ id: number;
17
+ name: string;
18
+ tradeName: string | null;
19
+ industry: string | null;
20
+ website: string | null;
21
+ lifecycleStage: string | null;
22
+ }
23
+
24
+ export interface EnterpriseAccount {
25
+ id: number;
26
+ name: string;
27
+ slug: string;
28
+ status: EnterpriseStatus;
29
+ crmAccountId: number | null;
30
+ crmAccountName: string | null;
31
+ crmAccount?: EnterpriseCrmAccount | null;
32
+ portalEnabled: boolean;
33
+ usersCount: number;
34
+ studentsCount: number;
35
+ managersCount: number;
36
+ adminsCount: number;
37
+ coursesCount: number;
38
+ classesCount: number;
39
+ licenseLimit: number | null;
40
+ notes: string | null;
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ }
44
+
45
+ export interface EnterpriseUser {
46
+ id: number;
47
+ userId: number;
48
+ name: string;
49
+ email: string;
50
+ role: EnterpriseUserRole;
51
+ status: EnterpriseUserStatus;
52
+ lastAccessAt: string | null;
53
+ }
54
+
55
+ export interface EnterpriseStudent {
56
+ id: number;
57
+ personId: number;
58
+ name: string | null;
59
+ email: string | null;
60
+ status: EnterpriseUserStatus;
61
+ createdAt: string | null;
62
+ }
63
+
64
+ export type EnterpriseCourseStatus = 'published' | 'draft' | 'archived';
65
+ export type EnterpriseClassStatus =
66
+ | 'open'
67
+ | 'ongoing'
68
+ | 'completed'
69
+ | 'cancelled';
70
+
71
+ export interface EnterpriseCourse {
72
+ id: number;
73
+ courseId?: number;
74
+ title: string;
75
+ slug: string | null;
76
+ status: EnterpriseCourseStatus;
77
+ level?: string | null;
78
+ modality?: string;
79
+ contractedAt?: string | null;
80
+ enrolledCount: number;
81
+ completionRate: number;
82
+ }
83
+
84
+ export interface EnterpriseClass {
85
+ id: number;
86
+ courseClassGroupId?: number;
87
+ code: string | null;
88
+ title?: string | null;
89
+ courseTitle: string | null;
90
+ startDate: string | null;
91
+ endDate: string | null;
92
+ capacity: number | null;
93
+ enrolledCount: number;
94
+ status: EnterpriseClassStatus;
95
+ deliveryMode?: string | null;
96
+ }
@@ -1,5 +1,5 @@
1
- import { redirect } from 'next/navigation';
2
-
3
- export default function LmsPage() {
4
- redirect('/lms/courses');
5
- }
1
+ import { redirect } from 'next/navigation';
2
+
3
+ export default function LmsPage() {
4
+ redirect('/lms/courses');
5
+ }
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { CourseAvatar } from '@/app/(app)/(libraries)/lms/_components/course-avatar';
3
4
  import {
4
5
  CourseCategoryOption,
5
6
  CourseFormSheet,
@@ -141,6 +142,8 @@ interface CursoOption {
141
142
  cargaHoraria: number;
142
143
  categories: string[];
143
144
  area: string;
145
+ name?: string;
146
+ logoFileId?: number | null;
144
147
  }
145
148
 
146
149
  interface ExameOption {
@@ -188,6 +191,8 @@ type ApiCourseListResponse = {
188
191
  title: string;
189
192
  durationHours: number;
190
193
  categories?: string[];
194
+ name?: string;
195
+ logoFileId?: number | null;
191
196
  }>;
192
197
  };
193
198
 
@@ -590,7 +595,7 @@ export default function TrainingPage() {
590
595
  ],
591
596
  queryFn: async () => {
592
597
  const response = await request<ApiTrainingListResponse>({
593
- url: '/lms/training',
598
+ url: '/lms/paths',
594
599
  method: 'GET',
595
600
  params: {
596
601
  page: currentPage,
@@ -613,7 +618,7 @@ export default function TrainingPage() {
613
618
  queryKey: ['lms-training-stats'],
614
619
  queryFn: async () => {
615
620
  const response = await request<ApiTrainingStatsResponse>({
616
- url: '/lms/training/stats',
621
+ url: '/lms/paths/stats',
617
622
  method: 'GET',
618
623
  });
619
624
 
@@ -708,6 +713,8 @@ export default function TrainingPage() {
708
713
  cargaHoraria: course.durationHours ?? 0,
709
714
  categories: course.categories ?? [],
710
715
  area: categorySlugToArea(course.categories ?? []),
716
+ name: course.name,
717
+ logoFileId: course.logoFileId ?? null,
711
718
  })
712
719
  );
713
720
 
@@ -975,7 +982,7 @@ export default function TrainingPage() {
975
982
  try {
976
983
  const [response] = await Promise.all([
977
984
  request<Formacao>({
978
- url: `/lms/training/${formacao.id}`,
985
+ url: `/lms/paths/${formacao.id}`,
979
986
  method: 'GET',
980
987
  }),
981
988
  refetchCourses(),
@@ -1220,7 +1227,7 @@ export default function TrainingPage() {
1220
1227
  }
1221
1228
 
1222
1229
  await request({
1223
- url: `/lms/training/${editingFormacao.id}`,
1230
+ url: `/lms/paths/${editingFormacao.id}`,
1224
1231
  method: 'PATCH',
1225
1232
  data: payload,
1226
1233
  });
@@ -1243,7 +1250,7 @@ export default function TrainingPage() {
1243
1250
  };
1244
1251
 
1245
1252
  await request({
1246
- url: '/lms/training',
1253
+ url: '/lms/paths',
1247
1254
  method: 'POST',
1248
1255
  data: payload,
1249
1256
  });
@@ -1334,7 +1341,7 @@ export default function TrainingPage() {
1334
1341
  if (!formacaoToDelete) return;
1335
1342
 
1336
1343
  await request({
1337
- url: `/lms/training/${formacaoToDelete.id}`,
1344
+ url: `/lms/paths/${formacaoToDelete.id}`,
1338
1345
  method: 'DELETE',
1339
1346
  });
1340
1347
 
@@ -2054,7 +2061,22 @@ export default function TrainingPage() {
2054
2061
  key={course.id}
2055
2062
  value={String(course.id)}
2056
2063
  >
2057
- {course.nome} ({course.cargaHoraria}h)
2064
+ <div className="flex items-center gap-2">
2065
+ <CourseAvatar
2066
+ fileId={course.logoFileId}
2067
+ title={course.nome}
2068
+ className="size-5 shrink-0 rounded"
2069
+ iconSize="size-3"
2070
+ />
2071
+ <div className="min-w-0">
2072
+ <span className="truncate">
2073
+ {course.nome}
2074
+ </span>
2075
+ <span className="ml-1.5 text-xs text-muted-foreground">
2076
+ {course.name ?? '—'} · #{course.id}
2077
+ </span>
2078
+ </div>
2079
+ </div>
2058
2080
  </SelectItem>
2059
2081
  ))}
2060
2082
  </SelectContent>
@@ -526,15 +526,15 @@
526
526
  "edit": "Update the course information below."
527
527
  },
528
528
  "fields": {
529
- "code": {
530
- "label": "Course Code",
531
- "placeholder": "Ex: REACT-ADV",
532
- "description": "Unique course identifier (e.g.: REACT-ADV)"
533
- },
534
529
  "internalName": {
535
530
  "label": "Internal Name",
536
- "placeholder": "Ex: react-advanced",
537
- "description": "Internal slug for system use"
531
+ "placeholder": "Ex: Advanced React",
532
+ "description": "Internal course name for administrative use"
533
+ },
534
+ "slug": {
535
+ "label": "Slug",
536
+ "placeholder": "Ex: advanced-react",
537
+ "description": "Unique URL identifier (lowercase letters, numbers and hyphens)"
538
538
  },
539
539
  "commercialTitle": {
540
540
  "label": "Commercial Title",
@@ -596,6 +596,7 @@
596
596
  "codeMaxLength": "Code must have at most 16 characters",
597
597
  "codePattern": "Only letters, numbers, and hyphens",
598
598
  "internalNameMinLength": "Internal name must have at least 3 characters",
599
+ "slugPattern": "Slug must contain only lowercase letters, numbers and hyphens",
599
600
  "commercialTitleMinLength": "Commercial title must have at least 3 characters",
600
601
  "descriptionMinLength": "Description must have at least 10 characters",
601
602
  "levelRequired": "Select a level",
@@ -666,7 +667,8 @@
666
667
  "autoSaveSaved": "Session saved automatically",
667
668
  "autoSaveError": "Automatic session save failed",
668
669
  "create": "Create Session",
669
- "update": "Update"
670
+ "update": "Update",
671
+ "save": "Save session"
670
672
  },
671
673
  "lessonForm": {
672
674
  "titleCreate": "New Lesson",
@@ -736,7 +738,25 @@
736
738
  "autoSaveError": "Automatic save failed",
737
739
  "cancel": "Cancel",
738
740
  "create": "Create Lesson",
739
- "update": "Update"
741
+ "update": "Update",
742
+ "save": "Save lesson",
743
+ "tabData": "Data",
744
+ "tabTranscription": "Transcription",
745
+ "tabResources": "Resources",
746
+ "videoProvider": "Video provider",
747
+ "videoUrl": "Video URL",
748
+ "autoDuration": "Auto duration",
749
+ "postContent": "Content",
750
+ "linkedExam": "Linked exam",
751
+ "linkedExamPlaceholder": "Exam ID...",
752
+ "transcriptionHint": "Full video transcription.",
753
+ "transcriptionVideoOnly": "Transcription is only available for video lessons.",
754
+ "transcriptionPlaceholder": "Write or paste the transcription here...",
755
+ "resourcesCount": "{count} resource(s)",
756
+ "addResource": "Add resource",
757
+ "noResources": "No resources added",
758
+ "public": "Public",
759
+ "private": "Private"
740
760
  },
741
761
  "deleteSession": {
742
762
  "title": "Delete Session",
@@ -799,9 +819,13 @@
799
819
  "sessionUpdated": "Session updated!",
800
820
  "sessionCreated": "Session created!",
801
821
  "sessionDeleted": "Session removed!",
822
+ "sessionDuplicated": "Session duplicated!",
802
823
  "lessonUpdated": "Lesson updated!",
803
824
  "lessonCreated": "Lesson created!",
804
825
  "lessonDeleted": "Lesson removed!",
826
+ "lessonDuplicated": "Lesson duplicated!",
827
+ "lessonMoved": "Lesson moved!",
828
+ "courseUpdated": "Course updated!",
805
829
  "resourceAdded": "Resource added!",
806
830
  "resourceRemoved": "Resource removed!",
807
831
  "lessonsDeleted": "{count} lesson(s) removed!",
@@ -828,6 +852,56 @@
828
852
  "titleMin": "Title must be at least 3 characters",
829
853
  "durationMin": "Minimum duration of 1 minute",
830
854
  "typeRequired": "Select a type"
855
+ },
856
+ "pageDescription": "{sessions} sessions · {lessons} lessons · {hours}h {minutes}min",
857
+ "mobileTabs": {
858
+ "tree": "Tree",
859
+ "detail": "Details"
860
+ },
861
+ "breadcrumbs": {
862
+ "lms": "LMS",
863
+ "courses": "Courses",
864
+ "structure": "Structure"
865
+ },
866
+ "search": {
867
+ "placeholder": "Search..."
868
+ },
869
+ "tree": {
870
+ "collapseAll": "Collapse all",
871
+ "expandAll": "Expand all",
872
+ "addItem": "Add item",
873
+ "addSession": "New session"
874
+ },
875
+ "contextMenu": {
876
+ "edit": "Edit",
877
+ "addLesson": "Add lesson",
878
+ "addSession": "New session",
879
+ "duplicate": "Duplicate",
880
+ "mergeWith": "Merge with...",
881
+ "moveTo": "Move to...",
882
+ "delete": "Delete"
883
+ },
884
+ "deleteDialog": {
885
+ "title": "Confirm deletion",
886
+ "sessionMessage": "Are you sure? All lessons in this session will be removed.",
887
+ "lessonMessage": "Are you sure? This lesson will be permanently removed.",
888
+ "cancel": "Cancel",
889
+ "confirm": "Delete"
890
+ },
891
+ "detailPanel": {
892
+ "emptyHint": "Select an item in the tree to view details"
893
+ },
894
+ "detailCourse": {
895
+ "subtitle": "General course data",
896
+ "title": "Title",
897
+ "code": "Code",
898
+ "slug": "Slug",
899
+ "description": "Description",
900
+ "published": "Published",
901
+ "save": "Save course"
902
+ },
903
+ "detailSession": {
904
+ "subtitle": "{lessons} lessons · {minutes}min"
831
905
  }
832
906
  }
833
907
  },
@@ -2434,7 +2508,11 @@
2434
2508
  "helper": "Click a lesson to edit it or create new lessons.",
2435
2509
  "viewSingle": "Month",
2436
2510
  "viewQuarter": "Quarter",
2437
- "viewYear": "Year"
2511
+ "viewYear": "Year",
2512
+ "empty": {
2513
+ "title": "No lessons registered",
2514
+ "description": "Add the first lesson to get started."
2515
+ }
2438
2516
  },
2439
2517
  "info": {
2440
2518
  "period": "Period",