@hed-hog/lms 0.0.365 → 0.0.370

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/dist/certificate/certificate.controller.d.ts +1 -1
  2. package/dist/certificate/certificate.controller.d.ts.map +1 -1
  3. package/dist/certificate/certificate.controller.js +4 -2
  4. package/dist/certificate/certificate.controller.js.map +1 -1
  5. package/dist/certificate/certificate.service.d.ts +50 -0
  6. package/dist/certificate/certificate.service.d.ts.map +1 -1
  7. package/dist/certificate/certificate.service.js +73 -0
  8. package/dist/certificate/certificate.service.js.map +1 -1
  9. package/dist/class-group/class-group.controller.d.ts +1 -0
  10. package/dist/class-group/class-group.controller.d.ts.map +1 -1
  11. package/dist/class-group/class-group.service.d.ts +1 -0
  12. package/dist/class-group/class-group.service.d.ts.map +1 -1
  13. package/dist/course/course-ai-usage.service.d.ts +58 -0
  14. package/dist/course/course-ai-usage.service.d.ts.map +1 -0
  15. package/dist/course/course-ai-usage.service.js +176 -0
  16. package/dist/course/course-ai-usage.service.js.map +1 -0
  17. package/dist/course/course-audio-transcription.service.d.ts +65 -1
  18. package/dist/course/course-audio-transcription.service.d.ts.map +1 -1
  19. package/dist/course/course-audio-transcription.service.js +381 -29
  20. package/dist/course/course-audio-transcription.service.js.map +1 -1
  21. package/dist/course/course-export-scorm12.service.d.ts +3 -0
  22. package/dist/course/course-export-scorm12.service.d.ts.map +1 -1
  23. package/dist/course/course-export-scorm12.service.js +141 -6
  24. package/dist/course/course-export-scorm12.service.js.map +1 -1
  25. package/dist/course/course-export.service.d.ts.map +1 -1
  26. package/dist/course/course-export.service.js +2 -1
  27. package/dist/course/course-export.service.js.map +1 -1
  28. package/dist/course/course-lesson.controller.d.ts +25 -3
  29. package/dist/course/course-lesson.controller.d.ts.map +1 -1
  30. package/dist/course/course-lesson.controller.js +71 -8
  31. package/dist/course/course-lesson.controller.js.map +1 -1
  32. package/dist/course/course-structure.controller.d.ts +30 -7
  33. package/dist/course/course-structure.controller.d.ts.map +1 -1
  34. package/dist/course/course-structure.controller.js +37 -4
  35. package/dist/course/course-structure.controller.js.map +1 -1
  36. package/dist/course/course-structure.service.d.ts +37 -5
  37. package/dist/course/course-structure.service.d.ts.map +1 -1
  38. package/dist/course/course-structure.service.js +165 -20
  39. package/dist/course/course-structure.service.js.map +1 -1
  40. package/dist/course/course-transcription-translation.service.d.ts +31 -0
  41. package/dist/course/course-transcription-translation.service.d.ts.map +1 -0
  42. package/dist/course/course-transcription-translation.service.js +227 -0
  43. package/dist/course/course-transcription-translation.service.js.map +1 -0
  44. package/dist/course/course-video-agent-pipeline.service.d.ts +70 -0
  45. package/dist/course/course-video-agent-pipeline.service.d.ts.map +1 -0
  46. package/dist/course/course-video-agent-pipeline.service.js +398 -0
  47. package/dist/course/course-video-agent-pipeline.service.js.map +1 -0
  48. package/dist/course/course-video-hls.service.d.ts +14 -0
  49. package/dist/course/course-video-hls.service.d.ts.map +1 -1
  50. package/dist/course/course-video-hls.service.js +25 -8
  51. package/dist/course/course-video-hls.service.js.map +1 -1
  52. package/dist/course/course.controller.d.ts +2 -0
  53. package/dist/course/course.controller.d.ts.map +1 -1
  54. package/dist/course/course.module.d.ts.map +1 -1
  55. package/dist/course/course.module.js +9 -0
  56. package/dist/course/course.module.js.map +1 -1
  57. package/dist/course/course.service.d.ts +2 -0
  58. package/dist/course/course.service.d.ts.map +1 -1
  59. package/dist/course/course.service.js +36 -2
  60. package/dist/course/course.service.js.map +1 -1
  61. package/dist/course/dto/create-course-bulk-job.dto.d.ts +2 -1
  62. package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -1
  63. package/dist/course/dto/create-course-bulk-job.dto.js +6 -1
  64. package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -1
  65. package/dist/course/dto/create-course-export.dto.d.ts +1 -0
  66. package/dist/course/dto/create-course-export.dto.d.ts.map +1 -1
  67. package/dist/course/dto/create-course-export.dto.js +6 -0
  68. package/dist/course/dto/create-course-export.dto.js.map +1 -1
  69. package/dist/course/ffmpeg.util.d.ts +10 -0
  70. package/dist/course/ffmpeg.util.d.ts.map +1 -0
  71. package/dist/course/ffmpeg.util.js +79 -0
  72. package/dist/course/ffmpeg.util.js.map +1 -0
  73. package/dist/course/lms-bulk-upload-automation.service.d.ts +3 -1
  74. package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
  75. package/dist/course/lms-bulk-upload-automation.service.js +33 -16
  76. package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
  77. package/dist/course/lms-bulk-upload.controller.d.ts +3 -0
  78. package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
  79. package/dist/course/lms-bulk-upload.service.d.ts +3 -0
  80. package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
  81. package/dist/course/lms-bulk-upload.service.js +48 -29
  82. package/dist/course/lms-bulk-upload.service.js.map +1 -1
  83. package/dist/course/subtitle.util.d.ts +46 -0
  84. package/dist/course/subtitle.util.d.ts.map +1 -0
  85. package/dist/course/subtitle.util.js +206 -0
  86. package/dist/course/subtitle.util.js.map +1 -0
  87. package/dist/enterprise/training/training-admin.controller.d.ts +2 -0
  88. package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
  89. package/dist/enterprise/training/training-admin.service.d.ts +2 -0
  90. package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
  91. package/dist/enterprise/training/training-student.service.d.ts +27 -0
  92. package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
  93. package/dist/enterprise/training/training-student.service.js +197 -10
  94. package/dist/enterprise/training/training-student.service.js.map +1 -1
  95. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +3 -1
  96. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -1
  97. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +19 -5
  98. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
  99. package/dist/lesson-xp-map/lesson-xp-map.module.d.ts.map +1 -1
  100. package/dist/lesson-xp-map/lesson-xp-map.module.js +2 -1
  101. package/dist/lesson-xp-map/lesson-xp-map.module.js.map +1 -1
  102. package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
  103. package/dist/lms.module.d.ts.map +1 -1
  104. package/dist/lms.module.js +14 -0
  105. package/dist/lms.module.js.map +1 -1
  106. package/dist/platforma/dto/heartbeat.dto.d.ts +9 -0
  107. package/dist/platforma/dto/heartbeat.dto.d.ts.map +1 -0
  108. package/dist/platforma/dto/heartbeat.dto.js +50 -0
  109. package/dist/platforma/dto/heartbeat.dto.js.map +1 -0
  110. package/dist/platforma/handlers/emit-certificate.handler.d.ts +27 -0
  111. package/dist/platforma/handlers/emit-certificate.handler.d.ts.map +1 -0
  112. package/dist/platforma/handlers/emit-certificate.handler.js +117 -0
  113. package/dist/platforma/handlers/emit-certificate.handler.js.map +1 -0
  114. package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts +31 -0
  115. package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts.map +1 -0
  116. package/dist/platforma/handlers/lesson-heartbeat.handler.js +281 -0
  117. package/dist/platforma/handlers/lesson-heartbeat.handler.js.map +1 -0
  118. package/dist/platforma/platforma-heartbeat.service.d.ts +10 -0
  119. package/dist/platforma/platforma-heartbeat.service.d.ts.map +1 -0
  120. package/dist/platforma/platforma-heartbeat.service.js +50 -0
  121. package/dist/platforma/platforma-heartbeat.service.js.map +1 -0
  122. package/dist/platforma/platforma-performance.service.d.ts +121 -0
  123. package/dist/platforma/platforma-performance.service.d.ts.map +1 -0
  124. package/dist/platforma/platforma-performance.service.js +500 -0
  125. package/dist/platforma/platforma-performance.service.js.map +1 -0
  126. package/dist/platforma/platforma-search.service.d.ts +21 -0
  127. package/dist/platforma/platforma-search.service.d.ts.map +1 -0
  128. package/dist/platforma/platforma-search.service.js +64 -0
  129. package/dist/platforma/platforma-search.service.js.map +1 -0
  130. package/dist/platforma/platforma-video.service.d.ts +8 -0
  131. package/dist/platforma/platforma-video.service.d.ts.map +1 -1
  132. package/dist/platforma/platforma-video.service.js +45 -2
  133. package/dist/platforma/platforma-video.service.js.map +1 -1
  134. package/dist/platforma/platforma.controller.d.ts +213 -1
  135. package/dist/platforma/platforma.controller.d.ts.map +1 -1
  136. package/dist/platforma/platforma.controller.js +159 -2
  137. package/dist/platforma/platforma.controller.js.map +1 -1
  138. package/dist/realtime/lms-realtime.controller.d.ts +2 -0
  139. package/dist/realtime/lms-realtime.controller.d.ts.map +1 -1
  140. package/dist/realtime/lms-realtime.controller.js +31 -0
  141. package/dist/realtime/lms-realtime.controller.js.map +1 -1
  142. package/dist/realtime/lms-realtime.service.d.ts +1 -1
  143. package/dist/realtime/lms-realtime.service.d.ts.map +1 -1
  144. package/dist/realtime/lms-realtime.service.js.map +1 -1
  145. package/dist/training/dto/create-training.dto.d.ts +9 -0
  146. package/dist/training/dto/create-training.dto.d.ts.map +1 -1
  147. package/dist/training/dto/create-training.dto.js +45 -1
  148. package/dist/training/dto/create-training.dto.js.map +1 -1
  149. package/dist/training/training.controller.d.ts +144 -0
  150. package/dist/training/training.controller.d.ts.map +1 -1
  151. package/dist/training/training.service.d.ts +149 -0
  152. package/dist/training/training.service.d.ts.map +1 -1
  153. package/dist/training/training.service.js +332 -167
  154. package/dist/training/training.service.js.map +1 -1
  155. package/hedhog/data/image_type.yaml +10 -0
  156. package/hedhog/data/route.yaml +251 -0
  157. package/hedhog/data/setting_group.yaml +97 -0
  158. package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +139 -27
  159. package/hedhog/frontend/app/certificates/models/page.tsx.ejs +182 -29
  160. package/hedhog/frontend/app/classes/_components/classes-calendar-view.tsx.ejs +277 -0
  161. package/hedhog/frontend/app/classes/page.tsx.ejs +127 -20
  162. package/hedhog/frontend/app/courses/[id]/_components/CourseFlagsCard.tsx.ejs +69 -57
  163. package/hedhog/frontend/app/courses/[id]/_components/CourseIssuedCertificatesCard.tsx.ejs +168 -0
  164. package/hedhog/frontend/app/courses/[id]/structure/_components/course-ai-costs-tab.tsx.ejs +191 -0
  165. package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +81 -1
  166. package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +12 -0
  167. package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +141 -30
  168. package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +13 -13
  169. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +69 -1
  170. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +11 -23
  171. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +267 -19
  172. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +114 -86
  173. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +239 -31
  174. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +344 -59
  175. package/hedhog/frontend/app/courses/[id]/structure/_components/lesson-video-preview.tsx.ejs +200 -0
  176. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +1 -0
  177. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +3 -0
  178. package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +1 -8
  179. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +19 -7
  180. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -0
  181. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-ai-costs.ts.ejs +40 -0
  182. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +2 -0
  183. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +25 -0
  184. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +148 -0
  185. package/hedhog/frontend/app/courses/[id]/structure/_data/use-transcription-segments.ts.ejs +157 -8
  186. package/hedhog/frontend/app/courses/_components/CourseRowActions.tsx.ejs +1 -22
  187. package/hedhog/frontend/app/courses/page.tsx.ejs +66 -13
  188. package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +6 -0
  189. package/hedhog/frontend/app/enterprise/_components/enterprise-classes-calendar-tab.tsx.ejs +264 -0
  190. package/hedhog/frontend/app/enterprise/page.tsx.ejs +104 -47
  191. package/hedhog/frontend/app/exams/page.tsx.ejs +38 -4
  192. package/hedhog/frontend/app/instructors/page.tsx.ejs +87 -46
  193. package/hedhog/frontend/app/paths/page.tsx.ejs +650 -168
  194. package/hedhog/frontend/app/training/page.tsx.ejs +38 -4
  195. package/hedhog/frontend/messages/en.json +41 -12
  196. package/hedhog/frontend/messages/pt.json +44 -13
  197. package/hedhog/query/triggers.sql +33 -0
  198. package/hedhog/table/course_ai_usage.yaml +46 -0
  199. package/hedhog/table/course_enrollment.yaml +3 -0
  200. package/hedhog/table/course_lesson.yaml +3 -0
  201. package/hedhog/table/course_lesson_answer.yaml +37 -0
  202. package/hedhog/table/course_lesson_transcription_segment.yaml +8 -0
  203. package/hedhog/table/learning_path.yaml +6 -0
  204. package/hedhog/table/learning_path_module.yaml +22 -0
  205. package/hedhog/table/learning_path_step.yaml +9 -6
  206. package/hedhog/table/lesson_view_event.yaml +66 -0
  207. package/package.json +8 -7
  208. package/src/certificate/certificate.controller.ts +2 -0
  209. package/src/certificate/certificate.service.ts +99 -0
  210. package/src/course/course-ai-usage.service.ts +221 -0
  211. package/src/course/course-audio-transcription.service.ts +471 -43
  212. package/src/course/course-export-scorm12.service.ts +149 -5
  213. package/src/course/course-export.service.ts +1 -0
  214. package/src/course/course-lesson.controller.ts +59 -6
  215. package/src/course/course-structure.controller.ts +19 -1
  216. package/src/course/course-structure.service.ts +184 -10
  217. package/src/course/course-transcription-translation.service.ts +293 -0
  218. package/src/course/course-video-agent-pipeline.service.ts +471 -0
  219. package/src/course/course-video-hls.service.ts +30 -10
  220. package/src/course/course.module.ts +9 -0
  221. package/src/course/course.service.ts +46 -1
  222. package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
  223. package/src/course/dto/create-course-export.dto.ts +6 -0
  224. package/src/course/ffmpeg.util.ts +65 -0
  225. package/src/course/lms-bulk-upload-automation.service.ts +33 -8
  226. package/src/course/lms-bulk-upload.service.ts +20 -1
  227. package/src/course/subtitle.util.ts +220 -0
  228. package/src/enterprise/training/training-student.service.ts +224 -4
  229. package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +14 -0
  230. package/src/lesson-xp-map/lesson-xp-map.module.ts +2 -1
  231. package/src/lms.module.ts +14 -0
  232. package/src/platforma/dto/heartbeat.dto.ts +30 -0
  233. package/src/platforma/handlers/emit-certificate.handler.ts +117 -0
  234. package/src/platforma/handlers/lesson-heartbeat.handler.ts +343 -0
  235. package/src/platforma/platforma-heartbeat.service.ts +33 -0
  236. package/src/platforma/platforma-performance.service.ts +606 -0
  237. package/src/platforma/platforma-search.service.ts +48 -0
  238. package/src/platforma/platforma-video.service.ts +59 -3
  239. package/src/platforma/platforma.controller.ts +130 -0
  240. package/src/realtime/lms-realtime.controller.ts +27 -1
  241. package/src/realtime/lms-realtime.service.ts +2 -1
  242. package/src/training/dto/create-training.dto.ts +36 -0
  243. package/src/training/training.service.ts +360 -163
@@ -1,15 +1,6 @@
1
1
  'use client';
2
2
 
3
- import {
4
- Eye,
5
- EyeOff,
6
- FolderInput,
7
- Layers,
8
- Lock,
9
- Save,
10
- Video,
11
- X,
12
- } from 'lucide-react';
3
+ import { FolderInput, Layers, Loader2, Save, Video, X } from 'lucide-react';
13
4
  import { useTranslations } from 'next-intl';
14
5
  import { useState } from 'react';
15
6
  import { toast } from 'sonner';
@@ -28,19 +19,13 @@ import {
28
19
  import { Separator } from '@/components/ui/separator';
29
20
  import { cn } from '@/lib/utils';
30
21
 
22
+ import {
23
+ useBulkUpdateMutation,
24
+ useMoveLessonsMutation,
25
+ } from '../_data/use-course-structure-mutations';
31
26
  import { IconActionTooltip } from './icon-action-tooltip';
32
27
  import { useStructureStore } from './store';
33
- import type { LessonStatus, Visibility } from './types';
34
-
35
- // ── Config ────────────────────────────────────────────────────────────────────
36
-
37
- const STATUS_LABELS: Record<LessonStatus, string> = {
38
- preparada: 'Preparada',
39
- gravada: 'Gravada',
40
- editada: 'Editada',
41
- finalizada: 'Finalizada',
42
- publicada: 'Publicada',
43
- };
28
+ import type { Lesson, LessonStatus } from './types';
44
29
 
45
30
  // ── Component ─────────────────────────────────────────────────────────────────
46
31
 
@@ -51,6 +36,9 @@ export function EditorBulk() {
51
36
  const lessons = useStructureStore((s) => s.lessons);
52
37
  const clearSelection = useStructureStore((s) => s.clearSelection);
53
38
 
39
+ const bulkUpdate = useBulkUpdateMutation();
40
+ const moveLessonsMutation = useMoveLessonsMutation();
41
+
54
42
  const selectedArray = [...selectedIds];
55
43
  const lessonIds = selectedArray.filter((id) =>
56
44
  lessons.some((l) => l.id === id)
@@ -62,24 +50,68 @@ export function EditorBulk() {
62
50
  const allLessons = lessonIds.length === selectedArray.length;
63
51
  const allSessions = sessionIds.length === selectedArray.length;
64
52
 
65
- // Local form state (mock not wired to store actions yet)
53
+ // Local form state — empty means "keep current" (no change applied).
66
54
  const [status, setStatus] = useState<LessonStatus | ''>('');
67
- const [visibility, setVisibility] = useState<Visibility | ''>('');
55
+ const [publish, setPublish] = useState<'publish' | 'unpublish' | ''>('');
68
56
  const [targetSession, setTargetSession] = useState<string>('');
69
57
 
58
+ const isPending = bulkUpdate.isPending || moveLessonsMutation.isPending;
59
+
60
+ function resetForm() {
61
+ setStatus('');
62
+ setPublish('');
63
+ setTargetSession('');
64
+ }
65
+
70
66
  function handleSave() {
71
- const lines: string[] = [];
72
- if (status) lines.push(`status ${STATUS_LABELS[status as LessonStatus]}`);
73
- if (visibility) lines.push(`visibilidade ${visibility}`);
74
- if (targetSession)
75
- lines.push(
76
- `mover para sessão ${sessions.find((s) => s.id === targetSession)?.title ?? targetSession}`
67
+ const changes: { published?: boolean; status?: LessonStatus } = {};
68
+ if (publish) changes.published = publish === 'publish';
69
+ // Production status only applies to lessons.
70
+ if (status && lessonIds.length > 0) changes.status = status;
71
+
72
+ const hasFieldChange =
73
+ changes.published !== undefined || changes.status !== undefined;
74
+ const hasMove = !!targetSession && lessonIds.length > 0;
75
+
76
+ if (!hasFieldChange && !hasMove) {
77
+ toast(t('toast.none'));
78
+ return;
79
+ }
80
+
81
+ if (hasFieldChange) {
82
+ bulkUpdate.mutate(
83
+ {
84
+ lessons: lessonIds.map((id) => ({
85
+ lessonId: id,
86
+ sessionId:
87
+ lessons.find((l) => l.id === id)?.sessionId ?? '',
88
+ })),
89
+ sessionIds: sessionIds.map((id) => ({ sessionId: id })),
90
+ changes,
91
+ },
92
+ { onSuccess: resetForm }
93
+ );
94
+ }
95
+
96
+ if (hasMove) {
97
+ const previousLessons = [...lessons];
98
+ const movingLessons = lessonIds
99
+ .map((id) => lessons.find((l) => l.id === id))
100
+ .filter(Boolean) as Lesson[];
101
+ const moves = movingLessons.map((l, i) => ({
102
+ lessonId: l.id,
103
+ fromSessionId: l.sessionId,
104
+ toSessionId: targetSession,
105
+ toIndex: i,
106
+ }));
107
+ // Optimistic store move (matches MultiSelectBar behaviour).
108
+ useStructureStore.getState().moveLessons(lessonIds, targetSession);
109
+ moveLessonsMutation.mutate(
110
+ { moves, previousLessons },
111
+ { onSuccess: () => setTargetSession('') }
77
112
  );
78
- toast.success(
79
- lines.length
80
- ? t('toast.preview', { changes: lines.join(', ') })
81
- : t('toast.none')
82
- );
113
+ toast.success(t('toast.moving', { count: lessonIds.length }));
114
+ }
83
115
  }
84
116
 
85
117
  return (
@@ -89,8 +121,6 @@ export function EditorBulk() {
89
121
  <div className="flex size-9 items-center justify-center rounded-lg bg-primary/10 shrink-0">
90
122
  {allLessons ? (
91
123
  <Video className="size-4 text-primary" />
92
- ) : allSessions ? (
93
- <Layers className="size-4 text-primary" />
94
124
  ) : (
95
125
  <Layers className="size-4 text-primary" />
96
126
  )}
@@ -99,7 +129,11 @@ export function EditorBulk() {
99
129
  <p className="text-sm font-semibold">{t('title')}</p>
100
130
  <p className="text-[0.65rem] text-muted-foreground">
101
131
  {selectedIds.size}{' '}
102
- {allLessons ? t('types.lessons') : allSessions ? t('types.sessions') : t('types.items')}{' '}
132
+ {allLessons
133
+ ? t('types.lessons')
134
+ : allSessions
135
+ ? t('types.sessions')
136
+ : t('types.items')}{' '}
103
137
  {t('types.selected')}
104
138
  </p>
105
139
  </div>
@@ -143,11 +177,36 @@ export function EditorBulk() {
143
177
  })}
144
178
  {selectedArray.length > 12 && (
145
179
  <Badge variant="outline" className="text-[0.65rem] h-5">
146
- +{selectedArray.length - 12} mais
180
+ +{selectedArray.length - 12} {t('more')}
147
181
  </Badge>
148
182
  )}
149
183
  </div>
150
184
 
185
+ {/* Publicação — aplica a aulas e sessões */}
186
+ <Card>
187
+ <CardHeader className="px-3 pt-3 pb-2">
188
+ <CardTitle className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
189
+ {t('publishTitle')}
190
+ </CardTitle>
191
+ </CardHeader>
192
+ <CardContent className="px-3 pb-3">
193
+ <Select
194
+ value={publish}
195
+ onValueChange={(v) =>
196
+ setPublish(v as 'publish' | 'unpublish')
197
+ }
198
+ >
199
+ <SelectTrigger className="h-8 text-xs w-full">
200
+ <SelectValue placeholder={t('keepCurrent')} />
201
+ </SelectTrigger>
202
+ <SelectContent>
203
+ <SelectItem value="publish">{t('publish.on')}</SelectItem>
204
+ <SelectItem value="unpublish">{t('publish.off')}</SelectItem>
205
+ </SelectContent>
206
+ </Select>
207
+ </CardContent>
208
+ </Card>
209
+
151
210
  {/* Status — só mostra para aulas */}
152
211
  {(allLessons || (!allSessions && lessonIds.length > 0)) && (
153
212
  <Card>
@@ -165,55 +224,25 @@ export function EditorBulk() {
165
224
  <SelectValue placeholder={t('keepCurrent')} />
166
225
  </SelectTrigger>
167
226
  <SelectContent>
168
- <SelectItem value="preparada">{t('status.preparada')}</SelectItem>
227
+ <SelectItem value="preparada">
228
+ {t('status.preparada')}
229
+ </SelectItem>
169
230
  <SelectItem value="gravada">{t('status.gravada')}</SelectItem>
170
231
  <SelectItem value="editada">{t('status.editada')}</SelectItem>
171
- <SelectItem value="finalizada">{t('status.finalizada')}</SelectItem>
172
- <SelectItem value="publicada">{t('status.publicada')}</SelectItem>
232
+ <SelectItem value="finalizada">
233
+ {t('status.finalizada')}
234
+ </SelectItem>
235
+ <SelectItem value="publicada">
236
+ {t('status.publicada')}
237
+ </SelectItem>
173
238
  </SelectContent>
174
239
  </Select>
175
240
  </CardContent>
176
241
  </Card>
177
242
  )}
178
243
 
179
- {/* Visibilidade */}
180
- <Card>
181
- <CardHeader className="px-3 pt-3 pb-2">
182
- <CardTitle className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
183
- {t('visibilityTitle')}
184
- </CardTitle>
185
- </CardHeader>
186
- <CardContent className="px-3 pb-3">
187
- <Select
188
- value={visibility}
189
- onValueChange={(v) => setVisibility(v as Visibility)}
190
- >
191
- <SelectTrigger className="h-8 text-xs w-full">
192
- <SelectValue placeholder={t('keepCurrent')} />
193
- </SelectTrigger>
194
- <SelectContent>
195
- <SelectItem value="publico">
196
- <span className="flex items-center gap-1.5">
197
- <Eye className="size-3" /> {t('visibility.publico')}
198
- </span>
199
- </SelectItem>
200
- <SelectItem value="privado">
201
- <span className="flex items-center gap-1.5">
202
- <EyeOff className="size-3" /> {t('visibility.privado')}
203
- </span>
204
- </SelectItem>
205
- <SelectItem value="restrito">
206
- <span className="flex items-center gap-1.5">
207
- <Lock className="size-3" /> {t('visibility.restrito')}
208
- </span>
209
- </SelectItem>
210
- </SelectContent>
211
- </Select>
212
- </CardContent>
213
- </Card>
214
-
215
244
  {/* Mover para sessão — só para aulas */}
216
- {(allLessons || lessonIds.length > 0) && (
245
+ {lessonIds.length > 0 && (
217
246
  <Card>
218
247
  <CardHeader className="px-3 pt-3 pb-2">
219
248
  <CardTitle className="text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-1.5">
@@ -240,12 +269,6 @@ export function EditorBulk() {
240
269
  </CardContent>
241
270
  </Card>
242
271
  )}
243
-
244
- <div className="rounded-md border border-amber-200 bg-amber-50/60 dark:border-amber-800 dark:bg-amber-950/30 px-3 py-2">
245
- <p className="text-[0.65rem] text-amber-700 dark:text-amber-400">
246
- {t('apiNotice')}
247
- </p>
248
- </div>
249
272
  </div>
250
273
  </ScrollArea>
251
274
 
@@ -269,9 +292,14 @@ export function EditorBulk() {
269
292
  size="sm"
270
293
  className="h-7 text-xs"
271
294
  onClick={handleSave}
295
+ disabled={isPending}
272
296
  >
273
- <Save className="size-3 mr-1" />
274
- Aplicar (mock)
297
+ {isPending ? (
298
+ <Loader2 className="size-3 mr-1 animate-spin" />
299
+ ) : (
300
+ <Save className="size-3 mr-1" />
301
+ )}
302
+ {t('apply')}
275
303
  </Button>
276
304
  </div>
277
305
  </div>