@hed-hog/lms 0.0.364 → 0.0.366

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 (290) hide show
  1. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts +1 -0
  2. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -1
  3. package/dist/bitcode-wallet/bitcode-wallet.service.js +22 -3
  4. package/dist/bitcode-wallet/bitcode-wallet.service.js.map +1 -1
  5. package/dist/class-group/class-group.controller.d.ts +1 -0
  6. package/dist/class-group/class-group.controller.d.ts.map +1 -1
  7. package/dist/class-group/class-group.service.d.ts +1 -0
  8. package/dist/class-group/class-group.service.d.ts.map +1 -1
  9. package/dist/course/course-export-scorm12-worker.service.d.ts +21 -0
  10. package/dist/course/course-export-scorm12-worker.service.d.ts.map +1 -0
  11. package/dist/course/course-export-scorm12-worker.service.js +109 -0
  12. package/dist/course/course-export-scorm12-worker.service.js.map +1 -0
  13. package/dist/course/course-export-scorm12.service.d.ts +42 -0
  14. package/dist/course/course-export-scorm12.service.d.ts.map +1 -0
  15. package/dist/course/course-export-scorm12.service.js +628 -0
  16. package/dist/course/course-export-scorm12.service.js.map +1 -0
  17. package/dist/course/course-export.service.d.ts +84 -0
  18. package/dist/course/course-export.service.d.ts.map +1 -0
  19. package/dist/course/course-export.service.js +237 -0
  20. package/dist/course/course-export.service.js.map +1 -0
  21. package/dist/course/course-structure.controller.d.ts +20 -10
  22. package/dist/course/course-structure.controller.d.ts.map +1 -1
  23. package/dist/course/course-structure.controller.js +20 -4
  24. package/dist/course/course-structure.controller.js.map +1 -1
  25. package/dist/course/course-structure.service.d.ts +12 -4
  26. package/dist/course/course-structure.service.d.ts.map +1 -1
  27. package/dist/course/course-structure.service.js +98 -23
  28. package/dist/course/course-structure.service.js.map +1 -1
  29. package/dist/course/course-video-agent-pipeline.service.d.ts +70 -0
  30. package/dist/course/course-video-agent-pipeline.service.d.ts.map +1 -0
  31. package/dist/course/course-video-agent-pipeline.service.js +398 -0
  32. package/dist/course/course-video-agent-pipeline.service.js.map +1 -0
  33. package/dist/course/course-video-hls.service.d.ts +71 -0
  34. package/dist/course/course-video-hls.service.d.ts.map +1 -0
  35. package/dist/course/course-video-hls.service.js +784 -0
  36. package/dist/course/course-video-hls.service.js.map +1 -0
  37. package/dist/course/course.controller.d.ts +47 -13
  38. package/dist/course/course.controller.d.ts.map +1 -1
  39. package/dist/course/course.controller.js +40 -26
  40. package/dist/course/course.controller.js.map +1 -1
  41. package/dist/course/course.mcp-tools.js +1 -1
  42. package/dist/course/course.mcp-tools.js.map +1 -1
  43. package/dist/course/course.module.d.ts.map +1 -1
  44. package/dist/course/course.module.js +16 -0
  45. package/dist/course/course.module.js.map +1 -1
  46. package/dist/course/course.service.d.ts +8 -9
  47. package/dist/course/course.service.d.ts.map +1 -1
  48. package/dist/course/course.service.js +93 -50
  49. package/dist/course/course.service.js.map +1 -1
  50. package/dist/course/dto/cleanup-course-storage.dto.d.ts +1 -1
  51. package/dist/course/dto/cleanup-course-storage.dto.d.ts.map +1 -1
  52. package/dist/course/dto/cleanup-course-storage.dto.js +1 -0
  53. package/dist/course/dto/cleanup-course-storage.dto.js.map +1 -1
  54. package/dist/course/dto/cleanup-upload-history.dto.d.ts +1 -1
  55. package/dist/course/dto/cleanup-upload-history.dto.d.ts.map +1 -1
  56. package/dist/course/dto/cleanup-upload-history.dto.js +1 -1
  57. package/dist/course/dto/cleanup-upload-history.dto.js.map +1 -1
  58. package/dist/course/dto/create-course-bulk-job.dto.d.ts +2 -1
  59. package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -1
  60. package/dist/course/dto/create-course-bulk-job.dto.js +6 -1
  61. package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -1
  62. package/dist/course/dto/create-course-export.dto.d.ts +14 -0
  63. package/dist/course/dto/create-course-export.dto.d.ts.map +1 -0
  64. package/dist/course/dto/create-course-export.dto.js +71 -0
  65. package/dist/course/dto/create-course-export.dto.js.map +1 -0
  66. package/dist/course/dto/create-course-structure-lesson.dto.d.ts +2 -2
  67. package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
  68. package/dist/course/dto/create-course-structure-lesson.dto.js +3 -2
  69. package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
  70. package/dist/course/ffmpeg.util.d.ts +10 -0
  71. package/dist/course/ffmpeg.util.d.ts.map +1 -0
  72. package/dist/course/ffmpeg.util.js +79 -0
  73. package/dist/course/ffmpeg.util.js.map +1 -0
  74. package/dist/course/lms-bulk-upload-automation.service.d.ts +18 -1
  75. package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
  76. package/dist/course/lms-bulk-upload-automation.service.js +106 -8
  77. package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
  78. package/dist/course/lms-bulk-upload-infra.service.d.ts +1 -0
  79. package/dist/course/lms-bulk-upload-infra.service.d.ts.map +1 -1
  80. package/dist/course/lms-bulk-upload-infra.service.js +32 -8
  81. package/dist/course/lms-bulk-upload-infra.service.js.map +1 -1
  82. package/dist/course/lms-bulk-upload.controller.d.ts +30 -3
  83. package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
  84. package/dist/course/lms-bulk-upload.controller.js +43 -2
  85. package/dist/course/lms-bulk-upload.controller.js.map +1 -1
  86. package/dist/course/lms-bulk-upload.service.d.ts +11 -0
  87. package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
  88. package/dist/course/lms-bulk-upload.service.js +59 -6
  89. package/dist/course/lms-bulk-upload.service.js.map +1 -1
  90. package/dist/course/lms-setting.controller.d.ts +2 -1
  91. package/dist/course/lms-setting.controller.d.ts.map +1 -1
  92. package/dist/course/lms-setting.controller.js +4 -2
  93. package/dist/course/lms-setting.controller.js.map +1 -1
  94. package/dist/course/scorm12-schemas.d.ts +4 -0
  95. package/dist/course/scorm12-schemas.d.ts.map +1 -0
  96. package/dist/course/scorm12-schemas.js +9 -0
  97. package/dist/course/scorm12-schemas.js.map +1 -0
  98. package/dist/enterprise/training/training-admin.controller.d.ts +2 -0
  99. package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
  100. package/dist/enterprise/training/training-admin.service.d.ts +2 -0
  101. package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
  102. package/dist/enterprise/training/training-student.service.d.ts +51 -0
  103. package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
  104. package/dist/enterprise/training/training-student.service.js +217 -4
  105. package/dist/enterprise/training/training-student.service.js.map +1 -1
  106. package/dist/evaluation/evaluation.service.d.ts +18 -0
  107. package/dist/evaluation/evaluation.service.d.ts.map +1 -1
  108. package/dist/evaluation/evaluation.service.js +125 -0
  109. package/dist/evaluation/evaluation.service.js.map +1 -1
  110. package/dist/exam/dto/create-standalone-question.dto.d.ts +12 -0
  111. package/dist/exam/dto/create-standalone-question.dto.d.ts.map +1 -0
  112. package/dist/exam/dto/create-standalone-question.dto.js +70 -0
  113. package/dist/exam/dto/create-standalone-question.dto.js.map +1 -0
  114. package/dist/exam/exam.module.d.ts.map +1 -1
  115. package/dist/exam/exam.module.js +2 -1
  116. package/dist/exam/exam.module.js.map +1 -1
  117. package/dist/exam/exam.service.d.ts +21 -0
  118. package/dist/exam/exam.service.d.ts.map +1 -1
  119. package/dist/exam/exam.service.js +80 -0
  120. package/dist/exam/exam.service.js.map +1 -1
  121. package/dist/exam/question.controller.d.ts +27 -0
  122. package/dist/exam/question.controller.d.ts.map +1 -0
  123. package/dist/exam/question.controller.js +53 -0
  124. package/dist/exam/question.controller.js.map +1 -0
  125. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +4 -0
  126. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -1
  127. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +161 -25
  128. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
  129. package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
  130. package/dist/lms-commerce-access.subscriber.d.ts +11 -0
  131. package/dist/lms-commerce-access.subscriber.d.ts.map +1 -0
  132. package/dist/lms-commerce-access.subscriber.js +74 -0
  133. package/dist/lms-commerce-access.subscriber.js.map +1 -0
  134. package/dist/lms.module.d.ts.map +1 -1
  135. package/dist/lms.module.js +16 -5
  136. package/dist/lms.module.js.map +1 -1
  137. package/dist/platforma/dto/heartbeat.dto.d.ts +9 -0
  138. package/dist/platforma/dto/heartbeat.dto.d.ts.map +1 -0
  139. package/dist/platforma/dto/heartbeat.dto.js +50 -0
  140. package/dist/platforma/dto/heartbeat.dto.js.map +1 -0
  141. package/dist/platforma/handlers/emit-certificate.handler.d.ts +27 -0
  142. package/dist/platforma/handlers/emit-certificate.handler.d.ts.map +1 -0
  143. package/dist/platforma/handlers/emit-certificate.handler.js +117 -0
  144. package/dist/platforma/handlers/emit-certificate.handler.js.map +1 -0
  145. package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts +31 -0
  146. package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts.map +1 -0
  147. package/dist/platforma/handlers/lesson-heartbeat.handler.js +281 -0
  148. package/dist/platforma/handlers/lesson-heartbeat.handler.js.map +1 -0
  149. package/dist/platforma/platforma-heartbeat.service.d.ts +10 -0
  150. package/dist/platforma/platforma-heartbeat.service.d.ts.map +1 -0
  151. package/dist/platforma/platforma-heartbeat.service.js +50 -0
  152. package/dist/platforma/platforma-heartbeat.service.js.map +1 -0
  153. package/dist/platforma/platforma-performance.service.d.ts +121 -0
  154. package/dist/platforma/platforma-performance.service.d.ts.map +1 -0
  155. package/dist/platforma/platforma-performance.service.js +500 -0
  156. package/dist/platforma/platforma-performance.service.js.map +1 -0
  157. package/dist/platforma/platforma-search.service.d.ts +21 -0
  158. package/dist/platforma/platforma-search.service.d.ts.map +1 -0
  159. package/dist/platforma/platforma-search.service.js +64 -0
  160. package/dist/platforma/platforma-search.service.js.map +1 -0
  161. package/dist/platforma/platforma-video.service.d.ts +39 -0
  162. package/dist/platforma/platforma-video.service.d.ts.map +1 -0
  163. package/dist/platforma/platforma-video.service.js +301 -0
  164. package/dist/platforma/platforma-video.service.js.map +1 -0
  165. package/dist/platforma/platforma.controller.d.ts +209 -1
  166. package/dist/platforma/platforma.controller.d.ts.map +1 -1
  167. package/dist/platforma/platforma.controller.js +208 -2
  168. package/dist/platforma/platforma.controller.js.map +1 -1
  169. package/dist/realtime/lms-realtime.controller.d.ts +2 -0
  170. package/dist/realtime/lms-realtime.controller.d.ts.map +1 -1
  171. package/dist/realtime/lms-realtime.controller.js +31 -0
  172. package/dist/realtime/lms-realtime.controller.js.map +1 -1
  173. package/dist/realtime/lms-realtime.service.d.ts +1 -1
  174. package/dist/realtime/lms-realtime.service.d.ts.map +1 -1
  175. package/dist/realtime/lms-realtime.service.js.map +1 -1
  176. package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts +5 -0
  177. package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts.map +1 -0
  178. package/dist/student-xp/dto/grant-skill-card-xp.dto.js +26 -0
  179. package/dist/student-xp/dto/grant-skill-card-xp.dto.js.map +1 -0
  180. package/dist/student-xp/student-xp.controller.d.ts +15 -0
  181. package/dist/student-xp/student-xp.controller.d.ts.map +1 -1
  182. package/dist/student-xp/student-xp.controller.js +24 -0
  183. package/dist/student-xp/student-xp.controller.js.map +1 -1
  184. package/dist/student-xp/student-xp.service.d.ts +16 -0
  185. package/dist/student-xp/student-xp.service.d.ts.map +1 -1
  186. package/dist/student-xp/student-xp.service.js +51 -1
  187. package/dist/student-xp/student-xp.service.js.map +1 -1
  188. package/hedhog/data/evaluation_topic.yaml +17 -0
  189. package/hedhog/data/menu.yaml +0 -17
  190. package/hedhog/data/queue_definition.yaml +48 -0
  191. package/hedhog/data/route.yaml +94 -124
  192. package/hedhog/data/setting_group.yaml +19 -19
  193. package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +337 -41
  194. package/hedhog/frontend/app/certificates/models/page.tsx.ejs +182 -29
  195. package/hedhog/frontend/app/classes/_components/classes-calendar-view.tsx.ejs +277 -0
  196. package/hedhog/frontend/app/classes/page.tsx.ejs +127 -20
  197. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +69 -4
  198. package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +420 -0
  199. package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +308 -0
  200. package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +158 -45
  201. package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +13 -13
  202. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +11 -23
  203. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +51 -63
  204. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +8 -3
  205. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +31 -8
  206. package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +16 -9
  207. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +201 -401
  208. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +378 -690
  209. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -2
  210. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +3 -9
  211. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -1
  212. package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +1 -8
  213. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +6 -10
  214. package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +49 -0
  215. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -3
  216. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +2 -1
  217. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +106 -0
  218. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +28 -1
  219. package/hedhog/frontend/app/courses/[id]/structure/_data/use-lms-settings-query.ts.ejs +0 -2
  220. package/hedhog/frontend/app/courses/page.tsx.ejs +85 -9
  221. package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +6 -0
  222. package/hedhog/frontend/app/enterprise/_components/enterprise-classes-calendar-tab.tsx.ejs +264 -0
  223. package/hedhog/frontend/app/enterprise/page.tsx.ejs +104 -47
  224. package/hedhog/frontend/app/exams/page.tsx.ejs +38 -4
  225. package/hedhog/frontend/app/instructors/page.tsx.ejs +87 -46
  226. package/hedhog/frontend/app/paths/page.tsx.ejs +38 -4
  227. package/hedhog/frontend/app/training/page.tsx.ejs +38 -4
  228. package/hedhog/frontend/messages/en.json +44 -28
  229. package/hedhog/frontend/messages/pt.json +47 -29
  230. package/hedhog/table/course_enrollment.yaml +3 -0
  231. package/hedhog/table/course_export.yaml +62 -0
  232. package/hedhog/table/lesson_view_event.yaml +66 -0
  233. package/package.json +14 -9
  234. package/src/bitcode-wallet/bitcode-wallet.service.ts +43 -4
  235. package/src/course/course-export-scorm12-worker.service.ts +124 -0
  236. package/src/course/course-export-scorm12.service.ts +668 -0
  237. package/src/course/course-export.service.ts +280 -0
  238. package/src/course/course-structure.controller.ts +16 -2
  239. package/src/course/course-structure.service.ts +100 -7
  240. package/src/course/course-video-agent-pipeline.service.ts +471 -0
  241. package/src/course/course-video-hls.service.ts +966 -0
  242. package/src/course/course.controller.ts +33 -19
  243. package/src/course/course.mcp-tools.ts +1 -1
  244. package/src/course/course.module.ts +16 -0
  245. package/src/course/course.service.ts +119 -61
  246. package/src/course/dto/cleanup-course-storage.dto.ts +1 -0
  247. package/src/course/dto/cleanup-upload-history.dto.ts +1 -1
  248. package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
  249. package/src/course/dto/create-course-export.dto.ts +56 -0
  250. package/src/course/dto/create-course-structure-lesson.dto.ts +4 -3
  251. package/src/course/ffmpeg.util.ts +65 -0
  252. package/src/course/lms-bulk-upload-automation.service.ts +156 -6
  253. package/src/course/lms-bulk-upload-infra.service.ts +39 -6
  254. package/src/course/lms-bulk-upload.controller.ts +32 -2
  255. package/src/course/lms-bulk-upload.service.ts +70 -7
  256. package/src/course/lms-setting.controller.ts +4 -2
  257. package/src/course/scorm12-schemas.ts +9 -0
  258. package/src/enterprise/training/training-student.service.ts +221 -2
  259. package/src/evaluation/evaluation.service.ts +123 -0
  260. package/src/exam/dto/create-standalone-question.dto.ts +66 -0
  261. package/src/exam/exam.module.ts +2 -1
  262. package/src/exam/exam.service.ts +86 -0
  263. package/src/exam/question.controller.ts +28 -0
  264. package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +205 -31
  265. package/src/lms-commerce-access.subscriber.ts +88 -0
  266. package/src/lms.module.ts +16 -5
  267. package/src/platforma/dto/heartbeat.dto.ts +30 -0
  268. package/src/platforma/handlers/emit-certificate.handler.ts +117 -0
  269. package/src/platforma/handlers/lesson-heartbeat.handler.ts +343 -0
  270. package/src/platforma/platforma-heartbeat.service.ts +33 -0
  271. package/src/platforma/platforma-performance.service.ts +606 -0
  272. package/src/platforma/platforma-search.service.ts +48 -0
  273. package/src/platforma/platforma-video.service.ts +346 -0
  274. package/src/platforma/platforma.controller.ts +137 -1
  275. package/src/platforma/platforma.service.ts +268 -268
  276. package/src/realtime/lms-realtime.controller.ts +27 -1
  277. package/src/realtime/lms-realtime.service.ts +2 -1
  278. package/src/student-xp/dto/grant-skill-card-xp.dto.ts +10 -0
  279. package/src/student-xp/student-xp.controller.ts +18 -2
  280. package/src/student-xp/student-xp.service.ts +84 -2
  281. package/hedhog/data/video_resolution_profile.yaml +0 -7
  282. package/hedhog/frontend/app/video-resolution-profiles/page.tsx.ejs +0 -607
  283. package/hedhog/table/course_video_resolution_profile.yaml +0 -22
  284. package/hedhog/table/video_resolution_profile.yaml +0 -18
  285. package/src/video-resolution-profile/dto/create-video-resolution-profile.dto.ts +0 -16
  286. package/src/video-resolution-profile/dto/update-video-resolution-profile.dto.ts +0 -16
  287. package/src/video-resolution-profile/video-resolution-profile.controller.ts +0 -62
  288. package/src/video-resolution-profile/video-resolution-profile.mcp-tools.ts +0 -128
  289. package/src/video-resolution-profile/video-resolution-profile.module.ts +0 -13
  290. package/src/video-resolution-profile/video-resolution-profile.service.ts +0 -117
@@ -72,7 +72,7 @@ const TITLE_PATTERNS = [
72
72
  'Conceitos fundamentais',
73
73
  'Configuracao do ambiente',
74
74
  'Pratica guiada passo a passo',
75
- 'Exercicio: implementacao',
75
+ 'Pratica: implementacao',
76
76
  'Quiz de revisao',
77
77
  'Caso de uso real',
78
78
  'Implementacao completa',
@@ -107,7 +107,6 @@ const LESSON_TYPES: LessonType[] = [
107
107
  'video',
108
108
  'video',
109
109
  'questao',
110
- 'exercicio',
111
110
  ];
112
111
  const PROVIDERS: VideoProvider[] = [
113
112
  'youtube',
@@ -7,8 +7,8 @@ import {
7
7
  TooltipTrigger,
8
8
  } from '@/components/ui/tooltip';
9
9
  import { cn } from '@/lib/utils';
10
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
10
11
  import {
11
- ClipboardList,
12
12
  Clock3,
13
13
  Eye,
14
14
  EyeOff,
@@ -24,19 +24,18 @@ import {
24
24
  } from 'lucide-react';
25
25
  import { useTranslations } from 'next-intl';
26
26
  import { useEffect, useRef } from 'react';
27
- import { useApp, useQuery } from '@hed-hog/next-app-provider';
28
- import { useUpdateLessonMutation } from '../_data/use-course-structure-mutations';
29
27
  import {
30
28
  getQueueJob,
31
29
  type QueueJobStatus,
32
30
  } from '../_data/services/course-structure.service';
31
+ import { useUpdateLessonMutation } from '../_data/use-course-structure-mutations';
33
32
  import { HighlightedText } from './highlighted-text';
34
33
  import { useStructureStore } from './store';
35
- import type { Lesson, LessonStatus, LessonType } from './types';
36
34
  import {
37
35
  getLessonAttachedResourceCount,
38
36
  getLessonUploadedVideoCount,
39
37
  } from './tree-helpers';
38
+ import type { Lesson, LessonStatus, LessonType } from './types';
40
39
  import { useTreeDisplaySettings } from './use-tree-display-settings';
41
40
 
42
41
  // ── Type configs ──────────────────────────────────────────────────────────────
@@ -48,11 +47,6 @@ const LESSON_TYPE_CONFIG: Record<
48
47
  video: { icon: Video, color: 'text-violet-500', label: 'Vídeo' },
49
48
  post: { icon: FileText, color: 'text-emerald-500', label: 'Post' },
50
49
  questao: { icon: HelpCircle, color: 'text-amber-500', label: 'Quiz' },
51
- exercicio: {
52
- icon: ClipboardList,
53
- color: 'text-rose-500',
54
- label: 'Exercício',
55
- },
56
50
  };
57
51
 
58
52
  const STATUS_CONFIG: Record<LessonStatus, { label: string; dot: string }> = {
@@ -2,7 +2,7 @@
2
2
  // Types — LMS Course Structure TreeView
3
3
  // ─────────────────────────────────────────────────────────────────────────────
4
4
 
5
- export type LessonType = 'video' | 'questao' | 'post' | 'exercicio';
5
+ export type LessonType = 'video' | 'questao' | 'post';
6
6
  export type VideoProvider = 'youtube' | 'vimeo' | 'file_storage';
7
7
  export type ItemType = 'course' | 'session' | 'lesson';
8
8
 
@@ -11,14 +11,7 @@ export function XpHighlightPill({
11
11
  value: string;
12
12
  tone: 'sky' | 'amber' | 'emerald' | 'violet';
13
13
  }) {
14
- const toneClassName =
15
- tone === 'sky'
16
- ? 'border-sky-500/15 bg-sky-500/10 text-sky-700 dark:text-sky-300'
17
- : tone === 'amber'
18
- ? 'border-amber-500/15 bg-amber-500/10 text-amber-700 dark:text-amber-300'
19
- : tone === 'emerald'
20
- ? 'border-emerald-500/15 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300'
21
- : 'border-violet-500/15 bg-violet-500/10 text-violet-700 dark:text-violet-300';
14
+ const toneClassName = 'border-border/60 bg-muted/30 text-muted-foreground';
22
15
 
23
16
  return (
24
17
  <div
@@ -14,9 +14,8 @@
14
14
  *
15
15
  * ⚠️ KNOWN MISMATCHES (documented with inline comments):
16
16
  * 1. exameVinculado (number) ↔ linkedExam (string) — converted with String()/Number()
17
- * 2. 'exercicio' tipo exists in backend and is now part of frontend LessonType.
18
- * 3. Session.order — not returned by API; inferred from sorted array position.
19
- * 4. Resource.size / url — not returned by API; left as empty string / undefined.
17
+ * 2. Session.ordernot returned by API; inferred from sorted array position.
18
+ * 3. Resource.size / url — not returned by API; left as empty string / undefined.
20
19
  */
21
20
 
22
21
  import type {
@@ -55,7 +54,7 @@ import type {
55
54
  * Map backend lesson type to the frontend LessonType union.
56
55
  *
57
56
  * ⚠️ ADAPTER POINT:
58
- * 'exercicio' is now part of the frontend LessonType union.
57
+ * Keep this helper updated if backend introduces new lesson type aliases.
59
58
  */
60
59
  function normalizeLessonType(tipo: ApiLesson['tipo']): LessonType {
61
60
  return tipo as LessonType;
@@ -129,7 +128,7 @@ export function normalizeCourse(raw: ApiCourse): Course {
129
128
  description: raw.descricao,
130
129
  slug: raw.slug,
131
130
  offeringType: raw.offeringType,
132
- published: false,
131
+ published: raw.status === 'published',
133
132
  };
134
133
  }
135
134
 
@@ -301,9 +300,7 @@ export function toCreateLessonPayload(
301
300
  ): ApiCreateLessonPayload {
302
301
  return {
303
302
  titulo: data.title,
304
- // ⚠️ TYPE NOTE: 'exercicio' is not in the frontend LessonType but the
305
- // backend accepts it. Cast is safe as long as LessonType ⊆ ApiLesson['tipo'].
306
- tipo: data.type as ApiCreateLessonPayload['tipo'],
303
+ tipo: data.type,
307
304
  duracao: data.duration,
308
305
  published: data.published,
309
306
  statusProducao: data.status,
@@ -361,8 +358,7 @@ export function toUpdateLessonPayload(
361
358
  ): ApiUpdateLessonPayload {
362
359
  const payload: ApiUpdateLessonPayload = {};
363
360
  if (data.title !== undefined) payload.titulo = data.title;
364
- if (data.type !== undefined)
365
- payload.tipo = data.type as ApiCreateLessonPayload['tipo'];
361
+ if (data.type !== undefined) payload.tipo = data.type;
366
362
  if (data.duration !== undefined) payload.duracao = data.duration;
367
363
  if (data.published !== undefined) payload.published = data.published;
368
364
  if (data.status !== undefined) payload.statusProducao = data.status;
@@ -54,6 +54,7 @@ type RequestFn = (input: {
54
54
  data?: unknown;
55
55
  headers?: Record<string, string>;
56
56
  onUploadProgress?: (event: { loaded: number; total?: number }) => void;
57
+ showErrors?: boolean;
57
58
  }) => Promise<{ data: unknown }>;
58
59
 
59
60
  export type QueueJobStatus =
@@ -584,6 +585,7 @@ export async function getQueueJob(
584
585
  const response = await request({
585
586
  url: `/queue/jobs/${jobId}`,
586
587
  method: 'GET',
588
+ showErrors: false,
587
589
  });
588
590
  return extractData<QueueJobResponse>(response);
589
591
  }
@@ -604,3 +606,50 @@ export async function deleteFile(
604
606
  data: { ids: [fileId] },
605
607
  });
606
608
  }
609
+
610
+ // ── Questions ─────────────────────────────────────────────────────────────────
611
+
612
+ export interface ApiQuestion {
613
+ id: number;
614
+ questionType: string;
615
+ statement: string;
616
+ points: number;
617
+ subjectId: number | null;
618
+ subjectName: string | null;
619
+ }
620
+
621
+ export interface ApiQuestionListResponse {
622
+ total: number;
623
+ page: number;
624
+ limit: number;
625
+ data: ApiQuestion[];
626
+ }
627
+
628
+ export interface CreateQuestionPayload {
629
+ statement: string;
630
+ questionType?: string;
631
+ points?: number;
632
+ subjectId?: number;
633
+ explanation?: string;
634
+ alternatives?: { text: string; isCorrect: boolean }[];
635
+ fillBlankAnswers?: { answer: string; alternatives?: string[] }[];
636
+ matchingPairs?: { id: string; leftText: string; rightText: string }[];
637
+ }
638
+
639
+ export async function listQuestions(
640
+ request: RequestFn,
641
+ search?: string
642
+ ): Promise<ApiQuestionListResponse> {
643
+ const params = new URLSearchParams({ limit: '100' });
644
+ if (search?.trim()) params.set('search', search.trim());
645
+ const response = await request({ url: `/lms/questions?${params}`, method: 'GET' });
646
+ return response.data as ApiQuestionListResponse;
647
+ }
648
+
649
+ export async function createQuestion(
650
+ request: RequestFn,
651
+ dto: CreateQuestionPayload
652
+ ): Promise<ApiQuestion> {
653
+ const response = await request({ url: '/lms/questions', method: 'POST', data: dto });
654
+ return response.data as ApiQuestion;
655
+ }
@@ -65,7 +65,7 @@ export interface ApiLessonInstructor {
65
65
  * The backend maps DB lesson types to UI types in mapDbTypeToUiType():
66
66
  * DB 'video' → UI 'video'
67
67
  * DB 'text' → UI 'post'
68
- * DB 'quiz' → UI 'questao' or 'exercicio' (based on content.sourceType)
68
+ * DB 'quiz' → UI 'questao' (based on content.sourceType)
69
69
  *
70
70
  * ⚠️ BACKEND NOTE — missing fields:
71
71
  * `order` and `visibility` are NOT included in the API response.
@@ -80,7 +80,7 @@ export interface ApiLesson {
80
80
  descricaoPrivada: string;
81
81
  locale_id?: number | null;
82
82
  /** UI-level lesson type resolved by the backend service. */
83
- tipo: 'video' | 'questao' | 'post' | 'exercicio';
83
+ tipo: 'video' | 'questao' | 'post';
84
84
  /** Duration in minutes. */
85
85
  duracao: number;
86
86
  published?: boolean;
@@ -140,6 +140,7 @@ export interface ApiCourse {
140
140
  titulo: string;
141
141
  descricao: string;
142
142
  offeringType?: 'scheduled' | 'on_demand' | 'blended';
143
+ status?: 'draft' | 'published' | 'archived';
143
144
  recursos?: ApiCourseResource[];
144
145
  }
145
146
 
@@ -207,7 +208,7 @@ export interface ApiUpdateSessionPayload {
207
208
  */
208
209
  export interface ApiCreateLessonPayload {
209
210
  titulo: string;
210
- tipo: 'video' | 'questao' | 'post' | 'exercicio';
211
+ tipo: 'video' | 'questao' | 'post';
211
212
  /** Duration in minutes. */
212
213
  duracao: number;
213
214
  published?: boolean;
@@ -11,13 +11,14 @@ export type CourseContentOverview = {
11
11
  video: number;
12
12
  questao: number;
13
13
  post: number;
14
- exercicio: number;
15
14
  };
16
15
  };
17
16
  videos: {
18
17
  lessonCount: number;
19
18
  withTranscription: number;
20
19
  withXp: number;
20
+ withVideo: number;
21
+ withProcessedVideo: number;
21
22
  };
22
23
  media: {
23
24
  extractedImageCount: number;
@@ -0,0 +1,106 @@
1
+ 'use client';
2
+
3
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
4
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
5
+
6
+ export type ScormVisualSettings = {
7
+ primaryColor?: string;
8
+ fontFamily?: string;
9
+ fontSize?: string;
10
+ sidebarWidth?: number;
11
+ sidebarPosition?: string;
12
+ progressStyle?: string;
13
+ sidebarTheme?: string;
14
+ };
15
+
16
+ export type CourseExportRecord = {
17
+ id: number;
18
+ format: string;
19
+ status: 'pending' | 'processing' | 'completed' | 'failed';
20
+ settings: Record<string, unknown> | null;
21
+ duration_seconds: number | null;
22
+ error_message: string | null;
23
+ created_at: string;
24
+ finished_at: string | null;
25
+ file_id: number | null;
26
+ notification_id: number | null;
27
+ file: {
28
+ id: number;
29
+ path: string;
30
+ filename: string;
31
+ size: number | null;
32
+ } | null;
33
+ user: {
34
+ id: number;
35
+ name: string;
36
+ photo_id: number | null;
37
+ };
38
+ };
39
+
40
+ export function courseExportsQueryKey(courseId: string) {
41
+ return ['course-exports', courseId] as const;
42
+ }
43
+
44
+ export function useCourseExportsQuery(courseId: string | null) {
45
+ const { request } = useApp();
46
+
47
+ return useQuery<CourseExportRecord[]>({
48
+ queryKey: courseExportsQueryKey(courseId ?? ''),
49
+ enabled: Boolean(courseId),
50
+ queryFn: async () => {
51
+ const res = await request<CourseExportRecord[]>({
52
+ url: `/lms/courses/${courseId}/exports`,
53
+ method: 'GET',
54
+ });
55
+ return res.data ?? [];
56
+ },
57
+ initialData: [],
58
+ });
59
+ }
60
+
61
+ export function useCreateCourseExportMutation(courseId: string | null) {
62
+ const { request } = useApp();
63
+ const queryClient = useQueryClient();
64
+
65
+ return useMutation({
66
+ mutationFn: async (payload: {
67
+ format: 'scorm_1_2';
68
+ visualSettings?: ScormVisualSettings;
69
+ }) => {
70
+ const res = await request<{
71
+ exportId: number;
72
+ queueJobId: number;
73
+ notificationId: number;
74
+ }>({
75
+ url: `/lms/courses/${courseId}/exports`,
76
+ method: 'POST',
77
+ data: payload,
78
+ });
79
+ return res.data;
80
+ },
81
+ onSuccess: () => {
82
+ queryClient.invalidateQueries({
83
+ queryKey: courseExportsQueryKey(courseId ?? ''),
84
+ });
85
+ },
86
+ });
87
+ }
88
+
89
+ export function useDeleteCourseExportMutation(courseId: string | null) {
90
+ const { request } = useApp();
91
+ const queryClient = useQueryClient();
92
+
93
+ return useMutation({
94
+ mutationFn: async (exportId: number) => {
95
+ await request({
96
+ url: `/lms/courses/${courseId}/exports/${exportId}`,
97
+ method: 'DELETE',
98
+ });
99
+ },
100
+ onSuccess: () => {
101
+ queryClient.invalidateQueries({
102
+ queryKey: courseExportsQueryKey(courseId ?? ''),
103
+ });
104
+ },
105
+ });
106
+ }
@@ -20,7 +20,7 @@
20
20
  * onError: restore cache snapshot + Zustand rollback
21
21
  */
22
22
 
23
- import { useMutation, useQueryClient } from '@tanstack/react-query';
23
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
24
24
  import { useTranslations } from 'next-intl';
25
25
  import { toast } from 'sonner';
26
26
 
@@ -54,6 +54,9 @@ import {
54
54
  updateCourse as apiUpdateCourse,
55
55
  updateLesson as apiUpdateLesson,
56
56
  updateSession as apiUpdateSession,
57
+ listQuestions as apiListQuestions,
58
+ createQuestion as apiCreateQuestion,
59
+ type CreateQuestionPayload,
57
60
  } from './services/course-structure.service';
58
61
  import type { CourseStructureCacheData } from './use-course-structure-query';
59
62
  import { courseStructureQueryKey } from './use-course-structure-query';
@@ -1104,3 +1107,27 @@ export function useUpdateResourceTypeMutation() {
1104
1107
  },
1105
1108
  });
1106
1109
  }
1110
+
1111
+ // ─────────────────────────────────────────────────────────────────────────────
1112
+ // useQuestionsQuery / useCreateQuestionMutation
1113
+ // ─────────────────────────────────────────────────────────────────────────────
1114
+
1115
+ export function useQuestionsQuery(search?: string) {
1116
+ const { request } = useApp();
1117
+ return useQuery({
1118
+ queryKey: ['lms-questions', search ?? ''],
1119
+ queryFn: () => apiListQuestions(request, search),
1120
+ staleTime: 30_000,
1121
+ });
1122
+ }
1123
+
1124
+ export function useCreateQuestionMutation() {
1125
+ const { request } = useApp();
1126
+ const queryClient = useQueryClient();
1127
+ return useMutation({
1128
+ mutationFn: (dto: CreateQuestionPayload) => apiCreateQuestion(request, dto),
1129
+ onSuccess: () => {
1130
+ void queryClient.invalidateQueries({ queryKey: ['lms-questions'] });
1131
+ },
1132
+ });
1133
+ }
@@ -3,7 +3,6 @@
3
3
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
4
4
 
5
5
  export interface LmsFeatureFlags {
6
- videoConversionEnabled: boolean;
7
6
  imageExtractionEnabled: boolean;
8
7
  transcriptionEnabled: boolean;
9
8
  youtubeEnabled: boolean;
@@ -11,7 +10,6 @@ export interface LmsFeatureFlags {
11
10
  }
12
11
 
13
12
  const DEFAULT_FLAGS: LmsFeatureFlags = {
14
- videoConversionEnabled: true,
15
13
  imageExtractionEnabled: true,
16
14
  transcriptionEnabled: true,
17
15
  youtubeEnabled: true,
@@ -95,6 +95,7 @@ interface Curso {
95
95
  criadoEm: string;
96
96
  logoFileId?: number | null;
97
97
  operationsProjectId?: number | null;
98
+ processando?: boolean;
98
99
  }
99
100
 
100
101
  type ApiCourse = {
@@ -122,6 +123,7 @@ type ApiCourse = {
122
123
  createdAt: string;
123
124
  logoFileId?: number | null;
124
125
  operationsProjectId?: number | null;
126
+ hasRunningJobs?: boolean;
125
127
  };
126
128
 
127
129
  type ApiCourseList = {
@@ -238,6 +240,7 @@ function mapApiCourse(course: ApiCourse): Curso {
238
240
  criadoEm: course.createdAt ?? '',
239
241
  logoFileId: course.logoFileId ?? null,
240
242
  operationsProjectId: course.operationsProjectId ?? null,
243
+ processando: course.hasRunningJobs ?? false,
241
244
  };
242
245
  }
243
246
 
@@ -315,7 +318,7 @@ const OFFERING_TYPE_COLOR: Record<string, string> = {
315
318
  hibrido: 'bg-teal-50 text-teal-700 border-teal-200',
316
319
  };
317
320
 
318
- const PAGE_SIZES = [6, 12, 24] as const;
321
+ const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
319
322
 
320
323
  // ── Seed Data ─────────────────────────────────────────────────────────────────
321
324
 
@@ -385,10 +388,44 @@ export default function CursosPage() {
385
388
 
386
389
  // Pagination
387
390
  const [currentPage, setCurrentPage] = useState(1);
391
+
392
+ const { data: generalSettings } = useQuery<{
393
+ data: Array<{ slug: string; value: string }>;
394
+ }>({
395
+ queryKey: ['setting-group-general'],
396
+ queryFn: async () => {
397
+ const response = await request<{
398
+ data: Array<{ slug: string; value: string }>;
399
+ }>({
400
+ url: '/setting/group/general',
401
+ method: 'GET',
402
+ });
403
+ return response.data;
404
+ },
405
+ staleTime: 5 * 60 * 1000,
406
+ });
407
+
408
+ const pageSizeOptions = useMemo(() => {
409
+ const setting = generalSettings?.data?.find(
410
+ (s) => s.slug === 'pagination-page-sizes'
411
+ );
412
+ if (!setting?.value) return DEFAULT_PAGE_SIZES;
413
+ try {
414
+ const parsed = JSON.parse(setting.value) as string[];
415
+ const sizes = parsed
416
+ .map(Number)
417
+ .filter((n) => !isNaN(n) && n > 0)
418
+ .sort((a, b) => a - b);
419
+ return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
420
+ } catch {
421
+ return DEFAULT_PAGE_SIZES;
422
+ }
423
+ }, [generalSettings]);
424
+
388
425
  const [pageSize, setPageSize] = usePersistedPageSize({
389
426
  storageKey: 'pagination:global:pageSize',
390
427
  defaultValue: 12,
391
- allowedValues: PAGE_SIZES,
428
+ allowedValues: pageSizeOptions,
392
429
  });
393
430
 
394
431
  const form = useForm<CourseSheetFormValues>({
@@ -1088,7 +1125,7 @@ export default function CursosPage() {
1088
1125
  ],
1089
1126
  },
1090
1127
  ]}
1091
- afterSearchButton={
1128
+ actions={
1092
1129
  <ViewModeToggle
1093
1130
  viewMode={viewMode}
1094
1131
  onViewModeChange={setViewMode}
@@ -1289,12 +1326,9 @@ export default function CursosPage() {
1289
1326
  />
1290
1327
  ) : (
1291
1328
  <div className="relative">
1292
- {cardsRefreshing && (
1293
- <div className="absolute inset-0 z-10 rounded-2xl bg-background/55 backdrop-blur-[1px]" />
1294
- )}
1295
1329
  {viewMode === 'cards' ? (
1296
1330
  <motion.div
1297
- className={`grid gap-4 sm:grid-cols-2 lg:grid-cols-3 ${cardsRefreshing ? 'pointer-events-none' : ''}`}
1331
+ className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"
1298
1332
  variants={stagger}
1299
1333
  initial="hidden"
1300
1334
  animate="show"
@@ -1405,6 +1439,27 @@ export default function CursosPage() {
1405
1439
  </Badge>
1406
1440
  </motion.div>
1407
1441
  )}
1442
+ {curso.processando &&
1443
+ !deletingCourseIds.has(curso.id) && (
1444
+ <motion.div
1445
+ initial={{ opacity: 0, scale: 0.8 }}
1446
+ animate={{ opacity: 1, scale: 1 }}
1447
+ exit={{ opacity: 0, scale: 0.8 }}
1448
+ transition={{
1449
+ type: 'spring',
1450
+ stiffness: 300,
1451
+ damping: 30,
1452
+ }}
1453
+ >
1454
+ <Badge
1455
+ variant="secondary"
1456
+ className="gap-1 rounded-full px-2 py-0.5 text-[10px]"
1457
+ >
1458
+ <Loader2 className="size-2.5 animate-spin" />
1459
+ Processando...
1460
+ </Badge>
1461
+ </motion.div>
1462
+ )}
1408
1463
  </div>
1409
1464
  </div>
1410
1465
  </div>
@@ -1440,7 +1495,7 @@ export default function CursosPage() {
1440
1495
  </motion.div>
1441
1496
  ) : (
1442
1497
  <div
1443
- className={`overflow-hidden rounded-xl border border-border/70 ${cardsRefreshing ? 'pointer-events-none' : ''}`}
1498
+ className="overflow-hidden rounded-xl border border-border/70"
1444
1499
  >
1445
1500
  <Table>
1446
1501
  <TableHeader>
@@ -1554,6 +1609,27 @@ export default function CursosPage() {
1554
1609
  </Badge>
1555
1610
  </motion.div>
1556
1611
  )}
1612
+ {curso.processando &&
1613
+ !deletingCourseIds.has(curso.id) && (
1614
+ <motion.div
1615
+ initial={{ opacity: 0, scale: 0.8 }}
1616
+ animate={{ opacity: 1, scale: 1 }}
1617
+ exit={{ opacity: 0, scale: 0.8 }}
1618
+ transition={{
1619
+ type: 'spring',
1620
+ stiffness: 300,
1621
+ damping: 30,
1622
+ }}
1623
+ >
1624
+ <Badge
1625
+ variant="secondary"
1626
+ className="gap-1 text-[11px]"
1627
+ >
1628
+ <Loader2 className="size-2.5 animate-spin" />
1629
+ Processando...
1630
+ </Badge>
1631
+ </motion.div>
1632
+ )}
1557
1633
  {curso.destaque && (
1558
1634
  <span className="inline-flex items-center gap-1 rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-[11px] font-medium text-amber-700">
1559
1635
  <Star className="size-3 fill-amber-400 text-amber-400" />
@@ -1627,7 +1703,7 @@ export default function CursosPage() {
1627
1703
  setPageSize(nextPageSize);
1628
1704
  setCurrentPage(1);
1629
1705
  }}
1630
- pageSizeOptions={PAGE_SIZES}
1706
+ pageSizeOptions={pageSizeOptions}
1631
1707
  selectedCount={selectedIds.size}
1632
1708
  />
1633
1709
  </div>
@@ -25,6 +25,7 @@ import { notFound, useParams, useRouter } from 'next/navigation';
25
25
  import { useState } from 'react';
26
26
  import { AdministratorsTab } from '../_components/enterprise-administrators-tab';
27
27
  import { ClassesTab } from '../_components/enterprise-classes-tab';
28
+ import { ClassesCalendarTab } from '../_components/enterprise-classes-calendar-tab';
28
29
  import { CoursesTab } from '../_components/enterprise-courses-tab';
29
30
  import { EnterpriseSheet } from '../_components/enterprise-sheet';
30
31
  import { StudentsTab } from '../_components/enterprise-students-tab';
@@ -265,6 +266,7 @@ export default function EnterpriseDetailPage() {
265
266
  <TabsTrigger value="overview">{t('tabs.overview')}</TabsTrigger>
266
267
  <TabsTrigger value="crm">{t('tabs.crm')}</TabsTrigger>
267
268
  <TabsTrigger value="classes">{t('tabs.classes')}</TabsTrigger>
269
+ <TabsTrigger value="classesCalendar">{t('tabs.classesCalendar')}</TabsTrigger>
268
270
  <TabsTrigger value="courses">{t('tabs.courses')}</TabsTrigger>
269
271
  <TabsTrigger value="students">{t('tabs.students')}</TabsTrigger>
270
272
  <TabsTrigger value="administrators">
@@ -288,6 +290,10 @@ export default function EnterpriseDetailPage() {
288
290
  <ClassesTab enterpriseId={account.id} />
289
291
  </TabsContent>
290
292
 
293
+ <TabsContent value="classesCalendar" className="mt-4 px-1">
294
+ <ClassesCalendarTab enterpriseId={account.id} />
295
+ </TabsContent>
296
+
291
297
  <TabsContent value="courses" className="mt-4">
292
298
  <CoursesTab enterpriseId={account.id} />
293
299
  </TabsContent>