@hed-hog/lms 0.0.361 → 0.0.365

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 (434) hide show
  1. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts +66 -0
  2. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -1
  3. package/dist/bitcode-wallet/bitcode-wallet.service.js +91 -0
  4. package/dist/bitcode-wallet/bitcode-wallet.service.js.map +1 -1
  5. package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.d.ts +8 -0
  6. package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.d.ts.map +1 -0
  7. package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.js +40 -0
  8. package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.js.map +1 -0
  9. package/dist/class-group/class-group.controller.d.ts +16 -16
  10. package/dist/class-group/class-group.service.d.ts +12 -12
  11. package/dist/course/course-audio-transcription.service.d.ts +3 -2
  12. package/dist/course/course-audio-transcription.service.d.ts.map +1 -1
  13. package/dist/course/course-audio-transcription.service.js +49 -8
  14. package/dist/course/course-audio-transcription.service.js.map +1 -1
  15. package/dist/course/course-export-scorm12-worker.service.d.ts +21 -0
  16. package/dist/course/course-export-scorm12-worker.service.d.ts.map +1 -0
  17. package/dist/course/course-export-scorm12-worker.service.js +109 -0
  18. package/dist/course/course-export-scorm12-worker.service.js.map +1 -0
  19. package/dist/course/course-export-scorm12.service.d.ts +42 -0
  20. package/dist/course/course-export-scorm12.service.d.ts.map +1 -0
  21. package/dist/course/course-export-scorm12.service.js +628 -0
  22. package/dist/course/course-export-scorm12.service.js.map +1 -0
  23. package/dist/course/course-export.service.d.ts +84 -0
  24. package/dist/course/course-export.service.d.ts.map +1 -0
  25. package/dist/course/course-export.service.js +237 -0
  26. package/dist/course/course-export.service.js.map +1 -0
  27. package/dist/course/course-lesson.controller.d.ts +4 -0
  28. package/dist/course/course-lesson.controller.d.ts.map +1 -1
  29. package/dist/course/course-lesson.controller.js +10 -0
  30. package/dist/course/course-lesson.controller.js.map +1 -1
  31. package/dist/course/course-structure.controller.d.ts +24 -9
  32. package/dist/course/course-structure.controller.d.ts.map +1 -1
  33. package/dist/course/course-structure.controller.js +30 -3
  34. package/dist/course/course-structure.controller.js.map +1 -1
  35. package/dist/course/course-structure.service.d.ts +25 -3
  36. package/dist/course/course-structure.service.d.ts.map +1 -1
  37. package/dist/course/course-structure.service.js +234 -24
  38. package/dist/course/course-structure.service.js.map +1 -1
  39. package/dist/course/course-video-conversion.service.d.ts +8 -0
  40. package/dist/course/course-video-conversion.service.d.ts.map +1 -1
  41. package/dist/course/course-video-conversion.service.js +87 -51
  42. package/dist/course/course-video-conversion.service.js.map +1 -1
  43. package/dist/course/course-video-hls.service.d.ts +57 -0
  44. package/dist/course/course-video-hls.service.d.ts.map +1 -0
  45. package/dist/course/course-video-hls.service.js +767 -0
  46. package/dist/course/course-video-hls.service.js.map +1 -0
  47. package/dist/course/course.controller.d.ts +115 -11
  48. package/dist/course/course.controller.d.ts.map +1 -1
  49. package/dist/course/course.controller.js +66 -28
  50. package/dist/course/course.controller.js.map +1 -1
  51. package/dist/course/course.mcp-tools.js +1 -1
  52. package/dist/course/course.mcp-tools.js.map +1 -1
  53. package/dist/course/course.module.d.ts.map +1 -1
  54. package/dist/course/course.module.js +13 -0
  55. package/dist/course/course.module.js.map +1 -1
  56. package/dist/course/course.service.d.ts +112 -11
  57. package/dist/course/course.service.d.ts.map +1 -1
  58. package/dist/course/course.service.js +682 -72
  59. package/dist/course/course.service.js.map +1 -1
  60. package/dist/course/dto/cleanup-course-storage.dto.d.ts +6 -0
  61. package/dist/course/dto/cleanup-course-storage.dto.d.ts.map +1 -0
  62. package/dist/course/dto/cleanup-course-storage.dto.js +34 -0
  63. package/dist/course/dto/cleanup-course-storage.dto.js.map +1 -0
  64. package/dist/course/dto/cleanup-upload-history.dto.d.ts +9 -0
  65. package/dist/course/dto/cleanup-upload-history.dto.d.ts.map +1 -0
  66. package/dist/course/dto/cleanup-upload-history.dto.js +36 -0
  67. package/dist/course/dto/cleanup-upload-history.dto.js.map +1 -0
  68. package/dist/course/dto/create-course-bulk-job.dto.d.ts +5 -0
  69. package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -0
  70. package/dist/course/dto/create-course-bulk-job.dto.js +26 -0
  71. package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -0
  72. package/dist/course/dto/create-course-export.dto.d.ts +14 -0
  73. package/dist/course/dto/create-course-export.dto.d.ts.map +1 -0
  74. package/dist/course/dto/create-course-export.dto.js +71 -0
  75. package/dist/course/dto/create-course-export.dto.js.map +1 -0
  76. package/dist/course/dto/create-course-structure-lesson.dto.d.ts +2 -2
  77. package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
  78. package/dist/course/dto/create-course-structure-lesson.dto.js +3 -2
  79. package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
  80. package/dist/course/lms-bulk-upload-automation.service.d.ts +54 -0
  81. package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -0
  82. package/dist/course/lms-bulk-upload-automation.service.js +537 -0
  83. package/dist/course/lms-bulk-upload-automation.service.js.map +1 -0
  84. package/dist/course/lms-bulk-upload-infra.service.d.ts +32 -0
  85. package/dist/course/lms-bulk-upload-infra.service.d.ts.map +1 -0
  86. package/dist/course/lms-bulk-upload-infra.service.js +301 -0
  87. package/dist/course/lms-bulk-upload-infra.service.js.map +1 -0
  88. package/dist/course/lms-bulk-upload.constants.d.ts +4 -0
  89. package/dist/course/lms-bulk-upload.constants.d.ts.map +1 -0
  90. package/dist/course/lms-bulk-upload.constants.js +7 -0
  91. package/dist/course/lms-bulk-upload.constants.js.map +1 -0
  92. package/dist/course/lms-bulk-upload.controller.d.ts +144 -1
  93. package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
  94. package/dist/course/lms-bulk-upload.controller.js +114 -4
  95. package/dist/course/lms-bulk-upload.controller.js.map +1 -1
  96. package/dist/course/lms-bulk-upload.service.d.ts +153 -3
  97. package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
  98. package/dist/course/lms-bulk-upload.service.js +659 -21
  99. package/dist/course/lms-bulk-upload.service.js.map +1 -1
  100. package/dist/course/lms-setting.controller.d.ts +6 -2
  101. package/dist/course/lms-setting.controller.d.ts.map +1 -1
  102. package/dist/course/lms-setting.controller.js +25 -8
  103. package/dist/course/lms-setting.controller.js.map +1 -1
  104. package/dist/course/scorm12-schemas.d.ts +4 -0
  105. package/dist/course/scorm12-schemas.d.ts.map +1 -0
  106. package/dist/course/scorm12-schemas.js +9 -0
  107. package/dist/course/scorm12-schemas.js.map +1 -0
  108. package/dist/enterprise/enterprise.controller.d.ts +20 -20
  109. package/dist/enterprise/enterprise.service.d.ts +20 -20
  110. package/dist/enterprise/training/training-admin.controller.d.ts +11 -11
  111. package/dist/enterprise/training/training-admin.service.d.ts +11 -11
  112. package/dist/enterprise/training/training-instructor.controller.d.ts +2 -2
  113. package/dist/enterprise/training/training-instructor.service.d.ts +2 -2
  114. package/dist/enterprise/training/training-student.controller.d.ts +1 -1
  115. package/dist/enterprise/training/training-student.service.d.ts +52 -1
  116. package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
  117. package/dist/enterprise/training/training-student.service.js +217 -4
  118. package/dist/enterprise/training/training-student.service.js.map +1 -1
  119. package/dist/enterprise/training/training-viewer.controller.d.ts +2 -2
  120. package/dist/evaluation/evaluation.controller.d.ts +8 -8
  121. package/dist/evaluation/evaluation.service.d.ts +26 -8
  122. package/dist/evaluation/evaluation.service.d.ts.map +1 -1
  123. package/dist/evaluation/evaluation.service.js +125 -0
  124. package/dist/evaluation/evaluation.service.js.map +1 -1
  125. package/dist/exam/dto/create-standalone-question.dto.d.ts +12 -0
  126. package/dist/exam/dto/create-standalone-question.dto.d.ts.map +1 -0
  127. package/dist/exam/dto/create-standalone-question.dto.js +70 -0
  128. package/dist/exam/dto/create-standalone-question.dto.js.map +1 -0
  129. package/dist/exam/exam.module.d.ts.map +1 -1
  130. package/dist/exam/exam.module.js +2 -1
  131. package/dist/exam/exam.module.js.map +1 -1
  132. package/dist/exam/exam.service.d.ts +21 -0
  133. package/dist/exam/exam.service.d.ts.map +1 -1
  134. package/dist/exam/exam.service.js +80 -0
  135. package/dist/exam/exam.service.js.map +1 -1
  136. package/dist/exam/question.controller.d.ts +27 -0
  137. package/dist/exam/question.controller.d.ts.map +1 -0
  138. package/dist/exam/question.controller.js +53 -0
  139. package/dist/exam/question.controller.js.map +1 -0
  140. package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.d.ts +6 -0
  141. package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.d.ts.map +1 -0
  142. package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.js +34 -0
  143. package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.js.map +1 -0
  144. package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.d.ts +28 -0
  145. package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.d.ts.map +1 -0
  146. package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.js +123 -0
  147. package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.js.map +1 -0
  148. package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.d.ts +4 -0
  149. package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.d.ts.map +1 -0
  150. package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.js +22 -0
  151. package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.js.map +1 -0
  152. package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.d.ts +10 -0
  153. package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.d.ts.map +1 -0
  154. package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.js +52 -0
  155. package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.js.map +1 -0
  156. package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.d.ts +15 -0
  157. package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.d.ts.map +1 -0
  158. package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.js +86 -0
  159. package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.js.map +1 -0
  160. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +30 -0
  161. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -0
  162. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +440 -0
  163. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -0
  164. package/dist/lesson-xp-map/lesson-xp-map.controller.d.ts +87 -0
  165. package/dist/lesson-xp-map/lesson-xp-map.controller.d.ts.map +1 -0
  166. package/dist/lesson-xp-map/lesson-xp-map.controller.js +185 -0
  167. package/dist/lesson-xp-map/lesson-xp-map.controller.js.map +1 -0
  168. package/dist/lesson-xp-map/lesson-xp-map.module.d.ts +3 -0
  169. package/dist/lesson-xp-map/lesson-xp-map.module.d.ts.map +1 -0
  170. package/dist/lesson-xp-map/lesson-xp-map.module.js +34 -0
  171. package/dist/lesson-xp-map/lesson-xp-map.module.js.map +1 -0
  172. package/dist/lesson-xp-map/lesson-xp-map.service.d.ts +84 -0
  173. package/dist/lesson-xp-map/lesson-xp-map.service.d.ts.map +1 -0
  174. package/dist/lesson-xp-map/lesson-xp-map.service.js +353 -0
  175. package/dist/lesson-xp-map/lesson-xp-map.service.js.map +1 -0
  176. package/dist/lesson-xp-map/lesson-xp-segment.controller.d.ts +10 -0
  177. package/dist/lesson-xp-map/lesson-xp-segment.controller.d.ts.map +1 -0
  178. package/dist/lesson-xp-map/lesson-xp-segment.controller.js +63 -0
  179. package/dist/lesson-xp-map/lesson-xp-segment.controller.js.map +1 -0
  180. package/dist/lesson-xp-map/lesson-xp-segment.service.d.ts +27 -0
  181. package/dist/lesson-xp-map/lesson-xp-segment.service.d.ts.map +1 -0
  182. package/dist/lesson-xp-map/lesson-xp-segment.service.js +194 -0
  183. package/dist/lesson-xp-map/lesson-xp-segment.service.js.map +1 -0
  184. package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -0
  185. package/dist/lms-commerce-access.subscriber.d.ts +11 -0
  186. package/dist/lms-commerce-access.subscriber.d.ts.map +1 -0
  187. package/dist/lms-commerce-access.subscriber.js +74 -0
  188. package/dist/lms-commerce-access.subscriber.js.map +1 -0
  189. package/dist/lms.module.d.ts.map +1 -1
  190. package/dist/lms.module.js +21 -5
  191. package/dist/lms.module.js.map +1 -1
  192. package/dist/platforma/dto/update-profile.dto.d.ts +17 -0
  193. package/dist/platforma/dto/update-profile.dto.d.ts.map +1 -0
  194. package/dist/platforma/dto/update-profile.dto.js +87 -0
  195. package/dist/platforma/dto/update-profile.dto.js.map +1 -0
  196. package/dist/platforma/platforma-video.service.d.ts +39 -0
  197. package/dist/platforma/platforma-video.service.d.ts.map +1 -0
  198. package/dist/platforma/platforma-video.service.js +301 -0
  199. package/dist/platforma/platforma-video.service.js.map +1 -0
  200. package/dist/platforma/platforma.controller.d.ts +182 -1
  201. package/dist/platforma/platforma.controller.d.ts.map +1 -1
  202. package/dist/platforma/platforma.controller.js +243 -2
  203. package/dist/platforma/platforma.controller.js.map +1 -1
  204. package/dist/platforma/platforma.service.d.ts +27 -0
  205. package/dist/platforma/platforma.service.d.ts.map +1 -0
  206. package/dist/platforma/platforma.service.js +274 -0
  207. package/dist/platforma/platforma.service.js.map +1 -0
  208. package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts +5 -0
  209. package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts.map +1 -0
  210. package/dist/student-xp/dto/grant-skill-card-xp.dto.js +26 -0
  211. package/dist/student-xp/dto/grant-skill-card-xp.dto.js.map +1 -0
  212. package/dist/student-xp/student-xp.controller.d.ts +56 -0
  213. package/dist/student-xp/student-xp.controller.d.ts.map +1 -0
  214. package/dist/student-xp/student-xp.controller.js +138 -0
  215. package/dist/student-xp/student-xp.controller.js.map +1 -0
  216. package/dist/student-xp/student-xp.module.d.ts +3 -0
  217. package/dist/student-xp/student-xp.module.d.ts.map +1 -0
  218. package/dist/student-xp/student-xp.module.js +25 -0
  219. package/dist/student-xp/student-xp.module.js.map +1 -0
  220. package/dist/student-xp/student-xp.service.d.ts +81 -0
  221. package/dist/student-xp/student-xp.service.d.ts.map +1 -0
  222. package/dist/student-xp/student-xp.service.js +247 -0
  223. package/dist/student-xp/student-xp.service.js.map +1 -0
  224. package/dist/xp-catalog/dto/create-xp-area.dto.d.ts +12 -0
  225. package/dist/xp-catalog/dto/create-xp-area.dto.d.ts.map +1 -0
  226. package/dist/xp-catalog/dto/create-xp-area.dto.js +63 -0
  227. package/dist/xp-catalog/dto/create-xp-area.dto.js.map +1 -0
  228. package/dist/xp-catalog/dto/create-xp-learning-type.dto.d.ts +11 -0
  229. package/dist/xp-catalog/dto/create-xp-learning-type.dto.d.ts.map +1 -0
  230. package/dist/xp-catalog/dto/create-xp-learning-type.dto.js +57 -0
  231. package/dist/xp-catalog/dto/create-xp-learning-type.dto.js.map +1 -0
  232. package/dist/xp-catalog/dto/create-xp-skill.dto.d.ts +11 -0
  233. package/dist/xp-catalog/dto/create-xp-skill.dto.d.ts.map +1 -0
  234. package/dist/xp-catalog/dto/create-xp-skill.dto.js +57 -0
  235. package/dist/xp-catalog/dto/create-xp-skill.dto.js.map +1 -0
  236. package/dist/xp-catalog/dto/update-xp-area.dto.d.ts +12 -0
  237. package/dist/xp-catalog/dto/update-xp-area.dto.d.ts.map +1 -0
  238. package/dist/xp-catalog/dto/update-xp-area.dto.js +66 -0
  239. package/dist/xp-catalog/dto/update-xp-area.dto.js.map +1 -0
  240. package/dist/xp-catalog/dto/update-xp-learning-type.dto.d.ts +11 -0
  241. package/dist/xp-catalog/dto/update-xp-learning-type.dto.d.ts.map +1 -0
  242. package/dist/xp-catalog/dto/update-xp-learning-type.dto.js +60 -0
  243. package/dist/xp-catalog/dto/update-xp-learning-type.dto.js.map +1 -0
  244. package/dist/xp-catalog/dto/update-xp-skill.dto.d.ts +11 -0
  245. package/dist/xp-catalog/dto/update-xp-skill.dto.d.ts.map +1 -0
  246. package/dist/xp-catalog/dto/update-xp-skill.dto.js +60 -0
  247. package/dist/xp-catalog/dto/update-xp-skill.dto.js.map +1 -0
  248. package/dist/xp-catalog/xp-area.controller.d.ts +25 -0
  249. package/dist/xp-catalog/xp-area.controller.d.ts.map +1 -0
  250. package/dist/xp-catalog/xp-area.controller.js +105 -0
  251. package/dist/xp-catalog/xp-area.controller.js.map +1 -0
  252. package/dist/xp-catalog/xp-area.service.d.ts +35 -0
  253. package/dist/xp-catalog/xp-area.service.d.ts.map +1 -0
  254. package/dist/xp-catalog/xp-area.service.js +168 -0
  255. package/dist/xp-catalog/xp-area.service.js.map +1 -0
  256. package/dist/xp-catalog/xp-catalog.module.d.ts +3 -0
  257. package/dist/xp-catalog/xp-catalog.module.d.ts.map +1 -0
  258. package/dist/xp-catalog/xp-catalog.module.js +29 -0
  259. package/dist/xp-catalog/xp-catalog.module.js.map +1 -0
  260. package/dist/xp-catalog/xp-learning-type.controller.d.ts +20 -0
  261. package/dist/xp-catalog/xp-learning-type.controller.d.ts.map +1 -0
  262. package/dist/xp-catalog/xp-learning-type.controller.js +96 -0
  263. package/dist/xp-catalog/xp-learning-type.controller.js.map +1 -0
  264. package/dist/xp-catalog/xp-learning-type.service.d.ts +30 -0
  265. package/dist/xp-catalog/xp-learning-type.service.d.ts.map +1 -0
  266. package/dist/xp-catalog/xp-learning-type.service.js +146 -0
  267. package/dist/xp-catalog/xp-learning-type.service.js.map +1 -0
  268. package/dist/xp-catalog/xp-skill.controller.d.ts +26 -0
  269. package/dist/xp-catalog/xp-skill.controller.d.ts.map +1 -0
  270. package/dist/xp-catalog/xp-skill.controller.js +113 -0
  271. package/dist/xp-catalog/xp-skill.controller.js.map +1 -0
  272. package/dist/xp-catalog/xp-skill.service.d.ts +37 -0
  273. package/dist/xp-catalog/xp-skill.service.d.ts.map +1 -0
  274. package/dist/xp-catalog/xp-skill.service.js +174 -0
  275. package/dist/xp-catalog/xp-skill.service.js.map +1 -0
  276. package/hedhog/data/evaluation_topic.yaml +17 -0
  277. package/hedhog/data/menu.yaml +91 -7
  278. package/hedhog/data/queue_definition.yaml +48 -0
  279. package/hedhog/data/route.yaml +511 -29
  280. package/hedhog/data/setting_group.yaml +20 -20
  281. package/hedhog/data/xp_area.yaml +164 -0
  282. package/hedhog/data/xp_learning_type.yaml +131 -0
  283. package/hedhog/data/xp_skill.yaml +1834 -0
  284. package/hedhog/frontend/app/achievements/page.tsx.ejs +108 -118
  285. package/hedhog/frontend/app/bitcodes/page.tsx.ejs +22 -34
  286. package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +1749 -0
  287. package/hedhog/frontend/app/certificates/models/page.tsx.ejs +21 -45
  288. package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +40 -74
  289. package/hedhog/frontend/app/classes/page.tsx.ejs +56 -85
  290. package/hedhog/frontend/app/courses/[id]/_components/CourseDangerZoneCard.tsx.ejs +3 -2
  291. package/hedhog/frontend/app/courses/[id]/_components/CourseMediaCard.tsx.ejs +48 -5
  292. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +73 -8
  293. package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +420 -0
  294. package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +308 -0
  295. package/hedhog/frontend/app/courses/[id]/structure/_components/course-operations-tab.tsx.ejs +19 -2
  296. package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +1172 -0
  297. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +16 -0
  298. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +2 -0
  299. package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +623 -0
  300. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +1458 -0
  301. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +87 -46
  302. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +8 -3
  303. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +31 -8
  304. package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +16 -9
  305. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +618 -480
  306. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +672 -737
  307. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -2
  308. package/hedhog/frontend/app/courses/[id]/structure/_components/sortable-tree-row.tsx.ejs +3 -0
  309. package/hedhog/frontend/app/courses/[id]/structure/_components/store.ts.ejs +1 -0
  310. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +101 -85
  311. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +24 -10
  312. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row.tsx.ejs +3 -0
  313. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -1
  314. package/hedhog/frontend/app/courses/[id]/structure/_components/use-tree-display-settings.ts.ejs +7 -1
  315. package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +44 -0
  316. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +6 -10
  317. package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +49 -0
  318. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -3
  319. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +53 -0
  320. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +106 -0
  321. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +80 -1
  322. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-xp-overview.ts.ejs +76 -0
  323. package/hedhog/frontend/app/courses/[id]/structure/_data/use-lesson-xp-map.ts.ejs +128 -0
  324. package/hedhog/frontend/app/courses/[id]/structure/_data/use-lms-settings-query.ts.ejs +0 -2
  325. package/hedhog/frontend/app/courses/[id]/structure/_data/use-transcription-segments.ts.ejs +30 -0
  326. package/hedhog/frontend/app/courses/[id]/structure/_utils/xp-color-config.ts.ejs +115 -0
  327. package/hedhog/frontend/app/courses/_components/CourseDeleteDialog.tsx.ejs +223 -0
  328. package/hedhog/frontend/app/courses/_components/CourseRowActions.tsx.ejs +89 -0
  329. package/hedhog/frontend/app/courses/page.tsx.ejs +445 -230
  330. package/hedhog/frontend/app/enterprise/page.tsx.ejs +39 -63
  331. package/hedhog/frontend/app/exams/[id]/questions/page.tsx.ejs +53 -77
  332. package/hedhog/frontend/app/exams/page.tsx.ejs +54 -90
  333. package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +23 -36
  334. package/hedhog/frontend/app/instructors/page.tsx.ejs +72 -81
  335. package/hedhog/frontend/app/paths/page.tsx.ejs +40 -68
  336. package/hedhog/frontend/app/training/page.tsx.ejs +40 -68
  337. package/hedhog/frontend/app/xp/areas/page.tsx.ejs +782 -0
  338. package/hedhog/frontend/app/xp/learning-types/page.tsx.ejs +690 -0
  339. package/hedhog/frontend/app/xp/skills/page.tsx.ejs +811 -0
  340. package/hedhog/frontend/messages/en.json +412 -31
  341. package/hedhog/frontend/messages/pt.json +412 -31
  342. package/hedhog/table/course_export.yaml +62 -0
  343. package/hedhog/table/lesson_xp_map.yaml +50 -0
  344. package/hedhog/table/lesson_xp_segment.yaml +40 -0
  345. package/hedhog/table/lesson_xp_segment_area.yaml +24 -0
  346. package/hedhog/table/lesson_xp_segment_learning_type.yaml +24 -0
  347. package/hedhog/table/lesson_xp_segment_skill.yaml +24 -0
  348. package/hedhog/table/lms_bulk_upload_item.yaml +44 -0
  349. package/hedhog/table/lms_bulk_upload_session.yaml +42 -0
  350. package/hedhog/table/student_area_xp.yaml +30 -0
  351. package/hedhog/table/student_learning_type_xp.yaml +30 -0
  352. package/hedhog/table/student_skill_xp.yaml +30 -0
  353. package/hedhog/table/student_xp_event.yaml +34 -0
  354. package/hedhog/table/xp_area.yaml +39 -0
  355. package/hedhog/table/xp_learning_type.yaml +34 -0
  356. package/hedhog/table/xp_skill.yaml +39 -0
  357. package/package.json +13 -8
  358. package/src/bitcode-wallet/bitcode-wallet.service.ts +152 -0
  359. package/src/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.ts +32 -0
  360. package/src/course/course-audio-transcription.service.ts +58 -21
  361. package/src/course/course-export-scorm12-worker.service.ts +124 -0
  362. package/src/course/course-export-scorm12.service.ts +668 -0
  363. package/src/course/course-export.service.ts +280 -0
  364. package/src/course/course-lesson.controller.ts +6 -1
  365. package/src/course/course-structure.controller.ts +23 -1
  366. package/src/course/course-structure.service.ts +273 -7
  367. package/src/course/course-video-conversion.service.ts +113 -75
  368. package/src/course/course-video-hls.service.ts +946 -0
  369. package/src/course/course.controller.ts +54 -21
  370. package/src/course/course.mcp-tools.ts +1 -1
  371. package/src/course/course.module.ts +13 -0
  372. package/src/course/course.service.ts +906 -76
  373. package/src/course/dto/cleanup-course-storage.dto.ts +23 -0
  374. package/src/course/dto/cleanup-upload-history.dto.ts +26 -0
  375. package/src/course/dto/create-course-bulk-job.dto.ts +10 -0
  376. package/src/course/dto/create-course-export.dto.ts +56 -0
  377. package/src/course/dto/create-course-structure-lesson.dto.ts +4 -3
  378. package/src/course/lms-bulk-upload-automation.service.ts +707 -0
  379. package/src/course/lms-bulk-upload-infra.service.ts +360 -0
  380. package/src/course/lms-bulk-upload.constants.ts +5 -0
  381. package/src/course/lms-bulk-upload.controller.ts +110 -4
  382. package/src/course/lms-bulk-upload.service.ts +1092 -204
  383. package/src/course/lms-setting.controller.ts +26 -8
  384. package/src/course/scorm12-schemas.ts +9 -0
  385. package/src/enterprise/training/training-student.service.ts +221 -2
  386. package/src/evaluation/evaluation.service.ts +123 -0
  387. package/src/exam/dto/create-standalone-question.dto.ts +66 -0
  388. package/src/exam/exam.module.ts +2 -1
  389. package/src/exam/exam.service.ts +86 -0
  390. package/src/exam/question.controller.ts +28 -0
  391. package/src/lesson-xp-map/dto/create-lesson-xp-map.dto.ts +17 -0
  392. package/src/lesson-xp-map/dto/create-lesson-xp-segment.dto.ts +102 -0
  393. package/src/lesson-xp-map/dto/review-lesson-xp-map.dto.ts +7 -0
  394. package/src/lesson-xp-map/dto/update-lesson-xp-map.dto.ts +36 -0
  395. package/src/lesson-xp-map/dto/update-lesson-xp-segment.dto.ts +78 -0
  396. package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +570 -0
  397. package/src/lesson-xp-map/lesson-xp-map.controller.ts +116 -0
  398. package/src/lesson-xp-map/lesson-xp-map.module.ts +21 -0
  399. package/src/lesson-xp-map/lesson-xp-map.service.ts +442 -0
  400. package/src/lesson-xp-map/lesson-xp-segment.controller.ts +36 -0
  401. package/src/lesson-xp-map/lesson-xp-segment.service.ts +229 -0
  402. package/src/lms-commerce-access.subscriber.ts +88 -0
  403. package/src/lms.module.ts +21 -5
  404. package/src/platforma/dto/update-profile.dto.ts +59 -0
  405. package/src/platforma/platforma-video.service.ts +346 -0
  406. package/src/platforma/platforma.controller.ts +152 -3
  407. package/src/platforma/platforma.service.ts +268 -0
  408. package/src/student-xp/dto/grant-skill-card-xp.dto.ts +10 -0
  409. package/src/student-xp/student-xp.controller.ts +92 -0
  410. package/src/student-xp/student-xp.module.ts +12 -0
  411. package/src/student-xp/student-xp.service.ts +318 -0
  412. package/src/xp-catalog/dto/create-xp-area.dto.ts +40 -0
  413. package/src/xp-catalog/dto/create-xp-learning-type.dto.ts +35 -0
  414. package/src/xp-catalog/dto/create-xp-skill.dto.ts +35 -0
  415. package/src/xp-catalog/dto/update-xp-area.dto.ts +43 -0
  416. package/src/xp-catalog/dto/update-xp-learning-type.dto.ts +38 -0
  417. package/src/xp-catalog/dto/update-xp-skill.dto.ts +38 -0
  418. package/src/xp-catalog/xp-area.controller.ts +64 -0
  419. package/src/xp-catalog/xp-area.service.ts +196 -0
  420. package/src/xp-catalog/xp-catalog.module.ts +16 -0
  421. package/src/xp-catalog/xp-learning-type.controller.ts +59 -0
  422. package/src/xp-catalog/xp-learning-type.service.ts +170 -0
  423. package/src/xp-catalog/xp-skill.controller.ts +71 -0
  424. package/src/xp-catalog/xp-skill.service.ts +205 -0
  425. package/hedhog/data/video_resolution_profile.yaml +0 -7
  426. package/hedhog/frontend/app/video-resolution-profiles/page.tsx.ejs +0 -607
  427. package/hedhog/table/course_video_resolution_profile.yaml +0 -22
  428. package/hedhog/table/video_resolution_profile.yaml +0 -18
  429. package/src/video-resolution-profile/dto/create-video-resolution-profile.dto.ts +0 -16
  430. package/src/video-resolution-profile/dto/update-video-resolution-profile.dto.ts +0 -16
  431. package/src/video-resolution-profile/video-resolution-profile.controller.ts +0 -62
  432. package/src/video-resolution-profile/video-resolution-profile.mcp-tools.ts +0 -128
  433. package/src/video-resolution-profile/video-resolution-profile.module.ts +0 -13
  434. package/src/video-resolution-profile/video-resolution-profile.service.ts +0 -117
@@ -27,6 +27,7 @@ import {
27
27
  useReorderLessonsMutation,
28
28
  useReorderSessionsMutation,
29
29
  } from '../_data/use-course-structure-mutations';
30
+ import { useCourseXpOverviewQuery } from '../_data/use-course-xp-overview';
30
31
  import { TreeDragOverlay } from './drag-overlay';
31
32
  import { SortableTreeRow } from './sortable-tree-row';
32
33
  import { useStructureStore } from './store';
@@ -88,6 +89,20 @@ export function CourseTreeDnd() {
88
89
  [sessions]
89
90
  );
90
91
 
92
+ const { data: courseXpOverview } = useCourseXpOverviewQuery(
93
+ course?.id ?? null
94
+ );
95
+
96
+ const lessonsWithXpMap = useMemo(
97
+ () =>
98
+ new Set(
99
+ (courseXpOverview?.lessons ?? [])
100
+ .filter((lesson) => lesson.hasMap)
101
+ .map((lesson) => String(lesson.courseLessonId))
102
+ ),
103
+ [courseXpOverview]
104
+ );
105
+
91
106
  const isSearchActive = filterQuery.trim().length > 0;
92
107
  const dragDisabled = isSearchActive;
93
108
 
@@ -375,6 +390,7 @@ export function CourseTreeDnd() {
375
390
  sessionIndicatorMap={sessionIndicatorMap}
376
391
  visibleItems={items}
377
392
  dragDisabled={dragDisabled}
393
+ lessonsWithXpMap={lessonsWithXpMap}
378
394
  />
379
395
  </div>
380
396
  ))}
@@ -44,6 +44,7 @@ export function CourseTree() {
44
44
  () => buildSessionIndicatorMap(lessons),
45
45
  [lessons]
46
46
  );
47
+ const lessonsWithXpMap = useMemo(() => new Set<string>(), []);
47
48
 
48
49
  const estimateSize = useCallback(
49
50
  (index: number) => ROW_HEIGHT[items[index]?.type ?? 'lesson'] ?? 32,
@@ -131,6 +132,7 @@ export function CourseTree() {
131
132
  lessonCountMap={lessonCountMap}
132
133
  sessionIndicatorMap={sessionIndicatorMap}
133
134
  visibleItems={items}
135
+ lessonsWithXpMap={lessonsWithXpMap}
134
136
  />
135
137
  </div>
136
138
  );
@@ -0,0 +1,623 @@
1
+ 'use client';
2
+
3
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from '@/components/ui/card';
11
+ import {
12
+ ChartContainer,
13
+ ChartTooltip,
14
+ ChartTooltipContent,
15
+ } from '@/components/ui/chart';
16
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
17
+ import { Skeleton } from '@/components/ui/skeleton';
18
+ import {
19
+ BarChart3,
20
+ BookOpen,
21
+ ChartPie,
22
+ Layers3,
23
+ Sparkles,
24
+ Target,
25
+ } from 'lucide-react';
26
+ import { useTranslations } from 'next-intl';
27
+ import { useMemo } from 'react';
28
+ import {
29
+ Bar,
30
+ BarChart,
31
+ CartesianGrid,
32
+ Cell,
33
+ Pie,
34
+ PieChart,
35
+ XAxis,
36
+ YAxis,
37
+ } from 'recharts';
38
+ import { useCourseXpOverviewQuery } from '../_data/use-course-xp-overview';
39
+ import {
40
+ resolveXpAreaColor,
41
+ resolveXpLearningTypeColor,
42
+ resolveXpSkillColor,
43
+ } from '../_utils/xp-color-config';
44
+ import { XpHighlightPill, XpMetaPill } from './xp-premium-pills';
45
+
46
+ type XpAreaOption = {
47
+ id: number;
48
+ name: string;
49
+ color: string | null;
50
+ };
51
+
52
+ function formatCompactNumber(value: number, locale: string) {
53
+ return new Intl.NumberFormat(locale, {
54
+ notation: 'compact',
55
+ maximumFractionDigits: value >= 100 ? 0 : 1,
56
+ }).format(value);
57
+ }
58
+
59
+ function formatPercentage(value: number, locale: string) {
60
+ return new Intl.NumberFormat(locale, {
61
+ minimumFractionDigits: 0,
62
+ maximumFractionDigits: 1,
63
+ }).format(value);
64
+ }
65
+
66
+ function getTopItems<T>(items: T[], maxItems = 5) {
67
+ return items.slice(0, maxItems);
68
+ }
69
+
70
+ interface Props {
71
+ courseId: string;
72
+ locale: string;
73
+ }
74
+
75
+ export function CourseXpOverviewTab({ courseId, locale }: Props) {
76
+ const t = useTranslations('lms.CursoEditPage.structureEditor.xpOverview');
77
+ const { request } = useApp();
78
+ const { data, isLoading, isError } = useCourseXpOverviewQuery(courseId);
79
+ const { data: areaOptions = [] } = useQuery<XpAreaOption[]>({
80
+ queryKey: ['lms-xp-areas-all'],
81
+ enabled: Boolean(courseId),
82
+ queryFn: async () => {
83
+ const response = await request<XpAreaOption[]>({
84
+ url: '/lms/xp/areas/all',
85
+ method: 'GET',
86
+ });
87
+ return response.data;
88
+ },
89
+ placeholderData: [],
90
+ });
91
+
92
+ const areaColorLookup = useMemo(
93
+ () => new Map(areaOptions.map((area) => [area.id, area.color])),
94
+ [areaOptions]
95
+ );
96
+
97
+ const kpiItems = useMemo(() => {
98
+ if (!data) return [];
99
+
100
+ return [
101
+ {
102
+ key: 'totalXp',
103
+ title: t('kpis.totalXp'),
104
+ value: data.summary.totalXp,
105
+ description: t('kpis.totalXpDescription'),
106
+ icon: Sparkles,
107
+ accentClassName: 'from-cyan-500 via-sky-500 to-blue-500',
108
+ iconContainerClassName:
109
+ 'bg-cyan-500/10 text-cyan-600 dark:text-cyan-400',
110
+ },
111
+ {
112
+ key: 'mappedLessons',
113
+ title: t('kpis.mappedLessons'),
114
+ value: `${data.summary.mappedLessons}/${data.summary.totalLessons}`,
115
+ description: t('kpis.mappedLessonsDescription'),
116
+ icon: BookOpen,
117
+ accentClassName: 'from-emerald-500 via-teal-500 to-green-500',
118
+ iconContainerClassName:
119
+ 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400',
120
+ },
121
+ {
122
+ key: 'areas',
123
+ title: 'Áreas macro',
124
+ value: data.areas.length,
125
+ description: 'Principais áreas mapeadas no curso',
126
+ icon: Layers3,
127
+ accentClassName: 'from-amber-500 via-orange-500 to-rose-500',
128
+ iconContainerClassName:
129
+ 'bg-amber-500/10 text-amber-600 dark:text-amber-400',
130
+ },
131
+ {
132
+ key: 'skills',
133
+ title: 'Skills únicas',
134
+ value: data.skills.length,
135
+ description: 'Quantidade total de skills do curso',
136
+ icon: Target,
137
+ accentClassName: 'from-violet-500 via-fuchsia-500 to-purple-500',
138
+ iconContainerClassName:
139
+ 'bg-violet-500/10 text-violet-600 dark:text-violet-400',
140
+ },
141
+ ];
142
+ }, [data, t]);
143
+
144
+ const areaData = getTopItems(data?.areas ?? [], 6);
145
+ const skillData = getTopItems(data?.skills ?? [], 6);
146
+ const learningTypeData = getTopItems(data?.learningTypes ?? [], 4);
147
+
148
+ const areaChartConfig = useMemo(
149
+ () =>
150
+ Object.fromEntries(
151
+ areaData.map((item, index) => [
152
+ item.slug,
153
+ {
154
+ label: item.name,
155
+ color: resolveXpAreaColor({
156
+ areaId: item.xpAreaId,
157
+ areaSlug: item.slug,
158
+ index,
159
+ persistedColor: areaColorLookup.get(item.xpAreaId),
160
+ }),
161
+ },
162
+ ])
163
+ ),
164
+ [areaColorLookup, areaData]
165
+ );
166
+
167
+ const skillChartConfig = useMemo(
168
+ () =>
169
+ Object.fromEntries(
170
+ skillData.map((item, index) => [
171
+ item.slug,
172
+ {
173
+ label: item.name,
174
+ color: resolveXpSkillColor({
175
+ skillId: item.xpSkillId,
176
+ skillSlug: item.slug,
177
+ index,
178
+ }),
179
+ },
180
+ ])
181
+ ),
182
+ [skillData]
183
+ );
184
+
185
+ const overviewHighlights = useMemo(() => {
186
+ if (!data) return [];
187
+
188
+ const topArea = data.areas[0];
189
+ const topSkill = data.skills[0];
190
+
191
+ return [
192
+ topArea
193
+ ? {
194
+ key: 'top-area',
195
+ label: 'Área líder',
196
+ value: `${topArea.name} ${formatPercentage(topArea.sharePercent, locale)}%`,
197
+ tone: 'sky' as const,
198
+ }
199
+ : null,
200
+ topSkill
201
+ ? {
202
+ key: 'top-skill',
203
+ label: 'Skill líder',
204
+ value: `${topSkill.name} ${formatPercentage(topSkill.sharePercent, locale)}%`,
205
+ tone: 'amber' as const,
206
+ }
207
+ : null,
208
+ {
209
+ key: 'coverage',
210
+ label: 'Cobertura',
211
+ value: `${data.summary.mappedLessons}/${data.summary.totalLessons} aulas`,
212
+ tone: 'emerald' as const,
213
+ },
214
+ ].filter(Boolean);
215
+ }, [data, locale]);
216
+
217
+ if (isLoading) {
218
+ return (
219
+ <div className="flex flex-col gap-3">
220
+ <div className="grid grid-cols-2 gap-3 xl:grid-cols-4">
221
+ {Array.from({ length: 4 }).map((_, index) => (
222
+ <Skeleton key={index} className="h-24 rounded-xl" />
223
+ ))}
224
+ </div>
225
+ <div className="grid gap-3 xl:grid-cols-2">
226
+ <Skeleton className="h-72 rounded-xl" />
227
+ <Skeleton className="h-72 rounded-xl" />
228
+ </div>
229
+ <Skeleton className="h-36 rounded-xl" />
230
+ </div>
231
+ );
232
+ }
233
+
234
+ if (isError || !data) {
235
+ return (
236
+ <Card className="border-dashed bg-muted/20">
237
+ <CardHeader>
238
+ <CardTitle className="text-sm font-semibold">
239
+ {t('errorTitle')}
240
+ </CardTitle>
241
+ <CardDescription>{t('errorDescription')}</CardDescription>
242
+ </CardHeader>
243
+ </Card>
244
+ );
245
+ }
246
+
247
+ if (data.summary.mappedLessons === 0) {
248
+ return (
249
+ <Card className="border-dashed bg-muted/20">
250
+ <CardHeader>
251
+ <CardTitle className="text-sm font-semibold">
252
+ {t('emptyTitle')}
253
+ </CardTitle>
254
+ <CardDescription>{t('emptyDescription')}</CardDescription>
255
+ </CardHeader>
256
+ </Card>
257
+ );
258
+ }
259
+
260
+ return (
261
+ <div className="flex flex-col gap-2.5">
262
+ <div className="rounded-2xl border border-border/70 bg-linear-to-br from-background via-background to-muted/30 px-2.5 py-2 shadow-[0_14px_34px_-28px_rgba(15,23,42,0.45)] backdrop-blur-sm sm:px-3 sm:py-2.5">
263
+ <div className="flex flex-wrap items-start justify-between gap-3 border-b border-border/50 pb-2">
264
+ <div className="min-w-0">
265
+ <div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-cyan-700/80 dark:text-cyan-300/80">
266
+ Course XP overview
267
+ </div>
268
+ <div className="mt-1 text-sm font-semibold text-foreground">
269
+ Panorama do mapeamento do curso
270
+ </div>
271
+ <div className="mt-0.5 text-xs text-muted-foreground">
272
+ Leitura consolidada de áreas macro, skills e tipos de aprendizado.
273
+ </div>
274
+ </div>
275
+ <div className="flex flex-wrap gap-1.5">
276
+ {overviewHighlights.map((item) =>
277
+ item ? (
278
+ <XpHighlightPill
279
+ key={item.key}
280
+ label={item.label}
281
+ value={item.value}
282
+ tone={item.tone}
283
+ />
284
+ ) : null
285
+ )}
286
+ </div>
287
+ </div>
288
+
289
+ <div className="mt-2">
290
+ <KpiCardsGrid
291
+ items={kpiItems.map((item) => ({
292
+ ...item,
293
+ layout: 'compact' as const,
294
+ }))}
295
+ columns={4}
296
+ className="gap-2.5"
297
+ cardClassName="shadow-[0_12px_24px_-22px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
298
+ />
299
+ </div>
300
+ </div>
301
+
302
+ <div className="grid gap-3 xl:grid-cols-[minmax(0,1.06fr)_minmax(0,0.94fr)]">
303
+ <Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
304
+ <CardHeader className="border-b border-border/70 bg-linear-to-r from-teal-500/12 via-cyan-500/6 to-transparent pt-2.5 pb-1.5!">
305
+ <div className="flex flex-wrap items-start justify-between gap-3">
306
+ <div className="flex min-w-0 items-start gap-3">
307
+ <div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-teal-500/10 text-teal-600 ring-1 ring-inset ring-teal-500/15 dark:text-teal-400">
308
+ <ChartPie className="size-4" />
309
+ </div>
310
+ <div className="min-w-0">
311
+ <div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-teal-600/80 dark:text-teal-400/80">
312
+ Macro areas
313
+ </div>
314
+ <CardTitle className="mt-1 text-sm font-semibold">
315
+ {t('charts.macroAreas.title')}
316
+ </CardTitle>
317
+ <CardDescription className="mt-0.5">
318
+ {t('charts.macroAreas.description')}
319
+ </CardDescription>
320
+ </div>
321
+ </div>
322
+ <div className="rounded-full border border-teal-500/15 bg-teal-500/10 px-2.5 py-1 text-[10px] font-semibold text-teal-700 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-teal-500/15 hover:shadow-md dark:text-teal-300">
323
+ {data.areas.length} áreas
324
+ </div>
325
+ </div>
326
+ </CardHeader>
327
+ <CardContent className="grid gap-2.5 px-2.5 py-2.5 sm:px-3 md:grid-cols-[minmax(0,188px)_minmax(0,1fr)] md:items-start">
328
+ <ChartContainer config={areaChartConfig} className="h-48 w-full">
329
+ <PieChart>
330
+ <Pie
331
+ data={areaData}
332
+ dataKey="xp"
333
+ nameKey="name"
334
+ innerRadius={48}
335
+ outerRadius={72}
336
+ paddingAngle={2.5}
337
+ animationDuration={900}
338
+ strokeWidth={3}
339
+ stroke="hsl(var(--background))"
340
+ >
341
+ {areaData.map((entry, index) => (
342
+ <Cell
343
+ key={entry.xpAreaId}
344
+ fill={resolveXpAreaColor({
345
+ areaId: entry.xpAreaId,
346
+ areaSlug: entry.slug,
347
+ index,
348
+ persistedColor: areaColorLookup.get(entry.xpAreaId),
349
+ })}
350
+ />
351
+ ))}
352
+ </Pie>
353
+ <ChartTooltip
354
+ content={
355
+ <ChartTooltipContent
356
+ hideIndicator
357
+ formatter={(value, _name, item) => {
358
+ const payload = item?.payload as
359
+ | {
360
+ name?: string;
361
+ lessonCount?: number;
362
+ segmentCount?: number;
363
+ }
364
+ | undefined;
365
+ return (
366
+ <div className="flex min-w-48 flex-col gap-1 text-xs">
367
+ <span className="font-medium text-foreground">
368
+ {payload?.name}
369
+ </span>
370
+ <span className="text-muted-foreground">
371
+ {formatCompactNumber(Number(value ?? 0), locale)}{' '}
372
+ XP
373
+ </span>
374
+ <span className="text-muted-foreground">
375
+ {payload?.lessonCount ?? 0} aulas ·{' '}
376
+ {payload?.segmentCount ?? 0} segmentos
377
+ </span>
378
+ </div>
379
+ );
380
+ }}
381
+ />
382
+ }
383
+ />
384
+ </PieChart>
385
+ </ChartContainer>
386
+
387
+ <div className="grid gap-1.5">
388
+ {areaData.map((item, index) => (
389
+ <div
390
+ key={item.xpAreaId}
391
+ className="rounded-2xl border border-border/60 bg-linear-to-br from-background via-background to-sky-500/5 px-3 py-2 shadow-[0_14px_28px_-24px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:border-sky-500/20 hover:to-sky-500/10 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
392
+ >
393
+ <div className="flex items-center gap-2">
394
+ <span
395
+ className="size-2.5 rounded-full"
396
+ style={{
397
+ backgroundColor: resolveXpAreaColor({
398
+ areaId: item.xpAreaId,
399
+ areaSlug: item.slug,
400
+ index,
401
+ persistedColor: areaColorLookup.get(item.xpAreaId),
402
+ }),
403
+ }}
404
+ />
405
+ <span className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">
406
+ {item.name}
407
+ </span>
408
+ <span className="rounded-full border border-border/50 bg-background/90 px-2 py-0.5 text-[10px] font-semibold text-muted-foreground shadow-sm transition-all duration-200 hover:border-border hover:bg-background hover:text-foreground hover:shadow-md">
409
+ {formatPercentage(item.sharePercent, locale)}%
410
+ </span>
411
+ </div>
412
+ <div className="mt-1.5 flex flex-wrap gap-1">
413
+ <XpMetaPill
414
+ value={`${formatCompactNumber(item.xp, locale)} XP`}
415
+ />
416
+ <XpMetaPill value={`${item.lessonCount} aulas`} />
417
+ <XpMetaPill value={`${item.segmentCount} seg.`} />
418
+ </div>
419
+ </div>
420
+ ))}
421
+ </div>
422
+ </CardContent>
423
+ </Card>
424
+
425
+ <Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
426
+ <CardHeader className="border-b border-border/70 bg-linear-to-r from-orange-500/12 via-amber-500/6 to-transparent pt-2.5 pb-1.5!">
427
+ <div className="flex flex-wrap items-start justify-between gap-3">
428
+ <div className="flex min-w-0 items-start gap-3">
429
+ <div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-orange-500/10 text-orange-600 ring-1 ring-inset ring-orange-500/15 dark:text-orange-400">
430
+ <BarChart3 className="size-4" />
431
+ </div>
432
+ <div className="min-w-0">
433
+ <div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-orange-600/80 dark:text-orange-400/80">
434
+ Skill density
435
+ </div>
436
+ <CardTitle className="mt-1 text-sm font-semibold">
437
+ {t('charts.skills.title')}
438
+ </CardTitle>
439
+ <CardDescription className="mt-0.5">
440
+ {t('charts.skills.description')}
441
+ </CardDescription>
442
+ </div>
443
+ </div>
444
+ <div className="rounded-full border border-orange-500/15 bg-orange-500/10 px-2.5 py-1 text-[10px] font-semibold text-orange-700 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-orange-500/15 hover:shadow-md dark:text-orange-300">
445
+ {data.skills.length} skills
446
+ </div>
447
+ </div>
448
+ </CardHeader>
449
+ <CardContent className="flex flex-col gap-2.5 px-2.5 py-2.5 sm:px-3">
450
+ <ChartContainer config={skillChartConfig} className="h-48 w-full">
451
+ <BarChart
452
+ data={skillData}
453
+ layout="vertical"
454
+ margin={{ left: 10, right: 10 }}
455
+ barCategoryGap={10}
456
+ >
457
+ <CartesianGrid horizontal={false} strokeDasharray="3 3" />
458
+ <XAxis type="number" tickLine={false} axisLine={false} />
459
+ <YAxis
460
+ dataKey="name"
461
+ type="category"
462
+ width={120}
463
+ tickLine={false}
464
+ axisLine={false}
465
+ />
466
+ <ChartTooltip
467
+ cursor={false}
468
+ content={
469
+ <ChartTooltipContent
470
+ hideLabel
471
+ formatter={(value, _name, item) => {
472
+ const payload = item?.payload as
473
+ | {
474
+ name?: string;
475
+ lessonCount?: number;
476
+ segmentCount?: number;
477
+ }
478
+ | undefined;
479
+ return (
480
+ <div className="flex min-w-48 flex-col gap-1 text-xs">
481
+ <span className="font-medium text-foreground">
482
+ {payload?.name}
483
+ </span>
484
+ <span className="text-muted-foreground">
485
+ {formatCompactNumber(Number(value ?? 0), locale)}{' '}
486
+ XP
487
+ </span>
488
+ <span className="text-muted-foreground">
489
+ {payload?.lessonCount ?? 0} aulas ·{' '}
490
+ {payload?.segmentCount ?? 0} segmentos
491
+ </span>
492
+ </div>
493
+ );
494
+ }}
495
+ />
496
+ }
497
+ />
498
+ <Bar
499
+ dataKey="xp"
500
+ radius={[0, 10, 10, 0]}
501
+ animationDuration={950}
502
+ >
503
+ {skillData.map((entry, index) => (
504
+ <Cell
505
+ key={entry.xpSkillId}
506
+ fill={resolveXpSkillColor({
507
+ skillId: entry.xpSkillId,
508
+ skillSlug: entry.slug,
509
+ index,
510
+ })}
511
+ />
512
+ ))}
513
+ </Bar>
514
+ </BarChart>
515
+ </ChartContainer>
516
+
517
+ <div className="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-1.5">
518
+ {skillData.map((item, index) => (
519
+ <div
520
+ key={item.xpSkillId}
521
+ className="rounded-2xl border border-border/60 bg-linear-to-br from-background via-background to-orange-500/5 px-3 py-2 shadow-[0_14px_28px_-24px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:border-orange-500/20 hover:to-orange-500/10 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
522
+ >
523
+ <div className="flex flex-wrap items-center justify-between gap-2">
524
+ <div className="flex min-w-0 items-center gap-2">
525
+ <span
526
+ className="size-2 rounded-full"
527
+ style={{
528
+ backgroundColor: resolveXpSkillColor({
529
+ skillId: item.xpSkillId,
530
+ skillSlug: item.slug,
531
+ index,
532
+ }),
533
+ }}
534
+ />
535
+ <span className="truncate text-sm font-medium text-foreground">
536
+ {item.name}
537
+ </span>
538
+ </div>
539
+ <span className="rounded-full border border-border/50 bg-background/90 px-2 py-0.5 text-[10px] font-semibold text-muted-foreground shadow-sm transition-all duration-200 hover:border-border hover:bg-background hover:text-foreground hover:shadow-md">
540
+ {formatPercentage(item.sharePercent, locale)}%
541
+ </span>
542
+ </div>
543
+ <div className="mt-1.5 flex flex-wrap gap-1">
544
+ <XpMetaPill
545
+ value={`${formatCompactNumber(item.xp, locale)} XP`}
546
+ />
547
+ <XpMetaPill value={`${item.lessonCount} aulas`} />
548
+ <XpMetaPill value={`${item.segmentCount} seg.`} />
549
+ </div>
550
+ </div>
551
+ ))}
552
+ </div>
553
+ </CardContent>
554
+ </Card>
555
+ </div>
556
+
557
+ {learningTypeData.length > 0 && (
558
+ <Card className="min-w-0 overflow-hidden border-border/70 bg-card/95 py-0 gap-0! shadow-[0_18px_40px_-32px_rgba(15,23,42,0.45)]">
559
+ <CardHeader className="border-b border-border/70 bg-linear-to-r from-violet-500/10 via-fuchsia-500/5 to-transparent pt-2.5 pb-1.5!">
560
+ <div className="flex flex-wrap items-start justify-between gap-3">
561
+ <div className="flex min-w-0 items-start gap-3">
562
+ <div className="flex size-9 shrink-0 items-center justify-center rounded-2xl bg-violet-500/10 text-violet-600 ring-1 ring-inset ring-violet-500/15 dark:text-violet-400">
563
+ <Sparkles className="size-4" />
564
+ </div>
565
+ <div className="min-w-0">
566
+ <div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-violet-600/80 dark:text-violet-400/80">
567
+ Learning mix
568
+ </div>
569
+ <CardTitle className="mt-1 text-sm font-semibold">
570
+ {t('charts.learningTypes.title')}
571
+ </CardTitle>
572
+ <CardDescription className="mt-0.5">
573
+ {t('charts.learningTypes.description')}
574
+ </CardDescription>
575
+ </div>
576
+ </div>
577
+ <div className="rounded-full border border-violet-500/15 bg-violet-500/10 px-2.5 py-1 text-[10px] font-semibold text-violet-700 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-violet-500/15 hover:shadow-md dark:text-violet-300">
578
+ {learningTypeData.length} tipos
579
+ </div>
580
+ </div>
581
+ </CardHeader>
582
+ <CardContent className="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] content-start gap-2 px-2.5 py-2.5 sm:px-3">
583
+ {learningTypeData.map((item, index) => (
584
+ <div
585
+ key={item.xpLearningTypeId}
586
+ className="flex h-full flex-col justify-start gap-1.5 rounded-2xl border border-border/60 bg-linear-to-br from-background via-background to-violet-500/5 px-3 py-2 shadow-[0_14px_28px_-24px_rgba(15,23,42,0.45)] transition-all duration-200 hover:-translate-y-0.5 hover:border-violet-500/20 hover:to-violet-500/10 hover:shadow-[0_18px_34px_-22px_rgba(15,23,42,0.5)]"
587
+ >
588
+ <div className="flex flex-wrap items-center gap-2">
589
+ <div className="flex min-w-0 flex-1 items-center gap-2">
590
+ <span
591
+ className="size-2.5 rounded-full"
592
+ style={{
593
+ backgroundColor: resolveXpLearningTypeColor({
594
+ learningTypeId: item.xpLearningTypeId,
595
+ learningTypeSlug: item.slug,
596
+ index,
597
+ }),
598
+ }}
599
+ />
600
+ <span className="min-w-0 flex-1 truncate text-sm font-medium text-foreground">
601
+ {item.name}
602
+ </span>
603
+ </div>
604
+ <span className="rounded-full border border-border/50 bg-background/90 px-2 py-0.5 text-[10px] font-semibold text-muted-foreground shadow-sm transition-all duration-200 hover:border-border hover:bg-background hover:text-foreground hover:shadow-md">
605
+ x{formatPercentage(item.multiplier, locale)}
606
+ </span>
607
+ </div>
608
+ <div className="flex flex-wrap gap-1">
609
+ <XpMetaPill
610
+ value={`${formatCompactNumber(item.xp, locale)} XP`}
611
+ />
612
+ <XpMetaPill
613
+ value={`${formatPercentage(item.sharePercent, locale)}% share`}
614
+ />
615
+ </div>
616
+ </div>
617
+ ))}
618
+ </CardContent>
619
+ </Card>
620
+ )}
621
+ </div>
622
+ );
623
+ }