@hed-hog/lms 0.0.347 → 0.0.350

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 (414) hide show
  1. package/dist/achievement/achievement.controller.d.ts +62 -0
  2. package/dist/achievement/achievement.controller.d.ts.map +1 -0
  3. package/dist/achievement/achievement.controller.js +90 -0
  4. package/dist/achievement/achievement.controller.js.map +1 -0
  5. package/dist/achievement/achievement.mcp-tools.d.ts +19 -0
  6. package/dist/achievement/achievement.mcp-tools.d.ts.map +1 -0
  7. package/dist/achievement/achievement.mcp-tools.js +157 -0
  8. package/dist/achievement/achievement.mcp-tools.js.map +1 -0
  9. package/dist/achievement/achievement.module.d.ts +3 -0
  10. package/dist/achievement/achievement.module.d.ts.map +1 -0
  11. package/dist/achievement/achievement.module.js +26 -0
  12. package/dist/achievement/achievement.module.js.map +1 -0
  13. package/dist/achievement/achievement.service.d.ts +72 -0
  14. package/dist/achievement/achievement.service.d.ts.map +1 -0
  15. package/dist/achievement/achievement.service.js +200 -0
  16. package/dist/achievement/achievement.service.js.map +1 -0
  17. package/dist/achievement/dto/create-achievement.dto.d.ts +12 -0
  18. package/dist/achievement/dto/create-achievement.dto.d.ts.map +1 -0
  19. package/dist/achievement/dto/create-achievement.dto.js +60 -0
  20. package/dist/achievement/dto/create-achievement.dto.js.map +1 -0
  21. package/dist/achievement/dto/update-achievement.dto.d.ts +11 -0
  22. package/dist/achievement/dto/update-achievement.dto.d.ts.map +1 -0
  23. package/dist/achievement/dto/update-achievement.dto.js +57 -0
  24. package/dist/achievement/dto/update-achievement.dto.js.map +1 -0
  25. package/dist/bitcode-wallet/bitcode-wallet.controller.d.ts +114 -0
  26. package/dist/bitcode-wallet/bitcode-wallet.controller.d.ts.map +1 -0
  27. package/dist/bitcode-wallet/bitcode-wallet.controller.js +102 -0
  28. package/dist/bitcode-wallet/bitcode-wallet.controller.js.map +1 -0
  29. package/dist/bitcode-wallet/bitcode-wallet.mcp-tools.d.ts +25 -0
  30. package/dist/bitcode-wallet/bitcode-wallet.mcp-tools.d.ts.map +1 -0
  31. package/dist/bitcode-wallet/bitcode-wallet.mcp-tools.js +160 -0
  32. package/dist/bitcode-wallet/bitcode-wallet.mcp-tools.js.map +1 -0
  33. package/dist/bitcode-wallet/bitcode-wallet.module.d.ts +3 -0
  34. package/dist/bitcode-wallet/bitcode-wallet.module.d.ts.map +1 -0
  35. package/dist/bitcode-wallet/bitcode-wallet.module.js +26 -0
  36. package/dist/bitcode-wallet/bitcode-wallet.module.js.map +1 -0
  37. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts +127 -0
  38. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -0
  39. package/dist/bitcode-wallet/bitcode-wallet.service.js +264 -0
  40. package/dist/bitcode-wallet/bitcode-wallet.service.js.map +1 -0
  41. package/dist/bitcode-wallet/dto/create-bitcode-wallet-transaction.dto.d.ts +8 -0
  42. package/dist/bitcode-wallet/dto/create-bitcode-wallet-transaction.dto.d.ts.map +1 -0
  43. package/dist/bitcode-wallet/dto/create-bitcode-wallet-transaction.dto.js +33 -0
  44. package/dist/bitcode-wallet/dto/create-bitcode-wallet-transaction.dto.js.map +1 -0
  45. package/dist/bitcode-wallet/dto/create-bitcode-wallet.dto.d.ts +4 -0
  46. package/dist/bitcode-wallet/dto/create-bitcode-wallet.dto.d.ts.map +1 -0
  47. package/dist/bitcode-wallet/dto/create-bitcode-wallet.dto.js +22 -0
  48. package/dist/bitcode-wallet/dto/create-bitcode-wallet.dto.js.map +1 -0
  49. package/dist/bitcode-wallet/dto/update-bitcode-wallet-transaction.dto.d.ts +7 -0
  50. package/dist/bitcode-wallet/dto/update-bitcode-wallet-transaction.dto.d.ts.map +1 -0
  51. package/dist/bitcode-wallet/dto/update-bitcode-wallet-transaction.dto.js +35 -0
  52. package/dist/bitcode-wallet/dto/update-bitcode-wallet-transaction.dto.js.map +1 -0
  53. package/dist/bitcode-wallet/dto/update-bitcode-wallet.dto.d.ts +4 -0
  54. package/dist/bitcode-wallet/dto/update-bitcode-wallet.dto.d.ts.map +1 -0
  55. package/dist/bitcode-wallet/dto/update-bitcode-wallet.dto.js +23 -0
  56. package/dist/bitcode-wallet/dto/update-bitcode-wallet.dto.js.map +1 -0
  57. package/dist/certificate/certificate.controller.d.ts +22 -0
  58. package/dist/certificate/certificate.controller.d.ts.map +1 -1
  59. package/dist/certificate/certificate.controller.js +12 -0
  60. package/dist/certificate/certificate.controller.js.map +1 -1
  61. package/dist/certificate/certificate.mcp-tools.d.ts +24 -0
  62. package/dist/certificate/certificate.mcp-tools.d.ts.map +1 -0
  63. package/dist/certificate/certificate.mcp-tools.js +188 -0
  64. package/dist/certificate/certificate.mcp-tools.js.map +1 -0
  65. package/dist/certificate/certificate.module.d.ts.map +1 -1
  66. package/dist/certificate/certificate.module.js +2 -1
  67. package/dist/certificate/certificate.module.js.map +1 -1
  68. package/dist/certificate/certificate.service.d.ts +25 -2
  69. package/dist/certificate/certificate.service.d.ts.map +1 -1
  70. package/dist/certificate/certificate.service.js +87 -2
  71. package/dist/certificate/certificate.service.js.map +1 -1
  72. package/dist/certificate/dto/update-certificate-public-access.dto.d.ts +4 -0
  73. package/dist/certificate/dto/update-certificate-public-access.dto.d.ts.map +1 -0
  74. package/dist/certificate/dto/update-certificate-public-access.dto.js +21 -0
  75. package/dist/certificate/dto/update-certificate-public-access.dto.js.map +1 -0
  76. package/dist/class-group/class-group.controller.d.ts +3 -3
  77. package/dist/class-group/class-group.mcp-tools.d.ts +87 -0
  78. package/dist/class-group/class-group.mcp-tools.d.ts.map +1 -0
  79. package/dist/class-group/class-group.mcp-tools.js +553 -0
  80. package/dist/class-group/class-group.mcp-tools.js.map +1 -0
  81. package/dist/class-group/class-group.module.d.ts.map +1 -1
  82. package/dist/class-group/class-group.module.js +2 -1
  83. package/dist/class-group/class-group.module.js.map +1 -1
  84. package/dist/class-group/class-group.service.d.ts +6 -4
  85. package/dist/class-group/class-group.service.d.ts.map +1 -1
  86. package/dist/class-group/class-group.service.js +45 -2
  87. package/dist/class-group/class-group.service.js.map +1 -1
  88. package/dist/course/course-operations-integration.service.d.ts +40 -0
  89. package/dist/course/course-operations-integration.service.d.ts.map +1 -0
  90. package/dist/course/course-operations-integration.service.js +372 -0
  91. package/dist/course/course-operations-integration.service.js.map +1 -0
  92. package/dist/course/course-structure.controller.d.ts +43 -4
  93. package/dist/course/course-structure.controller.d.ts.map +1 -1
  94. package/dist/course/course-structure.controller.js +22 -0
  95. package/dist/course/course-structure.controller.js.map +1 -1
  96. package/dist/course/course-structure.service.d.ts +42 -1
  97. package/dist/course/course-structure.service.d.ts.map +1 -1
  98. package/dist/course/course-structure.service.js +199 -32
  99. package/dist/course/course-structure.service.js.map +1 -1
  100. package/dist/course/course.controller.d.ts +12 -0
  101. package/dist/course/course.controller.d.ts.map +1 -1
  102. package/dist/course/course.mcp-tools.d.ts +90 -0
  103. package/dist/course/course.mcp-tools.d.ts.map +1 -0
  104. package/dist/course/course.mcp-tools.js +520 -0
  105. package/dist/course/course.mcp-tools.js.map +1 -0
  106. package/dist/course/course.module.d.ts.map +1 -1
  107. package/dist/course/course.module.js +8 -1
  108. package/dist/course/course.module.js.map +1 -1
  109. package/dist/course/course.service.d.ts +15 -1
  110. package/dist/course/course.service.d.ts.map +1 -1
  111. package/dist/course/course.service.js +70 -35
  112. package/dist/course/course.service.js.map +1 -1
  113. package/dist/course/dto/create-course.dto.d.ts +1 -0
  114. package/dist/course/dto/create-course.dto.d.ts.map +1 -1
  115. package/dist/course/dto/create-course.dto.js +7 -0
  116. package/dist/course/dto/create-course.dto.js.map +1 -1
  117. package/dist/course/dto/update-course-resources.dto.d.ts +11 -0
  118. package/dist/course/dto/update-course-resources.dto.d.ts.map +1 -0
  119. package/dist/course/dto/update-course-resources.dto.js +51 -0
  120. package/dist/course/dto/update-course-resources.dto.js.map +1 -0
  121. package/dist/course-lesson-discussion/course-lesson-discussion.controller.d.ts +23 -0
  122. package/dist/course-lesson-discussion/course-lesson-discussion.controller.d.ts.map +1 -0
  123. package/dist/course-lesson-discussion/course-lesson-discussion.controller.js +78 -0
  124. package/dist/course-lesson-discussion/course-lesson-discussion.controller.js.map +1 -0
  125. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.d.ts +22 -0
  126. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.d.ts.map +1 -0
  127. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.js +120 -0
  128. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.js.map +1 -0
  129. package/dist/course-lesson-discussion/course-lesson-discussion.module.d.ts +3 -0
  130. package/dist/course-lesson-discussion/course-lesson-discussion.module.d.ts.map +1 -0
  131. package/dist/course-lesson-discussion/course-lesson-discussion.module.js +26 -0
  132. package/dist/course-lesson-discussion/course-lesson-discussion.module.js.map +1 -0
  133. package/dist/course-lesson-discussion/course-lesson-discussion.service.d.ts +49 -0
  134. package/dist/course-lesson-discussion/course-lesson-discussion.service.d.ts.map +1 -0
  135. package/dist/course-lesson-discussion/course-lesson-discussion.service.js +272 -0
  136. package/dist/course-lesson-discussion/course-lesson-discussion.service.js.map +1 -0
  137. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.d.ts +6 -0
  138. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.d.ts.map +1 -0
  139. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.js +33 -0
  140. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.js.map +1 -0
  141. package/dist/course-lesson-note/course-lesson-note.controller.d.ts +53 -0
  142. package/dist/course-lesson-note/course-lesson-note.controller.d.ts.map +1 -0
  143. package/dist/course-lesson-note/course-lesson-note.controller.js +93 -0
  144. package/dist/course-lesson-note/course-lesson-note.controller.js.map +1 -0
  145. package/dist/course-lesson-note/course-lesson-note.mcp-tools.d.ts +27 -0
  146. package/dist/course-lesson-note/course-lesson-note.mcp-tools.d.ts.map +1 -0
  147. package/dist/course-lesson-note/course-lesson-note.mcp-tools.js +145 -0
  148. package/dist/course-lesson-note/course-lesson-note.mcp-tools.js.map +1 -0
  149. package/dist/course-lesson-note/course-lesson-note.module.d.ts +3 -0
  150. package/dist/course-lesson-note/course-lesson-note.module.d.ts.map +1 -0
  151. package/dist/course-lesson-note/course-lesson-note.module.js +26 -0
  152. package/dist/course-lesson-note/course-lesson-note.module.js.map +1 -0
  153. package/dist/course-lesson-note/course-lesson-note.service.d.ts +59 -0
  154. package/dist/course-lesson-note/course-lesson-note.service.d.ts.map +1 -0
  155. package/dist/course-lesson-note/course-lesson-note.service.js +195 -0
  156. package/dist/course-lesson-note/course-lesson-note.service.js.map +1 -0
  157. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.d.ts +6 -0
  158. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.d.ts.map +1 -0
  159. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.js +33 -0
  160. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.js.map +1 -0
  161. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.d.ts +6 -0
  162. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.d.ts.map +1 -0
  163. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.js +35 -0
  164. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.js.map +1 -0
  165. package/dist/dashboard/dashboard.mcp-tools.d.ts +10 -0
  166. package/dist/dashboard/dashboard.mcp-tools.d.ts.map +1 -0
  167. package/dist/dashboard/dashboard.mcp-tools.js +46 -0
  168. package/dist/dashboard/dashboard.mcp-tools.js.map +1 -0
  169. package/dist/dashboard/dashboard.module.d.ts.map +1 -1
  170. package/dist/dashboard/dashboard.module.js +2 -1
  171. package/dist/dashboard/dashboard.module.js.map +1 -1
  172. package/dist/enterprise/enterprise.mcp-tools.d.ts +82 -0
  173. package/dist/enterprise/enterprise.mcp-tools.d.ts.map +1 -0
  174. package/dist/enterprise/enterprise.mcp-tools.js +516 -0
  175. package/dist/enterprise/enterprise.mcp-tools.js.map +1 -0
  176. package/dist/enterprise/enterprise.module.d.ts.map +1 -1
  177. package/dist/enterprise/enterprise.module.js +2 -1
  178. package/dist/enterprise/enterprise.module.js.map +1 -1
  179. package/dist/enterprise/training/enterprise-training.module.d.ts.map +1 -1
  180. package/dist/enterprise/training/enterprise-training.module.js +11 -1
  181. package/dist/enterprise/training/enterprise-training.module.js.map +1 -1
  182. package/dist/enterprise/training/training-admin.controller.d.ts +2 -2
  183. package/dist/enterprise/training/training-admin.mcp-tools.d.ts +79 -0
  184. package/dist/enterprise/training/training-admin.mcp-tools.d.ts.map +1 -0
  185. package/dist/enterprise/training/training-admin.mcp-tools.js +620 -0
  186. package/dist/enterprise/training/training-admin.mcp-tools.js.map +1 -0
  187. package/dist/enterprise/training/training-admin.service.d.ts +2 -2
  188. package/dist/enterprise/training/training-instructor.mcp-tools.d.ts +47 -0
  189. package/dist/enterprise/training/training-instructor.mcp-tools.d.ts.map +1 -0
  190. package/dist/enterprise/training/training-instructor.mcp-tools.js +275 -0
  191. package/dist/enterprise/training/training-instructor.mcp-tools.js.map +1 -0
  192. package/dist/enterprise/training/training-student.controller.d.ts +24 -0
  193. package/dist/enterprise/training/training-student.controller.d.ts.map +1 -1
  194. package/dist/enterprise/training/training-student.controller.js +22 -0
  195. package/dist/enterprise/training/training-student.controller.js.map +1 -1
  196. package/dist/enterprise/training/training-student.mcp-tools.d.ts +27 -0
  197. package/dist/enterprise/training/training-student.mcp-tools.d.ts.map +1 -0
  198. package/dist/enterprise/training/training-student.mcp-tools.js +186 -0
  199. package/dist/enterprise/training/training-student.mcp-tools.js.map +1 -0
  200. package/dist/enterprise/training/training-student.service.d.ts +32 -0
  201. package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
  202. package/dist/enterprise/training/training-student.service.js +138 -0
  203. package/dist/enterprise/training/training-student.service.js.map +1 -1
  204. package/dist/evaluation/evaluation.controller.d.ts +4 -4
  205. package/dist/evaluation/evaluation.mcp-tools.d.ts +25 -0
  206. package/dist/evaluation/evaluation.mcp-tools.d.ts.map +1 -0
  207. package/dist/evaluation/evaluation.mcp-tools.js +220 -0
  208. package/dist/evaluation/evaluation.mcp-tools.js.map +1 -0
  209. package/dist/evaluation/evaluation.module.d.ts.map +1 -1
  210. package/dist/evaluation/evaluation.module.js +2 -1
  211. package/dist/evaluation/evaluation.module.js.map +1 -1
  212. package/dist/evaluation/evaluation.service.d.ts +4 -4
  213. package/dist/exam/dto/create-exam-question.dto.d.ts +2 -0
  214. package/dist/exam/dto/create-exam-question.dto.d.ts.map +1 -1
  215. package/dist/exam/dto/create-exam-question.dto.js +10 -0
  216. package/dist/exam/dto/create-exam-question.dto.js.map +1 -1
  217. package/dist/exam/dto/create-exam.dto.d.ts +2 -0
  218. package/dist/exam/dto/create-exam.dto.d.ts.map +1 -1
  219. package/dist/exam/dto/create-exam.dto.js +10 -0
  220. package/dist/exam/dto/create-exam.dto.js.map +1 -1
  221. package/dist/exam/dto/create-question-subject.dto.d.ts +5 -0
  222. package/dist/exam/dto/create-question-subject.dto.d.ts.map +1 -0
  223. package/dist/exam/dto/create-question-subject.dto.js +28 -0
  224. package/dist/exam/dto/create-question-subject.dto.js.map +1 -0
  225. package/dist/exam/exam-attempt.controller.d.ts +4 -0
  226. package/dist/exam/exam-attempt.controller.d.ts.map +1 -1
  227. package/dist/exam/exam-attempt.service.d.ts +7 -1
  228. package/dist/exam/exam-attempt.service.d.ts.map +1 -1
  229. package/dist/exam/exam-attempt.service.js +47 -17
  230. package/dist/exam/exam-attempt.service.js.map +1 -1
  231. package/dist/exam/exam.controller.d.ts +34 -0
  232. package/dist/exam/exam.controller.d.ts.map +1 -1
  233. package/dist/exam/exam.controller.js +27 -0
  234. package/dist/exam/exam.controller.js.map +1 -1
  235. package/dist/exam/exam.mcp-tools.d.ts +62 -0
  236. package/dist/exam/exam.mcp-tools.d.ts.map +1 -0
  237. package/dist/exam/exam.mcp-tools.js +430 -0
  238. package/dist/exam/exam.mcp-tools.js.map +1 -0
  239. package/dist/exam/exam.module.d.ts.map +1 -1
  240. package/dist/exam/exam.module.js +2 -1
  241. package/dist/exam/exam.module.js.map +1 -1
  242. package/dist/exam/exam.service.d.ts +38 -0
  243. package/dist/exam/exam.service.d.ts.map +1 -1
  244. package/dist/exam/exam.service.js +114 -17
  245. package/dist/exam/exam.service.js.map +1 -1
  246. package/dist/index.d.ts +9 -0
  247. package/dist/index.d.ts.map +1 -1
  248. package/dist/index.js +9 -0
  249. package/dist/index.js.map +1 -1
  250. package/dist/instructor/instructor.mcp-tools.d.ts +41 -0
  251. package/dist/instructor/instructor.mcp-tools.d.ts.map +1 -0
  252. package/dist/instructor/instructor.mcp-tools.js +326 -0
  253. package/dist/instructor/instructor.mcp-tools.js.map +1 -0
  254. package/dist/instructor/instructor.module.d.ts.map +1 -1
  255. package/dist/instructor/instructor.module.js +2 -1
  256. package/dist/instructor/instructor.module.js.map +1 -1
  257. package/dist/lms.module.d.ts.map +1 -1
  258. package/dist/lms.module.js +15 -0
  259. package/dist/lms.module.js.map +1 -1
  260. package/dist/realtime/lms-realtime.controller.d.ts +7 -0
  261. package/dist/realtime/lms-realtime.controller.d.ts.map +1 -0
  262. package/dist/realtime/lms-realtime.controller.js +34 -0
  263. package/dist/realtime/lms-realtime.controller.js.map +1 -0
  264. package/dist/realtime/lms-realtime.module.d.ts +3 -0
  265. package/dist/realtime/lms-realtime.module.d.ts.map +1 -0
  266. package/dist/realtime/lms-realtime.module.js +25 -0
  267. package/dist/realtime/lms-realtime.module.js.map +1 -0
  268. package/dist/realtime/lms-realtime.service.d.ts +36 -0
  269. package/dist/realtime/lms-realtime.service.d.ts.map +1 -0
  270. package/dist/realtime/lms-realtime.service.js +59 -0
  271. package/dist/realtime/lms-realtime.service.js.map +1 -0
  272. package/dist/realtime/lms-realtime.subscriber.d.ts +10 -0
  273. package/dist/realtime/lms-realtime.subscriber.d.ts.map +1 -0
  274. package/dist/realtime/lms-realtime.subscriber.js +70 -0
  275. package/dist/realtime/lms-realtime.subscriber.js.map +1 -0
  276. package/dist/reports/reports.mcp-tools.d.ts +10 -0
  277. package/dist/reports/reports.mcp-tools.d.ts.map +1 -0
  278. package/dist/reports/reports.mcp-tools.js +50 -0
  279. package/dist/reports/reports.mcp-tools.js.map +1 -0
  280. package/dist/reports/reports.module.d.ts.map +1 -1
  281. package/dist/reports/reports.module.js +2 -1
  282. package/dist/reports/reports.module.js.map +1 -1
  283. package/dist/training/training.mcp-tools.d.ts +20 -0
  284. package/dist/training/training.mcp-tools.d.ts.map +1 -0
  285. package/dist/training/training.mcp-tools.js +181 -0
  286. package/dist/training/training.mcp-tools.js.map +1 -0
  287. package/dist/training/training.module.d.ts.map +1 -1
  288. package/dist/training/training.module.js +2 -1
  289. package/dist/training/training.module.js.map +1 -1
  290. package/hedhog/data/integration_event_catalog.yaml +69 -0
  291. package/hedhog/data/menu.yaml +34 -0
  292. package/hedhog/data/route.yaml +2351 -0
  293. package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +168 -103
  294. package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +80 -1
  295. package/hedhog/frontend/app/_components/course-picker.tsx.ejs +228 -0
  296. package/hedhog/frontend/app/_lib/hooks/use-lms-realtime-refresh.ts.ejs +58 -0
  297. package/hedhog/frontend/app/achievements/page.tsx.ejs +844 -0
  298. package/hedhog/frontend/app/bitcodes/page.tsx.ejs +1010 -0
  299. package/hedhog/frontend/app/certificates/issued/page.tsx.ejs +61 -2
  300. package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +7 -0
  301. package/hedhog/frontend/app/classes/page.tsx.ejs +55 -2060
  302. package/hedhog/frontend/app/courses/[id]/_components/CourseRelationsCard.tsx.ejs +28 -0
  303. package/hedhog/frontend/app/courses/[id]/_components/course-edit-types.ts.ejs +1 -0
  304. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +0 -9
  305. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +80 -66
  306. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +583 -8
  307. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +527 -57
  308. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -1
  309. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-context-menu.tsx.ejs +106 -4
  310. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +2 -1
  311. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +11 -1
  312. package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +53 -6
  313. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +13 -2
  314. package/hedhog/frontend/app/courses/page.tsx.ejs +175 -29
  315. package/hedhog/frontend/app/enterprise/_components/enterprise-course-create-sheet.tsx.ejs +3 -0
  316. package/hedhog/frontend/app/enterprise/_components/enterprise-course-edit-sheet.tsx.ejs +7 -0
  317. package/hedhog/frontend/app/exams/[id]/questions/page.tsx.ejs +169 -2
  318. package/hedhog/frontend/app/exams/page.tsx.ejs +77 -22
  319. package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +1 -0
  320. package/hedhog/frontend/app/instructors/page.tsx.ejs +1 -0
  321. package/hedhog/frontend/app/paths/page.tsx.ejs +6 -24
  322. package/hedhog/frontend/app/training/page.tsx.ejs +6 -24
  323. package/hedhog/frontend/messages/en.json +314 -12
  324. package/hedhog/frontend/messages/pt.json +314 -12
  325. package/hedhog/query/triggers.sql +53 -0
  326. package/hedhog/table/achievement.yaml +46 -0
  327. package/hedhog/table/bitcode_wallet.yaml +18 -0
  328. package/hedhog/table/bitcode_wallet_transaction.yaml +22 -0
  329. package/hedhog/table/certificate.yaml +3 -0
  330. package/hedhog/table/course.yaml +4 -0
  331. package/hedhog/table/course_file.yaml +23 -0
  332. package/hedhog/table/course_lesson.yaml +5 -0
  333. package/hedhog/table/course_lesson_discussion_like.yaml +21 -0
  334. package/hedhog/table/course_lesson_discussion_topic.yaml +35 -0
  335. package/hedhog/table/course_lesson_note.yaml +34 -0
  336. package/hedhog/table/exam.yaml +5 -0
  337. package/hedhog/table/learning_path_enrollment.yaml +6 -0
  338. package/hedhog/table/question.yaml +10 -0
  339. package/hedhog/table/question_subject.yaml +17 -0
  340. package/hedhog/table/student_activity_streak.yaml +25 -0
  341. package/package.json +7 -7
  342. package/src/achievement/achievement.controller.ts +60 -0
  343. package/src/achievement/achievement.mcp-tools.ts +108 -0
  344. package/src/achievement/achievement.module.ts +13 -0
  345. package/src/achievement/achievement.service.ts +252 -0
  346. package/src/achievement/dto/create-achievement.dto.ts +50 -0
  347. package/src/achievement/dto/update-achievement.dto.ts +47 -0
  348. package/src/bitcode-wallet/bitcode-wallet.controller.ts +69 -0
  349. package/src/bitcode-wallet/bitcode-wallet.mcp-tools.ts +107 -0
  350. package/src/bitcode-wallet/bitcode-wallet.module.ts +13 -0
  351. package/src/bitcode-wallet/bitcode-wallet.service.ts +361 -0
  352. package/src/bitcode-wallet/dto/create-bitcode-wallet-transaction.dto.ts +27 -0
  353. package/src/bitcode-wallet/dto/create-bitcode-wallet.dto.ts +7 -0
  354. package/src/bitcode-wallet/dto/update-bitcode-wallet-transaction.dto.ts +28 -0
  355. package/src/bitcode-wallet/dto/update-bitcode-wallet.dto.ts +8 -0
  356. package/src/certificate/certificate.controller.ts +20 -11
  357. package/src/certificate/certificate.mcp-tools.ts +131 -0
  358. package/src/certificate/certificate.module.ts +2 -1
  359. package/src/certificate/certificate.service.ts +95 -4
  360. package/src/certificate/dto/update-certificate-public-access.dto.ts +6 -0
  361. package/src/class-group/class-group.mcp-tools.ts +435 -0
  362. package/src/class-group/class-group.module.ts +2 -1
  363. package/src/class-group/class-group.service.ts +51 -1
  364. package/src/course/course-operations-integration.service.ts +520 -0
  365. package/src/course/course-structure.controller.ts +22 -8
  366. package/src/course/course-structure.service.ts +215 -23
  367. package/src/course/course.mcp-tools.ts +409 -0
  368. package/src/course/course.module.ts +8 -1
  369. package/src/course/course.service.ts +106 -27
  370. package/src/course/dto/create-course.dto.ts +8 -0
  371. package/src/course/dto/update-course-resources.dto.ts +39 -0
  372. package/src/course-lesson-discussion/course-lesson-discussion.controller.ts +55 -0
  373. package/src/course-lesson-discussion/course-lesson-discussion.mcp-tools.ts +75 -0
  374. package/src/course-lesson-discussion/course-lesson-discussion.module.ts +13 -0
  375. package/src/course-lesson-discussion/course-lesson-discussion.service.ts +354 -0
  376. package/src/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.ts +16 -0
  377. package/src/course-lesson-note/course-lesson-note.controller.ts +68 -0
  378. package/src/course-lesson-note/course-lesson-note.mcp-tools.ts +96 -0
  379. package/src/course-lesson-note/course-lesson-note.module.ts +13 -0
  380. package/src/course-lesson-note/course-lesson-note.service.ts +248 -0
  381. package/src/course-lesson-note/dto/create-course-lesson-note.dto.ts +16 -0
  382. package/src/course-lesson-note/dto/update-course-lesson-note.dto.ts +18 -0
  383. package/src/dashboard/dashboard.mcp-tools.ts +23 -0
  384. package/src/dashboard/dashboard.module.ts +2 -1
  385. package/src/enterprise/enterprise.mcp-tools.ts +403 -0
  386. package/src/enterprise/enterprise.module.ts +2 -1
  387. package/src/enterprise/training/enterprise-training.module.ts +11 -1
  388. package/src/enterprise/training/training-admin.mcp-tools.ts +479 -0
  389. package/src/enterprise/training/training-instructor.mcp-tools.ts +210 -0
  390. package/src/enterprise/training/training-student.controller.ts +17 -1
  391. package/src/enterprise/training/training-student.mcp-tools.ts +136 -0
  392. package/src/enterprise/training/training-student.service.ts +167 -1
  393. package/src/evaluation/evaluation.mcp-tools.ts +155 -0
  394. package/src/evaluation/evaluation.module.ts +2 -1
  395. package/src/exam/dto/create-exam-question.dto.ts +8 -0
  396. package/src/exam/dto/create-exam.dto.ts +8 -0
  397. package/src/exam/dto/create-question-subject.dto.ts +12 -0
  398. package/src/exam/exam-attempt.service.ts +46 -14
  399. package/src/exam/exam.controller.ts +19 -0
  400. package/src/exam/exam.mcp-tools.ts +337 -0
  401. package/src/exam/exam.module.ts +2 -1
  402. package/src/exam/exam.service.ts +121 -0
  403. package/src/index.ts +9 -0
  404. package/src/instructor/instructor.mcp-tools.ts +243 -0
  405. package/src/instructor/instructor.module.ts +2 -1
  406. package/src/lms.module.ts +15 -1
  407. package/src/realtime/lms-realtime.controller.ts +12 -0
  408. package/src/realtime/lms-realtime.module.ts +12 -0
  409. package/src/realtime/lms-realtime.service.ts +98 -0
  410. package/src/realtime/lms-realtime.subscriber.ts +61 -0
  411. package/src/reports/reports.mcp-tools.ts +27 -0
  412. package/src/reports/reports.module.ts +2 -1
  413. package/src/training/training.mcp-tools.ts +128 -0
  414. package/src/training/training.module.ts +2 -1
@@ -57,6 +57,7 @@ import {
57
57
  type CourseCategoryOption,
58
58
  type CourseSheetFormValues,
59
59
  } from './course-form-sheet';
60
+ import { CoursePicker } from './course-picker';
60
61
 
61
62
  // ── Types ─────────────────────────────────────────────────────────────────────
62
63
 
@@ -104,14 +105,6 @@ export type ApiClass = {
104
105
  sessionRecurrenceSummary?: SessionRecurrenceSummary | null;
105
106
  };
106
107
 
107
- type ApiCourseList = {
108
- data: Array<{ id: number; title: string }>;
109
- total?: number;
110
- page?: number;
111
- pageSize?: number;
112
- lastPage?: number;
113
- };
114
-
115
108
  type ApiCategoryList = {
116
109
  data: ApiCategory[];
117
110
  total: number;
@@ -131,6 +124,21 @@ type ApiCreatedCourse = {
131
124
  title: string;
132
125
  };
133
126
 
127
+ type ApiCourseDetail = {
128
+ id: number;
129
+ code?: string;
130
+ slug?: string;
131
+ title: string;
132
+ description?: string;
133
+ level?: 'beginner' | 'intermediate' | 'advanced';
134
+ status?: 'draft' | 'published' | 'archived';
135
+ categories?: string[];
136
+ primaryColor?: string | null;
137
+ secondaryColor?: string | null;
138
+ logoFileId?: number | null;
139
+ operationsProjectId?: number | null;
140
+ };
141
+
134
142
  type InstructorOption = {
135
143
  id: number;
136
144
  name: string;
@@ -367,6 +375,18 @@ function toApiCourseStatus(status: CourseSheetFormValues['status']) {
367
375
  return 'archived';
368
376
  }
369
377
 
378
+ function toCourseFormLevel(level?: string): CourseSheetFormValues['nivel'] {
379
+ if (level === 'intermediate') return 'intermediario';
380
+ if (level === 'advanced') return 'avancado';
381
+ return 'iniciante';
382
+ }
383
+
384
+ function toCourseFormStatus(status?: string): CourseSheetFormValues['status'] {
385
+ if (status === 'published') return 'ativo';
386
+ if (status === 'archived') return 'arquivado';
387
+ return 'rascunho';
388
+ }
389
+
370
390
  // ── Constants ─────────────────────────────────────────────────────────────────
371
391
 
372
392
  const TIME_OPTIONS = Array.from({ length: 32 }, (_, index) => {
@@ -558,6 +578,8 @@ export function ClassFormSheet({
558
578
  null
559
579
  );
560
580
  const [courseSheetOpen, setCourseSheetOpen] = useState(false);
581
+ const [editingCourseId, setEditingCourseId] = useState<number | null>(null);
582
+ const [coursePickerRefreshToken, setCoursePickerRefreshToken] = useState(0);
561
583
  const [customRecurrenceDialogOpen, setCustomRecurrenceDialogOpen] =
562
584
  useState(false);
563
585
  const [previousRecurrenceMode, setPreviousRecurrenceMode] =
@@ -1024,32 +1046,71 @@ export function ClassFormSheet({
1024
1046
  description: data.descricao,
1025
1047
  level: toApiCourseLevel(data.nivel),
1026
1048
  status: toApiCourseStatus(data.status),
1049
+ offeringType: 'scheduled' as const,
1027
1050
  categorySlugs: data.categorias,
1028
1051
  primaryColor: data.primaryColor,
1029
1052
  primaryContrastColor: getContrastColor(data.primaryColor),
1030
1053
  secondaryColor: data.secondaryColor,
1031
1054
  secondaryContrastColor: getContrastColor(data.secondaryColor),
1055
+ operationsProjectId: data.operationsProjectId
1056
+ ? Number(data.operationsProjectId)
1057
+ : null,
1032
1058
  };
1033
1059
 
1034
- const response = await request<ApiCreatedCourse>({
1035
- url: '/lms/courses',
1036
- method: 'POST',
1037
- data: payload,
1038
- });
1060
+ if (editingCourseId) {
1061
+ await request({
1062
+ url: `/lms/courses/${editingCourseId}`,
1063
+ method: 'PATCH',
1064
+ data: {
1065
+ slug: data.nomeInterno.trim().toLowerCase(),
1066
+ title: data.tituloComercial,
1067
+ description: data.descricao,
1068
+ level: toApiCourseLevel(data.nivel),
1069
+ status: toApiCourseStatus(data.status),
1070
+ categorySlugs: data.categorias,
1071
+ primaryColor: data.primaryColor,
1072
+ primaryContrastColor: getContrastColor(data.primaryColor),
1073
+ secondaryColor: data.secondaryColor,
1074
+ secondaryContrastColor: getContrastColor(data.secondaryColor),
1075
+ operationsProjectId: data.operationsProjectId
1076
+ ? Number(data.operationsProjectId)
1077
+ : null,
1078
+ logoFileId: data.logoFileId ?? null,
1079
+ },
1080
+ });
1039
1081
 
1040
- const createdCourse = response.data;
1041
- form.setValue('courseId', createdCourse.id, {
1042
- shouldDirty: true,
1043
- shouldTouch: true,
1044
- shouldValidate: true,
1045
- });
1046
- form.setValue('curso', createdCourse.title, {
1047
- shouldDirty: true,
1048
- shouldTouch: true,
1049
- shouldValidate: false,
1050
- });
1082
+ form.setValue('curso', data.tituloComercial, {
1083
+ shouldDirty: true,
1084
+ shouldTouch: true,
1085
+ shouldValidate: false,
1086
+ });
1087
+
1088
+ toast.success(courseSheetT('toasts.courseUpdated'));
1089
+ } else {
1090
+ const response = await request<ApiCreatedCourse>({
1091
+ url: '/lms/courses',
1092
+ method: 'POST',
1093
+ data: payload,
1094
+ });
1095
+
1096
+ const createdCourse = response.data;
1097
+ form.setValue('courseId', createdCourse.id, {
1098
+ shouldDirty: true,
1099
+ shouldTouch: true,
1100
+ shouldValidate: true,
1101
+ });
1102
+ form.setValue('curso', createdCourse.title, {
1103
+ shouldDirty: true,
1104
+ shouldTouch: true,
1105
+ shouldValidate: false,
1106
+ });
1107
+
1108
+ toast.success(courseSheetT('toasts.courseCreated'));
1109
+ }
1110
+
1111
+ setCoursePickerRefreshToken((current) => current + 1);
1112
+ setEditingCourseId(null);
1051
1113
  setCourseSheetOpen(false);
1052
- toast.success(courseSheetT('toasts.courseCreated'));
1053
1114
  } catch {
1054
1115
  toast.error(t('messages.classCreateCourseError'));
1055
1116
  } finally {
@@ -1183,81 +1244,80 @@ export function ClassFormSheet({
1183
1244
  {t('form.fields.course.label')}{' '}
1184
1245
  <span className="text-destructive">*</span>
1185
1246
  </FieldLabel>
1186
- <div className="flex items-end gap-2">
1187
- <div className="min-w-0 flex-1">
1188
- <EntityPicker<{ id: number; title: string }, TurmaForm>
1189
- form={form}
1190
- name="courseId"
1191
- valueType="number"
1192
- placeholder={t('form.fields.course.placeholder')}
1193
- entityLabel={t('form.fields.course.label')}
1194
- initialSelectedLabel={selectedCourseTitle}
1195
- searchPlaceholder={t('form.fields.course.placeholder')}
1196
- emptyStateDescription={t(
1197
- 'components.entityPicker.courses.empty'
1198
- )}
1199
- loadingLabel={t(
1200
- 'components.entityPicker.courses.loading'
1201
- )}
1202
- noResultsLabel={t(
1203
- 'components.entityPicker.courses.empty'
1204
- )}
1205
- disabled={lockCourse}
1206
- showCreateButton={false}
1207
- onChange={(value, option) => {
1208
- const cId =
1209
- typeof value === 'number' ? value : undefined;
1210
- const cTitle =
1211
- option && typeof option.title === 'string'
1212
- ? option.title
1213
- : '';
1214
- form.setValue('courseId', cId, {
1215
- shouldDirty: true,
1216
- shouldTouch: true,
1217
- shouldValidate: true,
1218
- });
1219
- form.setValue('curso', cTitle, {
1220
- shouldDirty: true,
1221
- shouldTouch: true,
1222
- shouldValidate: false,
1223
- });
1224
- }}
1225
- loadOptions={async ({ page, pageSize, search }) => {
1226
- const response = await request<ApiCourseList>({
1227
- url: '/lms/courses',
1228
- method: 'GET',
1229
- params: {
1230
- page,
1231
- pageSize,
1232
- ...(search.trim()
1233
- ? { search: search.trim() }
1234
- : {}),
1235
- },
1236
- });
1237
- return {
1238
- items: response.data?.data ?? [],
1239
- hasMore: page < (response.data?.lastPage ?? 1),
1240
- };
1241
- }}
1242
- getOptionValue={(option) => option.id}
1243
- getOptionLabel={(option) => option.title}
1244
- />
1245
- </div>
1246
- <Button
1247
- type="button"
1248
- variant="outline"
1249
- size="icon"
1250
- className="shrink-0"
1251
- disabled={lockCourse}
1252
- onClick={() => {
1253
- courseForm.reset(DEFAULT_COURSE_FORM_VALUES);
1254
- setCourseSheetOpen(true);
1255
- }}
1256
- aria-label="Cadastrar novo curso"
1257
- >
1258
- <Plus className="h-4 w-4" />
1259
- </Button>
1260
- </div>
1247
+ <CoursePicker<TurmaForm>
1248
+ form={form}
1249
+ name="courseId"
1250
+ selectedCourseTitle={selectedCourseTitle}
1251
+ placeholder={t('form.fields.course.placeholder')}
1252
+ entityLabel={t('form.fields.course.label')}
1253
+ searchPlaceholder={t('form.fields.course.placeholder')}
1254
+ emptyStateDescription={t(
1255
+ 'components.entityPicker.courses.empty'
1256
+ )}
1257
+ loadingLabel={t('components.entityPicker.courses.loading')}
1258
+ noResultsLabel={t('components.entityPicker.courses.empty')}
1259
+ disabled={lockCourse}
1260
+ allowClearSelection={!lockCourse}
1261
+ showCreateButton={!lockCourse}
1262
+ showEditButton={!lockCourse}
1263
+ searchEndpoint="/lms/courses"
1264
+ searchExtraParams={{
1265
+ offeringTypes: 'scheduled,blended,on_demand',
1266
+ }}
1267
+ refreshToken={coursePickerRefreshToken}
1268
+ isOptionDisabled={(option) =>
1269
+ option.offeringType === 'on_demand'
1270
+ }
1271
+ onSelectionChange={(value, option) => {
1272
+ const cId = typeof value === 'number' ? value : undefined;
1273
+ const cTitle =
1274
+ option && typeof option.title === 'string'
1275
+ ? option.title
1276
+ : '';
1277
+
1278
+ form.setValue('courseId', cId, {
1279
+ shouldDirty: true,
1280
+ shouldTouch: true,
1281
+ shouldValidate: true,
1282
+ });
1283
+ form.setValue('curso', cTitle, {
1284
+ shouldDirty: true,
1285
+ shouldTouch: true,
1286
+ shouldValidate: false,
1287
+ });
1288
+ }}
1289
+ onCreateClick={() => {
1290
+ setEditingCourseId(null);
1291
+ courseForm.reset(DEFAULT_COURSE_FORM_VALUES);
1292
+ setCourseSheetOpen(true);
1293
+ }}
1294
+ onEditClick={async (selected) => {
1295
+ if (!selected?.id) return;
1296
+
1297
+ const response = await request<ApiCourseDetail>({
1298
+ url: `/lms/courses/${selected.id}`,
1299
+ method: 'GET',
1300
+ });
1301
+
1302
+ const detail = response.data;
1303
+ setEditingCourseId(detail.id);
1304
+ courseForm.reset({
1305
+ nomeInterno: detail.slug ?? detail.code ?? '',
1306
+ tituloComercial: detail.title ?? '',
1307
+ descricao: detail.description ?? '',
1308
+ nivel: toCourseFormLevel(detail.level),
1309
+ status: toCourseFormStatus(detail.status),
1310
+ categorias: detail.categories ?? [],
1311
+ operationsProjectId: detail.operationsProjectId
1312
+ ? String(detail.operationsProjectId)
1313
+ : '',
1314
+ primaryColor: detail.primaryColor ?? '#1D4ED8',
1315
+ secondaryColor: detail.secondaryColor ?? '#111827',
1316
+ logoFileId: detail.logoFileId ?? null,
1317
+ });
1318
+ setCourseSheetOpen(true);
1319
+ }}
1320
+ />
1261
1321
  </Field>
1262
1322
  </div>
1263
1323
 
@@ -2063,10 +2123,15 @@ export function ClassFormSheet({
2063
2123
 
2064
2124
  {/* Course create sheet */}
2065
2125
  <CourseFormSheet
2066
- key="class-form-sheet-course-create"
2126
+ key={`class-form-sheet-course-${editingCourseId ?? 'create'}`}
2067
2127
  open={courseSheetOpen}
2068
- onOpenChange={setCourseSheetOpen}
2069
- editing={false}
2128
+ onOpenChange={(nextOpen) => {
2129
+ setCourseSheetOpen(nextOpen);
2130
+ if (!nextOpen) {
2131
+ setEditingCourseId(null);
2132
+ }
2133
+ }}
2134
+ editing={Boolean(editingCourseId)}
2070
2135
  saving={savingCourse}
2071
2136
  form={courseForm}
2072
2137
  onSubmit={onSubmitCourse}
@@ -15,6 +15,7 @@ import {
15
15
  FieldError,
16
16
  FieldLabel,
17
17
  } from '@/components/ui/field';
18
+ import { EntityPicker } from '@/components/ui/entity-picker';
18
19
  import { Input } from '@/components/ui/input';
19
20
  import {
20
21
  Popover,
@@ -37,7 +38,7 @@ import {
37
38
  SheetTitle,
38
39
  } from '@/components/ui/sheet';
39
40
  import { Textarea } from '@/components/ui/textarea';
40
- import { useApp } from '@hed-hog/next-app-provider';
41
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
41
42
  import {
42
43
  ChevronsUpDown,
43
44
  ImageIcon,
@@ -55,6 +56,15 @@ export type CourseCategoryOption = {
55
56
  label: string;
56
57
  };
57
58
 
59
+ type OperationsProjectOption = {
60
+ id: number;
61
+ code?: string | null;
62
+ name: string;
63
+ label?: string;
64
+ clientName?: string | null;
65
+ status?: string | null;
66
+ };
67
+
58
68
  // ---------------------------------------------------------------------------
59
69
  // Color extraction utilities
60
70
  // ---------------------------------------------------------------------------
@@ -222,6 +232,7 @@ export function getCourseSheetSchema(t: (key: string) => string) {
222
232
  nivel: z.enum(['iniciante', 'intermediario', 'avancado']).optional(),
223
233
  status: z.enum(['ativo', 'rascunho', 'arquivado']).optional(),
224
234
  categorias: z.array(z.string()).optional(),
235
+ operationsProjectId: z.string().optional(),
225
236
  primaryColor: z.string().optional(),
226
237
  secondaryColor: z.string().optional(),
227
238
  logoFileId: z.number().nullable().optional(),
@@ -236,6 +247,7 @@ export type CourseSheetFormValues = {
236
247
  nivel: 'iniciante' | 'intermediario' | 'avancado';
237
248
  status: 'ativo' | 'rascunho' | 'arquivado';
238
249
  categorias: string[];
250
+ operationsProjectId: string;
239
251
  primaryColor: string;
240
252
  secondaryColor: string;
241
253
  logoFileId?: number | null;
@@ -249,6 +261,7 @@ export const DEFAULT_COURSE_FORM_VALUES: CourseSheetFormValues = {
249
261
  nivel: 'iniciante',
250
262
  status: 'rascunho',
251
263
  categorias: [],
264
+ operationsProjectId: '',
252
265
  primaryColor: '#1D4ED8',
253
266
  secondaryColor: '#111827',
254
267
  logoFileId: null,
@@ -312,6 +325,36 @@ export function CourseFormSheet({
312
325
  const [colorExtracting, setColorExtracting] = useState(false);
313
326
  const logoInputRef = useRef<HTMLInputElement>(null);
314
327
  const colorExtractionRef = useRef<{ cancelled: boolean } | null>(null);
328
+ const { data: operationsProjectsData } = useQuery<
329
+ { data: OperationsProjectOption[] } | OperationsProjectOption[]
330
+ >({
331
+ queryKey: ['lms-course-form-operations-projects'],
332
+ enabled: open,
333
+ queryFn: async () => {
334
+ try {
335
+ const response = await request<
336
+ { data: OperationsProjectOption[] } | OperationsProjectOption[]
337
+ >({
338
+ url: '/operations/projects/options?pageSize=200&sortField=name&sortOrder=asc',
339
+ method: 'GET',
340
+ });
341
+ return response.data;
342
+ } catch {
343
+ return { data: [] };
344
+ }
345
+ },
346
+ initialData: { data: [] },
347
+ });
348
+ const operationsProjectOptions = (
349
+ Array.isArray(operationsProjectsData)
350
+ ? operationsProjectsData
351
+ : (operationsProjectsData?.data ?? [])
352
+ ).map((project) => ({
353
+ value: String(project.id),
354
+ label: project.name,
355
+ description: project.code ?? project.clientName ?? null,
356
+ meta: project.status ?? null,
357
+ }));
315
358
 
316
359
  useEffect(() => {
317
360
  if (!initialLogoFileId) {
@@ -538,6 +581,42 @@ export function CourseFormSheet({
538
581
  <FieldError>{form.formState.errors.descricao?.message}</FieldError>
539
582
  </Field>
540
583
 
584
+ <Field>
585
+ <FieldLabel>Projeto vinculado</FieldLabel>
586
+ <Controller
587
+ name="operationsProjectId"
588
+ control={form.control}
589
+ render={({ field }) => (
590
+ <EntityPicker<{
591
+ value: string;
592
+ label: string;
593
+ description?: string | null;
594
+ meta?: string | null;
595
+ }>
596
+ value={field.value}
597
+ onChange={(value) => field.onChange(String(value ?? ''))}
598
+ options={operationsProjectOptions}
599
+ placeholder="Selecione um projeto do Operations"
600
+ searchPlaceholder="Buscar projeto..."
601
+ entityLabel="projeto"
602
+ emptyStateDescription="Nenhum projeto disponível"
603
+ getOptionValue={(option) => option.value}
604
+ getOptionLabel={(option) => option.label}
605
+ getOptionDescription={(option) =>
606
+ option.description || option.meta || undefined
607
+ }
608
+ />
609
+ )}
610
+ />
611
+ <FieldDescription>
612
+ Quando o curso estiver vinculado a um projeto, cada nova aula gera
613
+ uma tarefa automaticamente.
614
+ </FieldDescription>
615
+ <FieldError>
616
+ {form.formState.errors.operationsProjectId?.message}
617
+ </FieldError>
618
+ </Field>
619
+
541
620
  <div className="grid grid-cols-2 gap-4">
542
621
  <Field>
543
622
  <FieldLabel>{t('form.fields.level.label')}</FieldLabel>