@hed-hog/lms 0.0.349 → 0.0.351

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 (496) 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 +24 -2
  58. package/dist/certificate/certificate.controller.d.ts.map +1 -1
  59. package/dist/certificate/certificate.controller.js +20 -6
  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 +30 -4
  69. package/dist/certificate/certificate.service.d.ts.map +1 -1
  70. package/dist/certificate/certificate.service.js +157 -8
  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.mcp-tools.d.ts +87 -0
  77. package/dist/class-group/class-group.mcp-tools.d.ts.map +1 -0
  78. package/dist/class-group/class-group.mcp-tools.js +553 -0
  79. package/dist/class-group/class-group.mcp-tools.js.map +1 -0
  80. package/dist/class-group/class-group.module.d.ts.map +1 -1
  81. package/dist/class-group/class-group.module.js +2 -1
  82. package/dist/class-group/class-group.module.js.map +1 -1
  83. package/dist/class-group/class-group.service.d.ts +3 -1
  84. package/dist/class-group/class-group.service.d.ts.map +1 -1
  85. package/dist/class-group/class-group.service.js +45 -2
  86. package/dist/class-group/class-group.service.js.map +1 -1
  87. package/dist/course/course-operations-integration.service.d.ts +40 -0
  88. package/dist/course/course-operations-integration.service.d.ts.map +1 -0
  89. package/dist/course/course-operations-integration.service.js +372 -0
  90. package/dist/course/course-operations-integration.service.js.map +1 -0
  91. package/dist/course/course-structure.controller.d.ts +67 -14
  92. package/dist/course/course-structure.controller.d.ts.map +1 -1
  93. package/dist/course/course-structure.controller.js +45 -2
  94. package/dist/course/course-structure.controller.js.map +1 -1
  95. package/dist/course/course-structure.service.d.ts +58 -9
  96. package/dist/course/course-structure.service.d.ts.map +1 -1
  97. package/dist/course/course-structure.service.js +260 -62
  98. package/dist/course/course-structure.service.js.map +1 -1
  99. package/dist/course/course-video-conversion.service.d.ts +37 -0
  100. package/dist/course/course-video-conversion.service.d.ts.map +1 -0
  101. package/dist/course/course-video-conversion.service.js +308 -0
  102. package/dist/course/course-video-conversion.service.js.map +1 -0
  103. package/dist/course/course.controller.d.ts +29 -0
  104. package/dist/course/course.controller.d.ts.map +1 -1
  105. package/dist/course/course.controller.js +23 -0
  106. package/dist/course/course.controller.js.map +1 -1
  107. package/dist/course/course.mcp-tools.d.ts +90 -0
  108. package/dist/course/course.mcp-tools.d.ts.map +1 -0
  109. package/dist/course/course.mcp-tools.js +520 -0
  110. package/dist/course/course.mcp-tools.js.map +1 -0
  111. package/dist/course/course.module.d.ts.map +1 -1
  112. package/dist/course/course.module.js +23 -3
  113. package/dist/course/course.module.js.map +1 -1
  114. package/dist/course/course.service.d.ts +30 -1
  115. package/dist/course/course.service.d.ts.map +1 -1
  116. package/dist/course/course.service.js +159 -70
  117. package/dist/course/course.service.js.map +1 -1
  118. package/dist/course/dto/create-course-structure-lesson.dto.d.ts +5 -1
  119. package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
  120. package/dist/course/dto/create-course-structure-lesson.dto.js +16 -2
  121. package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
  122. package/dist/course/dto/create-course.dto.d.ts +2 -0
  123. package/dist/course/dto/create-course.dto.d.ts.map +1 -1
  124. package/dist/course/dto/create-course.dto.js +16 -0
  125. package/dist/course/dto/create-course.dto.js.map +1 -1
  126. package/dist/course/dto/update-course-resources.dto.d.ts +11 -0
  127. package/dist/course/dto/update-course-resources.dto.d.ts.map +1 -0
  128. package/dist/course/dto/update-course-resources.dto.js +51 -0
  129. package/dist/course/dto/update-course-resources.dto.js.map +1 -0
  130. package/dist/course-lesson-discussion/course-lesson-discussion.controller.d.ts +23 -0
  131. package/dist/course-lesson-discussion/course-lesson-discussion.controller.d.ts.map +1 -0
  132. package/dist/course-lesson-discussion/course-lesson-discussion.controller.js +78 -0
  133. package/dist/course-lesson-discussion/course-lesson-discussion.controller.js.map +1 -0
  134. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.d.ts +22 -0
  135. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.d.ts.map +1 -0
  136. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.js +120 -0
  137. package/dist/course-lesson-discussion/course-lesson-discussion.mcp-tools.js.map +1 -0
  138. package/dist/course-lesson-discussion/course-lesson-discussion.module.d.ts +3 -0
  139. package/dist/course-lesson-discussion/course-lesson-discussion.module.d.ts.map +1 -0
  140. package/dist/course-lesson-discussion/course-lesson-discussion.module.js +26 -0
  141. package/dist/course-lesson-discussion/course-lesson-discussion.module.js.map +1 -0
  142. package/dist/course-lesson-discussion/course-lesson-discussion.service.d.ts +49 -0
  143. package/dist/course-lesson-discussion/course-lesson-discussion.service.d.ts.map +1 -0
  144. package/dist/course-lesson-discussion/course-lesson-discussion.service.js +272 -0
  145. package/dist/course-lesson-discussion/course-lesson-discussion.service.js.map +1 -0
  146. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.d.ts +6 -0
  147. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.d.ts.map +1 -0
  148. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.js +33 -0
  149. package/dist/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.js.map +1 -0
  150. package/dist/course-lesson-note/course-lesson-note.controller.d.ts +53 -0
  151. package/dist/course-lesson-note/course-lesson-note.controller.d.ts.map +1 -0
  152. package/dist/course-lesson-note/course-lesson-note.controller.js +93 -0
  153. package/dist/course-lesson-note/course-lesson-note.controller.js.map +1 -0
  154. package/dist/course-lesson-note/course-lesson-note.mcp-tools.d.ts +27 -0
  155. package/dist/course-lesson-note/course-lesson-note.mcp-tools.d.ts.map +1 -0
  156. package/dist/course-lesson-note/course-lesson-note.mcp-tools.js +145 -0
  157. package/dist/course-lesson-note/course-lesson-note.mcp-tools.js.map +1 -0
  158. package/dist/course-lesson-note/course-lesson-note.module.d.ts +3 -0
  159. package/dist/course-lesson-note/course-lesson-note.module.d.ts.map +1 -0
  160. package/dist/course-lesson-note/course-lesson-note.module.js +26 -0
  161. package/dist/course-lesson-note/course-lesson-note.module.js.map +1 -0
  162. package/dist/course-lesson-note/course-lesson-note.service.d.ts +59 -0
  163. package/dist/course-lesson-note/course-lesson-note.service.d.ts.map +1 -0
  164. package/dist/course-lesson-note/course-lesson-note.service.js +195 -0
  165. package/dist/course-lesson-note/course-lesson-note.service.js.map +1 -0
  166. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.d.ts +6 -0
  167. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.d.ts.map +1 -0
  168. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.js +33 -0
  169. package/dist/course-lesson-note/dto/create-course-lesson-note.dto.js.map +1 -0
  170. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.d.ts +6 -0
  171. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.d.ts.map +1 -0
  172. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.js +35 -0
  173. package/dist/course-lesson-note/dto/update-course-lesson-note.dto.js.map +1 -0
  174. package/dist/dashboard/dashboard.mcp-tools.d.ts +10 -0
  175. package/dist/dashboard/dashboard.mcp-tools.d.ts.map +1 -0
  176. package/dist/dashboard/dashboard.mcp-tools.js +46 -0
  177. package/dist/dashboard/dashboard.mcp-tools.js.map +1 -0
  178. package/dist/dashboard/dashboard.module.d.ts.map +1 -1
  179. package/dist/dashboard/dashboard.module.js +2 -1
  180. package/dist/dashboard/dashboard.module.js.map +1 -1
  181. package/dist/enterprise/enterprise.controller.d.ts +3 -3
  182. package/dist/enterprise/enterprise.controller.d.ts.map +1 -1
  183. package/dist/enterprise/enterprise.controller.js +0 -1
  184. package/dist/enterprise/enterprise.controller.js.map +1 -1
  185. package/dist/enterprise/enterprise.mcp-tools.d.ts +82 -0
  186. package/dist/enterprise/enterprise.mcp-tools.d.ts.map +1 -0
  187. package/dist/enterprise/enterprise.mcp-tools.js +516 -0
  188. package/dist/enterprise/enterprise.mcp-tools.js.map +1 -0
  189. package/dist/enterprise/enterprise.module.d.ts.map +1 -1
  190. package/dist/enterprise/enterprise.module.js +2 -1
  191. package/dist/enterprise/enterprise.module.js.map +1 -1
  192. package/dist/enterprise/enterprise.service.d.ts +3 -3
  193. package/dist/enterprise/training/enterprise-training.module.d.ts.map +1 -1
  194. package/dist/enterprise/training/enterprise-training.module.js +11 -1
  195. package/dist/enterprise/training/enterprise-training.module.js.map +1 -1
  196. package/dist/enterprise/training/training-admin.mcp-tools.d.ts +79 -0
  197. package/dist/enterprise/training/training-admin.mcp-tools.d.ts.map +1 -0
  198. package/dist/enterprise/training/training-admin.mcp-tools.js +620 -0
  199. package/dist/enterprise/training/training-admin.mcp-tools.js.map +1 -0
  200. package/dist/enterprise/training/training-instructor.mcp-tools.d.ts +47 -0
  201. package/dist/enterprise/training/training-instructor.mcp-tools.d.ts.map +1 -0
  202. package/dist/enterprise/training/training-instructor.mcp-tools.js +275 -0
  203. package/dist/enterprise/training/training-instructor.mcp-tools.js.map +1 -0
  204. package/dist/enterprise/training/training-student.controller.d.ts +24 -0
  205. package/dist/enterprise/training/training-student.controller.d.ts.map +1 -1
  206. package/dist/enterprise/training/training-student.controller.js +22 -0
  207. package/dist/enterprise/training/training-student.controller.js.map +1 -1
  208. package/dist/enterprise/training/training-student.mcp-tools.d.ts +27 -0
  209. package/dist/enterprise/training/training-student.mcp-tools.d.ts.map +1 -0
  210. package/dist/enterprise/training/training-student.mcp-tools.js +186 -0
  211. package/dist/enterprise/training/training-student.mcp-tools.js.map +1 -0
  212. package/dist/enterprise/training/training-student.service.d.ts +32 -0
  213. package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
  214. package/dist/enterprise/training/training-student.service.js +138 -0
  215. package/dist/enterprise/training/training-student.service.js.map +1 -1
  216. package/dist/evaluation/evaluation.mcp-tools.d.ts +25 -0
  217. package/dist/evaluation/evaluation.mcp-tools.d.ts.map +1 -0
  218. package/dist/evaluation/evaluation.mcp-tools.js +220 -0
  219. package/dist/evaluation/evaluation.mcp-tools.js.map +1 -0
  220. package/dist/evaluation/evaluation.module.d.ts.map +1 -1
  221. package/dist/evaluation/evaluation.module.js +2 -1
  222. package/dist/evaluation/evaluation.module.js.map +1 -1
  223. package/dist/evaluation/evaluation.service.d.ts.map +1 -1
  224. package/dist/evaluation/evaluation.service.js +9 -2
  225. package/dist/evaluation/evaluation.service.js.map +1 -1
  226. package/dist/exam/dto/create-exam-question.dto.d.ts +2 -0
  227. package/dist/exam/dto/create-exam-question.dto.d.ts.map +1 -1
  228. package/dist/exam/dto/create-exam-question.dto.js +10 -0
  229. package/dist/exam/dto/create-exam-question.dto.js.map +1 -1
  230. package/dist/exam/dto/create-exam.dto.d.ts +2 -0
  231. package/dist/exam/dto/create-exam.dto.d.ts.map +1 -1
  232. package/dist/exam/dto/create-exam.dto.js +10 -0
  233. package/dist/exam/dto/create-exam.dto.js.map +1 -1
  234. package/dist/exam/dto/create-question-subject.dto.d.ts +5 -0
  235. package/dist/exam/dto/create-question-subject.dto.d.ts.map +1 -0
  236. package/dist/exam/dto/create-question-subject.dto.js +28 -0
  237. package/dist/exam/dto/create-question-subject.dto.js.map +1 -0
  238. package/dist/exam/exam-attempt.controller.d.ts +4 -0
  239. package/dist/exam/exam-attempt.controller.d.ts.map +1 -1
  240. package/dist/exam/exam-attempt.service.d.ts +7 -1
  241. package/dist/exam/exam-attempt.service.d.ts.map +1 -1
  242. package/dist/exam/exam-attempt.service.js +47 -17
  243. package/dist/exam/exam-attempt.service.js.map +1 -1
  244. package/dist/exam/exam.controller.d.ts +34 -0
  245. package/dist/exam/exam.controller.d.ts.map +1 -1
  246. package/dist/exam/exam.controller.js +27 -0
  247. package/dist/exam/exam.controller.js.map +1 -1
  248. package/dist/exam/exam.mcp-tools.d.ts +62 -0
  249. package/dist/exam/exam.mcp-tools.d.ts.map +1 -0
  250. package/dist/exam/exam.mcp-tools.js +430 -0
  251. package/dist/exam/exam.mcp-tools.js.map +1 -0
  252. package/dist/exam/exam.module.d.ts.map +1 -1
  253. package/dist/exam/exam.module.js +2 -1
  254. package/dist/exam/exam.module.js.map +1 -1
  255. package/dist/exam/exam.service.d.ts +38 -0
  256. package/dist/exam/exam.service.d.ts.map +1 -1
  257. package/dist/exam/exam.service.js +114 -17
  258. package/dist/exam/exam.service.js.map +1 -1
  259. package/dist/index.d.ts +10 -0
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +10 -0
  262. package/dist/index.js.map +1 -1
  263. package/dist/instructor/instructor.mcp-tools.d.ts +41 -0
  264. package/dist/instructor/instructor.mcp-tools.d.ts.map +1 -0
  265. package/dist/instructor/instructor.mcp-tools.js +326 -0
  266. package/dist/instructor/instructor.mcp-tools.js.map +1 -0
  267. package/dist/instructor/instructor.module.d.ts.map +1 -1
  268. package/dist/instructor/instructor.module.js +2 -1
  269. package/dist/instructor/instructor.module.js.map +1 -1
  270. package/dist/lms.module.d.ts.map +1 -1
  271. package/dist/lms.module.js +18 -0
  272. package/dist/lms.module.js.map +1 -1
  273. package/dist/realtime/lms-realtime.controller.d.ts +7 -0
  274. package/dist/realtime/lms-realtime.controller.d.ts.map +1 -0
  275. package/dist/realtime/lms-realtime.controller.js +34 -0
  276. package/dist/realtime/lms-realtime.controller.js.map +1 -0
  277. package/dist/realtime/lms-realtime.module.d.ts +3 -0
  278. package/dist/realtime/lms-realtime.module.d.ts.map +1 -0
  279. package/dist/realtime/lms-realtime.module.js +25 -0
  280. package/dist/realtime/lms-realtime.module.js.map +1 -0
  281. package/dist/realtime/lms-realtime.service.d.ts +36 -0
  282. package/dist/realtime/lms-realtime.service.d.ts.map +1 -0
  283. package/dist/realtime/lms-realtime.service.js +59 -0
  284. package/dist/realtime/lms-realtime.service.js.map +1 -0
  285. package/dist/realtime/lms-realtime.subscriber.d.ts +10 -0
  286. package/dist/realtime/lms-realtime.subscriber.d.ts.map +1 -0
  287. package/dist/realtime/lms-realtime.subscriber.js +70 -0
  288. package/dist/realtime/lms-realtime.subscriber.js.map +1 -0
  289. package/dist/reports/reports.mcp-tools.d.ts +10 -0
  290. package/dist/reports/reports.mcp-tools.d.ts.map +1 -0
  291. package/dist/reports/reports.mcp-tools.js +50 -0
  292. package/dist/reports/reports.mcp-tools.js.map +1 -0
  293. package/dist/reports/reports.module.d.ts.map +1 -1
  294. package/dist/reports/reports.module.js +2 -1
  295. package/dist/reports/reports.module.js.map +1 -1
  296. package/dist/training/training.mcp-tools.d.ts +20 -0
  297. package/dist/training/training.mcp-tools.d.ts.map +1 -0
  298. package/dist/training/training.mcp-tools.js +181 -0
  299. package/dist/training/training.mcp-tools.js.map +1 -0
  300. package/dist/training/training.module.d.ts.map +1 -1
  301. package/dist/training/training.module.js +2 -1
  302. package/dist/training/training.module.js.map +1 -1
  303. package/dist/video-resolution-profile/dto/create-video-resolution-profile.dto.d.ts +6 -0
  304. package/dist/video-resolution-profile/dto/create-video-resolution-profile.dto.d.ts.map +1 -0
  305. package/dist/video-resolution-profile/dto/create-video-resolution-profile.dto.js +33 -0
  306. package/dist/video-resolution-profile/dto/create-video-resolution-profile.dto.js.map +1 -0
  307. package/dist/video-resolution-profile/dto/update-video-resolution-profile.dto.d.ts +6 -0
  308. package/dist/video-resolution-profile/dto/update-video-resolution-profile.dto.d.ts.map +1 -0
  309. package/dist/video-resolution-profile/dto/update-video-resolution-profile.dto.js +33 -0
  310. package/dist/video-resolution-profile/dto/update-video-resolution-profile.dto.js.map +1 -0
  311. package/dist/video-resolution-profile/video-resolution-profile.controller.d.ts +38 -0
  312. package/dist/video-resolution-profile/video-resolution-profile.controller.d.ts.map +1 -0
  313. package/dist/video-resolution-profile/video-resolution-profile.controller.js +89 -0
  314. package/dist/video-resolution-profile/video-resolution-profile.controller.js.map +1 -0
  315. package/dist/video-resolution-profile/video-resolution-profile.mcp-tools.d.ts +26 -0
  316. package/dist/video-resolution-profile/video-resolution-profile.mcp-tools.d.ts.map +1 -0
  317. package/dist/video-resolution-profile/video-resolution-profile.mcp-tools.js +160 -0
  318. package/dist/video-resolution-profile/video-resolution-profile.mcp-tools.js.map +1 -0
  319. package/dist/video-resolution-profile/video-resolution-profile.module.d.ts +3 -0
  320. package/dist/video-resolution-profile/video-resolution-profile.module.d.ts.map +1 -0
  321. package/dist/video-resolution-profile/video-resolution-profile.module.js +26 -0
  322. package/dist/video-resolution-profile/video-resolution-profile.module.js.map +1 -0
  323. package/dist/video-resolution-profile/video-resolution-profile.service.d.ts +45 -0
  324. package/dist/video-resolution-profile/video-resolution-profile.service.d.ts.map +1 -0
  325. package/dist/video-resolution-profile/video-resolution-profile.service.js +117 -0
  326. package/dist/video-resolution-profile/video-resolution-profile.service.js.map +1 -0
  327. package/hedhog/data/integration_event_catalog.yaml +69 -0
  328. package/hedhog/data/menu.yaml +51 -0
  329. package/hedhog/data/route.yaml +2484 -0
  330. package/hedhog/data/video_resolution_profile.yaml +7 -0
  331. package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +432 -422
  332. package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +200 -67
  333. package/hedhog/frontend/app/_components/course-picker.tsx.ejs +228 -0
  334. package/hedhog/frontend/app/_components/create-lms-instructor-sheet.tsx.ejs +7 -4
  335. package/hedhog/frontend/app/_components/create-lms-person-sheet.tsx.ejs +2 -2
  336. package/hedhog/frontend/app/_components/create-lms-student-person-sheet.tsx.ejs +2 -2
  337. package/hedhog/frontend/app/_lib/editor/templateSerializer.ts.ejs +34 -4
  338. package/hedhog/frontend/app/_lib/editor/types.ts.ejs +28 -3
  339. package/hedhog/frontend/app/_lib/hooks/use-lms-realtime-refresh.ts.ejs +58 -0
  340. package/hedhog/frontend/app/achievements/page.tsx.ejs +850 -0
  341. package/hedhog/frontend/app/bitcodes/page.tsx.ejs +1016 -0
  342. package/hedhog/frontend/app/certificates/issued/page.tsx.ejs +68 -5
  343. package/hedhog/frontend/app/certificates/models/CanvasStage.tsx.ejs +29 -8
  344. package/hedhog/frontend/app/certificates/models/LeftPanel.tsx.ejs +14 -0
  345. package/hedhog/frontend/app/certificates/models/RightPanel.tsx.ejs +194 -9
  346. package/hedhog/frontend/app/certificates/models/page.tsx.ejs +15 -5
  347. package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +16 -5
  348. package/hedhog/frontend/app/classes/page.tsx.ejs +126 -2105
  349. package/hedhog/frontend/app/courses/[id]/_components/CourseCertificateCard.tsx.ejs +19 -9
  350. package/hedhog/frontend/app/courses/[id]/_components/CourseClassificationCard.tsx.ejs +24 -1
  351. package/hedhog/frontend/app/courses/[id]/_components/CourseContentCard.tsx.ejs +1 -1
  352. package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +1 -1
  353. package/hedhog/frontend/app/courses/[id]/_components/CourseRelationsCard.tsx.ejs +51 -11
  354. package/hedhog/frontend/app/courses/[id]/_components/CourseSectionCard.tsx.ejs +11 -6
  355. package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +7 -4
  356. package/hedhog/frontend/app/courses/[id]/_components/course-edit-types.ts.ejs +2 -0
  357. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +24 -96
  358. package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +80 -66
  359. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +1286 -230
  360. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +1334 -153
  361. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-session.tsx.ejs +11 -11
  362. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -1
  363. package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +62 -52
  364. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-context-menu.tsx.ejs +106 -4
  365. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +4 -1
  366. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +30 -7
  367. package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +138 -6
  368. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +16 -2
  369. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +1 -0
  370. package/hedhog/frontend/app/courses/page.tsx.ejs +282 -113
  371. package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +1 -1
  372. package/hedhog/frontend/app/enterprise/_components/enterprise-admin-create-sheet.tsx.ejs +10 -3
  373. package/hedhog/frontend/app/enterprise/_components/enterprise-course-create-sheet.tsx.ejs +3 -0
  374. package/hedhog/frontend/app/enterprise/_components/enterprise-course-edit-sheet.tsx.ejs +7 -0
  375. package/hedhog/frontend/app/enterprise/_components/enterprise-detail-sheet.tsx.ejs +8 -4
  376. package/hedhog/frontend/app/enterprise/_components/enterprise-person-edit-sheet.tsx.ejs +2 -2
  377. package/hedhog/frontend/app/enterprise/_components/enterprise-sheet.tsx.ejs +10 -4
  378. package/hedhog/frontend/app/enterprise/_components/enterprise-student-create-sheet.tsx.ejs +10 -3
  379. package/hedhog/frontend/app/enterprise/_components/enterprise-user-create-sheet.tsx.ejs +10 -3
  380. package/hedhog/frontend/app/evaluations/_components/evaluation-topic-form-sheet.tsx.ejs +10 -3
  381. package/hedhog/frontend/app/exams/[id]/questions/page.tsx.ejs +186 -5
  382. package/hedhog/frontend/app/exams/page.tsx.ejs +89 -26
  383. package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +10 -3
  384. package/hedhog/frontend/app/instructors/_components/instructor-form-sheet.tsx.ejs +190 -17
  385. package/hedhog/frontend/app/instructors/page.tsx.ejs +1 -0
  386. package/hedhog/frontend/app/layout.tsx.ejs +5 -1
  387. package/hedhog/frontend/app/paths/page.tsx.ejs +19 -29
  388. package/hedhog/frontend/app/reports/evaluations/page.tsx.ejs +10 -10
  389. package/hedhog/frontend/app/training/page.tsx.ejs +19 -29
  390. package/hedhog/frontend/app/video-resolution-profiles/page.tsx.ejs +607 -0
  391. package/hedhog/frontend/messages/en.json +563 -20
  392. package/hedhog/frontend/messages/pt.json +563 -20
  393. package/hedhog/query/triggers.sql +53 -0
  394. package/hedhog/table/achievement.yaml +46 -0
  395. package/hedhog/table/bitcode_wallet.yaml +18 -0
  396. package/hedhog/table/bitcode_wallet_transaction.yaml +22 -0
  397. package/hedhog/table/certificate.yaml +3 -0
  398. package/hedhog/table/course.yaml +8 -0
  399. package/hedhog/table/course_file.yaml +23 -0
  400. package/hedhog/table/course_lesson.yaml +5 -0
  401. package/hedhog/table/course_lesson_discussion_like.yaml +21 -0
  402. package/hedhog/table/course_lesson_discussion_topic.yaml +35 -0
  403. package/hedhog/table/course_lesson_file.yaml +8 -0
  404. package/hedhog/table/course_lesson_note.yaml +34 -0
  405. package/hedhog/table/course_video_resolution_profile.yaml +22 -0
  406. package/hedhog/table/exam.yaml +5 -0
  407. package/hedhog/table/learning_path_enrollment.yaml +6 -0
  408. package/hedhog/table/question.yaml +10 -0
  409. package/hedhog/table/question_subject.yaml +17 -0
  410. package/hedhog/table/student_activity_streak.yaml +25 -0
  411. package/hedhog/table/video_resolution_profile.yaml +18 -0
  412. package/package.json +8 -7
  413. package/src/achievement/achievement.controller.ts +60 -0
  414. package/src/achievement/achievement.mcp-tools.ts +108 -0
  415. package/src/achievement/achievement.module.ts +13 -0
  416. package/src/achievement/achievement.service.ts +252 -0
  417. package/src/achievement/dto/create-achievement.dto.ts +50 -0
  418. package/src/achievement/dto/update-achievement.dto.ts +47 -0
  419. package/src/bitcode-wallet/bitcode-wallet.controller.ts +69 -0
  420. package/src/bitcode-wallet/bitcode-wallet.mcp-tools.ts +107 -0
  421. package/src/bitcode-wallet/bitcode-wallet.module.ts +13 -0
  422. package/src/bitcode-wallet/bitcode-wallet.service.ts +361 -0
  423. package/src/bitcode-wallet/dto/create-bitcode-wallet-transaction.dto.ts +27 -0
  424. package/src/bitcode-wallet/dto/create-bitcode-wallet.dto.ts +7 -0
  425. package/src/bitcode-wallet/dto/update-bitcode-wallet-transaction.dto.ts +28 -0
  426. package/src/bitcode-wallet/dto/update-bitcode-wallet.dto.ts +8 -0
  427. package/src/certificate/certificate.controller.ts +17 -3
  428. package/src/certificate/certificate.mcp-tools.ts +131 -0
  429. package/src/certificate/certificate.module.ts +2 -1
  430. package/src/certificate/certificate.service.ts +193 -7
  431. package/src/certificate/dto/update-certificate-public-access.dto.ts +6 -0
  432. package/src/class-group/class-group.mcp-tools.ts +435 -0
  433. package/src/class-group/class-group.module.ts +2 -1
  434. package/src/class-group/class-group.service.ts +51 -1
  435. package/src/course/course-operations-integration.service.ts +520 -0
  436. package/src/course/course-structure.controller.ts +46 -10
  437. package/src/course/course-structure.service.ts +236 -27
  438. package/src/course/course-video-conversion.service.ts +415 -0
  439. package/src/course/course.controller.ts +18 -0
  440. package/src/course/course.mcp-tools.ts +409 -0
  441. package/src/course/course.module.ts +23 -3
  442. package/src/course/course.service.ts +178 -29
  443. package/src/course/dto/create-course-structure-lesson.dto.ts +13 -2
  444. package/src/course/dto/create-course.dto.ts +16 -0
  445. package/src/course/dto/update-course-resources.dto.ts +39 -0
  446. package/src/course-lesson-discussion/course-lesson-discussion.controller.ts +55 -0
  447. package/src/course-lesson-discussion/course-lesson-discussion.mcp-tools.ts +75 -0
  448. package/src/course-lesson-discussion/course-lesson-discussion.module.ts +13 -0
  449. package/src/course-lesson-discussion/course-lesson-discussion.service.ts +354 -0
  450. package/src/course-lesson-discussion/dto/create-course-lesson-discussion-topic.dto.ts +16 -0
  451. package/src/course-lesson-note/course-lesson-note.controller.ts +68 -0
  452. package/src/course-lesson-note/course-lesson-note.mcp-tools.ts +96 -0
  453. package/src/course-lesson-note/course-lesson-note.module.ts +13 -0
  454. package/src/course-lesson-note/course-lesson-note.service.ts +248 -0
  455. package/src/course-lesson-note/dto/create-course-lesson-note.dto.ts +16 -0
  456. package/src/course-lesson-note/dto/update-course-lesson-note.dto.ts +18 -0
  457. package/src/dashboard/dashboard.mcp-tools.ts +23 -0
  458. package/src/dashboard/dashboard.module.ts +2 -1
  459. package/src/enterprise/enterprise.controller.ts +0 -1
  460. package/src/enterprise/enterprise.mcp-tools.ts +403 -0
  461. package/src/enterprise/enterprise.module.ts +2 -1
  462. package/src/enterprise/training/enterprise-training.module.ts +11 -1
  463. package/src/enterprise/training/training-admin.mcp-tools.ts +479 -0
  464. package/src/enterprise/training/training-instructor.mcp-tools.ts +210 -0
  465. package/src/enterprise/training/training-student.controller.ts +17 -1
  466. package/src/enterprise/training/training-student.mcp-tools.ts +136 -0
  467. package/src/enterprise/training/training-student.service.ts +167 -1
  468. package/src/evaluation/evaluation.mcp-tools.ts +155 -0
  469. package/src/evaluation/evaluation.module.ts +2 -1
  470. package/src/evaluation/evaluation.service.ts +9 -2
  471. package/src/exam/dto/create-exam-question.dto.ts +8 -0
  472. package/src/exam/dto/create-exam.dto.ts +8 -0
  473. package/src/exam/dto/create-question-subject.dto.ts +12 -0
  474. package/src/exam/exam-attempt.service.ts +46 -14
  475. package/src/exam/exam.controller.ts +19 -0
  476. package/src/exam/exam.mcp-tools.ts +337 -0
  477. package/src/exam/exam.module.ts +2 -1
  478. package/src/exam/exam.service.ts +121 -0
  479. package/src/index.ts +10 -0
  480. package/src/instructor/instructor.mcp-tools.ts +243 -0
  481. package/src/instructor/instructor.module.ts +2 -1
  482. package/src/lms.module.ts +18 -1
  483. package/src/realtime/lms-realtime.controller.ts +12 -0
  484. package/src/realtime/lms-realtime.module.ts +12 -0
  485. package/src/realtime/lms-realtime.service.ts +98 -0
  486. package/src/realtime/lms-realtime.subscriber.ts +61 -0
  487. package/src/reports/reports.mcp-tools.ts +27 -0
  488. package/src/reports/reports.module.ts +2 -1
  489. package/src/training/training.mcp-tools.ts +128 -0
  490. package/src/training/training.module.ts +2 -1
  491. package/src/video-resolution-profile/dto/create-video-resolution-profile.dto.ts +16 -0
  492. package/src/video-resolution-profile/dto/update-video-resolution-profile.dto.ts +16 -0
  493. package/src/video-resolution-profile/video-resolution-profile.controller.ts +62 -0
  494. package/src/video-resolution-profile/video-resolution-profile.mcp-tools.ts +128 -0
  495. package/src/video-resolution-profile/video-resolution-profile.module.ts +13 -0
  496. package/src/video-resolution-profile/video-resolution-profile.service.ts +117 -0
@@ -12,12 +12,7 @@ import {
12
12
  DialogTitle,
13
13
  } from '@/components/ui/dialog';
14
14
  import { EntityPicker } from '@/components/ui/entity-picker';
15
- import {
16
- Field,
17
- FieldDescription,
18
- FieldError,
19
- FieldLabel,
20
- } from '@/components/ui/field';
15
+ import { Field, FieldError, FieldLabel } from '@/components/ui/field';
21
16
  import { Input } from '@/components/ui/input';
22
17
  import {
23
18
  Popover,
@@ -33,12 +28,12 @@ import {
33
28
  } from '@/components/ui/select';
34
29
  import {
35
30
  Sheet,
36
- SheetContent,
37
31
  SheetDescription,
38
32
  SheetFooter,
39
33
  SheetHeader,
40
34
  SheetTitle,
41
35
  } from '@/components/ui/sheet';
36
+ import { ResizableSheetContent } from '@/components/ui/resizable-sheet-content';
42
37
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
43
38
  import { zodResolver } from '@hookform/resolvers/zod';
44
39
  import { format } from 'date-fns';
@@ -57,6 +52,7 @@ import {
57
52
  type CourseCategoryOption,
58
53
  type CourseSheetFormValues,
59
54
  } from './course-form-sheet';
55
+ import { CoursePicker } from './course-picker';
60
56
 
61
57
  // ── Types ─────────────────────────────────────────────────────────────────────
62
58
 
@@ -104,14 +100,6 @@ export type ApiClass = {
104
100
  sessionRecurrenceSummary?: SessionRecurrenceSummary | null;
105
101
  };
106
102
 
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
103
  type ApiCategoryList = {
116
104
  data: ApiCategory[];
117
105
  total: number;
@@ -131,6 +119,21 @@ type ApiCreatedCourse = {
131
119
  title: string;
132
120
  };
133
121
 
122
+ type ApiCourseDetail = {
123
+ id: number;
124
+ code?: string;
125
+ slug?: string;
126
+ title: string;
127
+ description?: string;
128
+ level?: 'beginner' | 'intermediate' | 'advanced';
129
+ status?: 'draft' | 'published' | 'archived';
130
+ categories?: string[];
131
+ primaryColor?: string | null;
132
+ secondaryColor?: string | null;
133
+ logoFileId?: number | null;
134
+ operationsProjectId?: number | null;
135
+ };
136
+
134
137
  type InstructorOption = {
135
138
  id: number;
136
139
  name: string;
@@ -367,6 +370,18 @@ function toApiCourseStatus(status: CourseSheetFormValues['status']) {
367
370
  return 'archived';
368
371
  }
369
372
 
373
+ function toCourseFormLevel(level?: string): CourseSheetFormValues['nivel'] {
374
+ if (level === 'intermediate') return 'intermediario';
375
+ if (level === 'advanced') return 'avancado';
376
+ return 'iniciante';
377
+ }
378
+
379
+ function toCourseFormStatus(status?: string): CourseSheetFormValues['status'] {
380
+ if (status === 'published') return 'ativo';
381
+ if (status === 'archived') return 'arquivado';
382
+ return 'rascunho';
383
+ }
384
+
370
385
  // ── Constants ─────────────────────────────────────────────────────────────────
371
386
 
372
387
  const TIME_OPTIONS = Array.from({ length: 32 }, (_, index) => {
@@ -558,6 +573,8 @@ export function ClassFormSheet({
558
573
  null
559
574
  );
560
575
  const [courseSheetOpen, setCourseSheetOpen] = useState(false);
576
+ const [editingCourseId, setEditingCourseId] = useState<number | null>(null);
577
+ const [coursePickerRefreshToken, setCoursePickerRefreshToken] = useState(0);
561
578
  const [customRecurrenceDialogOpen, setCustomRecurrenceDialogOpen] =
562
579
  useState(false);
563
580
  const [previousRecurrenceMode, setPreviousRecurrenceMode] =
@@ -749,11 +766,6 @@ export function ClassFormSheet({
749
766
  )
750
767
  ? t('form.fields.sessionAccess.placeholder')
751
768
  : 'Sala 201 ou https://meet.google.com/...';
752
- const sessionAccessDescription = t.has(
753
- 'form.fields.sessionAccess.description'
754
- )
755
- ? t('form.fields.sessionAccess.description')
756
- : 'Opcional. Quando preenchido, será aplicado a todas as aulas geradas para esta turma.';
757
769
 
758
770
  const filteredEndTimeOptions = useMemo(() => {
759
771
  const startTime = watchedFormValues.horarioInicio ?? '';
@@ -793,20 +805,6 @@ export function ClassFormSheet({
793
805
  [t]
794
806
  );
795
807
 
796
- const recurrenceSummaryText = useMemo(() => {
797
- const until = watchedFormValues.sessionRecurrenceUntil
798
- ? formatDate(watchedFormValues.sessionRecurrenceUntil)
799
- : '--';
800
- return t(
801
- `form.recurrence.summary.${watchedFormValues.sessionRecurrenceMode}`,
802
- { until }
803
- );
804
- }, [
805
- t,
806
- watchedFormValues.sessionRecurrenceMode,
807
- watchedFormValues.sessionRecurrenceUntil,
808
- ]);
809
-
810
808
  const customRecurrenceFrequency =
811
809
  watchedFormValues.sessionRecurrenceMode === 'custom'
812
810
  ? watchedFormValues.sessionRecurrenceCustomFrequency
@@ -1024,32 +1022,71 @@ export function ClassFormSheet({
1024
1022
  description: data.descricao,
1025
1023
  level: toApiCourseLevel(data.nivel),
1026
1024
  status: toApiCourseStatus(data.status),
1025
+ offeringType: 'scheduled' as const,
1027
1026
  categorySlugs: data.categorias,
1028
1027
  primaryColor: data.primaryColor,
1029
1028
  primaryContrastColor: getContrastColor(data.primaryColor),
1030
1029
  secondaryColor: data.secondaryColor,
1031
1030
  secondaryContrastColor: getContrastColor(data.secondaryColor),
1031
+ operationsProjectId: data.operationsProjectId
1032
+ ? Number(data.operationsProjectId)
1033
+ : null,
1032
1034
  };
1033
1035
 
1034
- const response = await request<ApiCreatedCourse>({
1035
- url: '/lms/courses',
1036
- method: 'POST',
1037
- data: payload,
1038
- });
1036
+ if (editingCourseId) {
1037
+ await request({
1038
+ url: `/lms/courses/${editingCourseId}`,
1039
+ method: 'PATCH',
1040
+ data: {
1041
+ slug: data.nomeInterno.trim().toLowerCase(),
1042
+ title: data.tituloComercial,
1043
+ description: data.descricao,
1044
+ level: toApiCourseLevel(data.nivel),
1045
+ status: toApiCourseStatus(data.status),
1046
+ categorySlugs: data.categorias,
1047
+ primaryColor: data.primaryColor,
1048
+ primaryContrastColor: getContrastColor(data.primaryColor),
1049
+ secondaryColor: data.secondaryColor,
1050
+ secondaryContrastColor: getContrastColor(data.secondaryColor),
1051
+ operationsProjectId: data.operationsProjectId
1052
+ ? Number(data.operationsProjectId)
1053
+ : null,
1054
+ logoFileId: data.logoFileId ?? null,
1055
+ },
1056
+ });
1039
1057
 
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
- });
1058
+ form.setValue('curso', data.tituloComercial, {
1059
+ shouldDirty: true,
1060
+ shouldTouch: true,
1061
+ shouldValidate: false,
1062
+ });
1063
+
1064
+ toast.success(courseSheetT('toasts.courseUpdated'));
1065
+ } else {
1066
+ const response = await request<ApiCreatedCourse>({
1067
+ url: '/lms/courses',
1068
+ method: 'POST',
1069
+ data: payload,
1070
+ });
1071
+
1072
+ const createdCourse = response.data;
1073
+ form.setValue('courseId', createdCourse.id, {
1074
+ shouldDirty: true,
1075
+ shouldTouch: true,
1076
+ shouldValidate: true,
1077
+ });
1078
+ form.setValue('curso', createdCourse.title, {
1079
+ shouldDirty: true,
1080
+ shouldTouch: true,
1081
+ shouldValidate: false,
1082
+ });
1083
+
1084
+ toast.success(courseSheetT('toasts.courseCreated'));
1085
+ }
1086
+
1087
+ setCoursePickerRefreshToken((current) => current + 1);
1088
+ setEditingCourseId(null);
1051
1089
  setCourseSheetOpen(false);
1052
- toast.success(courseSheetT('toasts.courseCreated'));
1053
1090
  } catch {
1054
1091
  toast.error(t('messages.classCreateCourseError'));
1055
1092
  } finally {
@@ -1136,9 +1173,13 @@ export function ClassFormSheet({
1136
1173
  return (
1137
1174
  <>
1138
1175
  <Sheet open={open} onOpenChange={onOpenChange}>
1139
- <SheetContent
1176
+ <ResizableSheetContent
1177
+ sheetId="lms-class-form-sheet"
1178
+ defaultWidth={672}
1179
+ minWidth={460}
1180
+ maxWidth={1100}
1140
1181
  side="right"
1141
- className="flex w-full flex-col overflow-y-auto sm:max-w-2xl"
1182
+ className="flex w-full flex-col overflow-y-auto"
1142
1183
  >
1143
1184
  <SheetHeader className="shrink-0">
1144
1185
  <SheetTitle>
@@ -1157,9 +1198,9 @@ export function ClassFormSheet({
1157
1198
  ) : (
1158
1199
  <form
1159
1200
  onSubmit={form.handleSubmit(onSubmit)}
1160
- className="flex flex-1 flex-col gap-5 px-4 py-6"
1201
+ className="flex flex-1 flex-col gap-4 px-4 py-6"
1161
1202
  >
1162
- <div className="grid gap-4 md:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)]">
1203
+ <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
1163
1204
  <Field>
1164
1205
  <FieldLabel htmlFor="codigo">
1165
1206
  {t('form.fields.code.label')}
@@ -1170,9 +1211,6 @@ export function ClassFormSheet({
1170
1211
  readOnly
1171
1212
  className="uppercase"
1172
1213
  />
1173
- <FieldDescription>
1174
- Codigo gerado automaticamente pelo sistema.
1175
- </FieldDescription>
1176
1214
  <FieldError>
1177
1215
  {form.formState.errors.codigo?.message}
1178
1216
  </FieldError>
@@ -1183,242 +1221,223 @@ export function ClassFormSheet({
1183
1221
  {t('form.fields.course.label')}{' '}
1184
1222
  <span className="text-destructive">*</span>
1185
1223
  </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
- };
1224
+ <CoursePicker<TurmaForm>
1225
+ form={form}
1226
+ name="courseId"
1227
+ selectedCourseTitle={selectedCourseTitle}
1228
+ placeholder={t('form.fields.course.placeholder')}
1229
+ entityLabel={t('form.fields.course.label')}
1230
+ searchPlaceholder={t('form.fields.course.placeholder')}
1231
+ emptyStateDescription={t(
1232
+ 'components.entityPicker.courses.empty'
1233
+ )}
1234
+ loadingLabel={t('components.entityPicker.courses.loading')}
1235
+ noResultsLabel={t('components.entityPicker.courses.empty')}
1236
+ disabled={lockCourse}
1237
+ allowClearSelection={!lockCourse}
1238
+ showCreateButton={!lockCourse}
1239
+ showEditButton={!lockCourse}
1240
+ searchEndpoint="/lms/courses"
1241
+ searchExtraParams={{
1242
+ offeringTypes: 'scheduled,blended',
1243
+ }}
1244
+ refreshToken={coursePickerRefreshToken}
1245
+ onSelectionChange={(value, option) => {
1246
+ const cId = typeof value === 'number' ? value : undefined;
1247
+ const cTitle =
1248
+ option && typeof option.title === 'string'
1249
+ ? option.title
1250
+ : '';
1251
+
1252
+ form.setValue('courseId', cId, {
1253
+ shouldDirty: true,
1254
+ shouldTouch: true,
1255
+ shouldValidate: true,
1256
+ });
1257
+ form.setValue('curso', cTitle, {
1258
+ shouldDirty: true,
1259
+ shouldTouch: true,
1260
+ shouldValidate: false,
1261
+ });
1262
+ }}
1263
+ onCreateClick={() => {
1264
+ setEditingCourseId(null);
1265
+ courseForm.reset(DEFAULT_COURSE_FORM_VALUES);
1266
+ setCourseSheetOpen(true);
1267
+ }}
1268
+ onEditClick={async (selected) => {
1269
+ if (!selected?.id) return;
1270
+
1271
+ const response = await request<ApiCourseDetail>({
1272
+ url: `/lms/courses/${selected.id}`,
1273
+ method: 'GET',
1274
+ });
1275
+
1276
+ const detail = response.data;
1277
+ setEditingCourseId(detail.id);
1278
+ courseForm.reset({
1279
+ nomeInterno: detail.slug ?? detail.code ?? '',
1280
+ tituloComercial: detail.title ?? '',
1281
+ descricao: detail.description ?? '',
1282
+ nivel: toCourseFormLevel(detail.level),
1283
+ status: toCourseFormStatus(detail.status),
1284
+ categorias: detail.categories ?? [],
1285
+ operationsProjectId: detail.operationsProjectId
1286
+ ? String(detail.operationsProjectId)
1287
+ : '',
1288
+ primaryColor: detail.primaryColor ?? '#1D4ED8',
1289
+ secondaryColor: detail.secondaryColor ?? '#111827',
1290
+ logoFileId: detail.logoFileId ?? null,
1291
+ });
1292
+ setCourseSheetOpen(true);
1293
+ }}
1294
+ />
1295
+ </Field>
1296
+ </div>
1297
+
1298
+ <div className="space-y-3">
1299
+ <Field>
1300
+ <FieldLabel>
1301
+ {t('form.fields.startDate.label')} /{' '}
1302
+ {t('form.fields.endDate.label')}{' '}
1303
+ <span className="text-destructive">*</span>
1304
+ </FieldLabel>
1305
+ <Popover open={dateRangeOpen} onOpenChange={setDateRangeOpen}>
1306
+ <PopoverTrigger asChild>
1307
+ <Button
1308
+ type="button"
1309
+ variant="outline"
1310
+ className={`w-full justify-start text-left font-normal ${
1311
+ !watchedFormValues.dataInicio ||
1312
+ !watchedFormValues.dataFim
1313
+ ? 'text-muted-foreground'
1314
+ : ''
1315
+ }`}
1316
+ >
1317
+ <CalendarIcon className="mr-2 size-4" />
1318
+ {formatDateRangeLabel(
1319
+ watchedFormValues.dataInicio,
1320
+ watchedFormValues.dataFim
1321
+ ) || t('form.fields.startDate.placeholder')}
1322
+ </Button>
1323
+ </PopoverTrigger>
1324
+ <PopoverContent className="w-auto p-0" align="start">
1325
+ <Calendar
1326
+ mode="range"
1327
+ numberOfMonths={2}
1328
+ selected={dateRangeDraft}
1329
+ onSelect={(range) => {
1330
+ setDateRangeDraft(range);
1331
+ if (!range?.from || !range?.to) {
1332
+ form.setValue('dataInicio', '', {
1333
+ shouldDirty: true,
1334
+ shouldTouch: true,
1335
+ shouldValidate: true,
1336
+ });
1337
+ form.setValue('dataFim', '', {
1338
+ shouldDirty: true,
1339
+ shouldTouch: true,
1340
+ shouldValidate: true,
1341
+ });
1342
+ return;
1343
+ }
1344
+ form.setValue(
1345
+ 'dataInicio',
1346
+ format(range.from, 'yyyy-MM-dd'),
1347
+ {
1348
+ shouldDirty: true,
1349
+ shouldTouch: true,
1350
+ shouldValidate: true,
1351
+ }
1352
+ );
1353
+ form.setValue(
1354
+ 'dataFim',
1355
+ format(range.to, 'yyyy-MM-dd'),
1356
+ {
1357
+ shouldDirty: true,
1358
+ shouldTouch: true,
1359
+ shouldValidate: true,
1360
+ }
1361
+ );
1241
1362
  }}
1242
- getOptionValue={(option) => option.id}
1243
- getOptionLabel={(option) => option.title}
1363
+ initialFocus
1244
1364
  />
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>
1365
+ </PopoverContent>
1366
+ </Popover>
1367
+ <FieldError>
1368
+ {form.formState.errors.dataInicio?.message ||
1369
+ form.formState.errors.dataFim?.message}
1370
+ </FieldError>
1261
1371
  </Field>
1262
- </div>
1263
1372
 
1264
- <div className="rounded-lg border border-border/70 p-4">
1265
- <div className="grid gap-4">
1373
+ <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
1266
1374
  <Field>
1267
- <FieldLabel>
1268
- {t('form.fields.startDate.label')} /{' '}
1269
- {t('form.fields.endDate.label')}{' '}
1375
+ <FieldLabel htmlFor="horarioInicio">
1376
+ {t('form.fields.startTime.label')}{' '}
1270
1377
  <span className="text-destructive">*</span>
1271
1378
  </FieldLabel>
1272
- <Popover
1273
- open={dateRangeOpen}
1274
- onOpenChange={setDateRangeOpen}
1275
- >
1276
- <PopoverTrigger asChild>
1277
- <Button
1278
- type="button"
1279
- variant="outline"
1280
- className={`w-full justify-start text-left font-normal ${
1281
- !watchedFormValues.dataInicio ||
1282
- !watchedFormValues.dataFim
1283
- ? 'text-muted-foreground'
1284
- : ''
1285
- }`}
1379
+ <Controller
1380
+ name="horarioInicio"
1381
+ control={form.control}
1382
+ render={({ field }) => (
1383
+ <Select
1384
+ onValueChange={field.onChange}
1385
+ value={field.value}
1286
1386
  >
1287
- <CalendarIcon className="mr-2 size-4" />
1288
- {formatDateRangeLabel(
1289
- watchedFormValues.dataInicio,
1290
- watchedFormValues.dataFim
1291
- ) || t('form.fields.startDate.placeholder')}
1292
- </Button>
1293
- </PopoverTrigger>
1294
- <PopoverContent className="w-auto p-0" align="start">
1295
- <Calendar
1296
- mode="range"
1297
- numberOfMonths={2}
1298
- selected={dateRangeDraft}
1299
- onSelect={(range) => {
1300
- setDateRangeDraft(range);
1301
- if (!range?.from || !range?.to) {
1302
- form.setValue('dataInicio', '', {
1303
- shouldDirty: true,
1304
- shouldTouch: true,
1305
- shouldValidate: true,
1306
- });
1307
- form.setValue('dataFim', '', {
1308
- shouldDirty: true,
1309
- shouldTouch: true,
1310
- shouldValidate: true,
1311
- });
1312
- return;
1313
- }
1314
- form.setValue(
1315
- 'dataInicio',
1316
- format(range.from, 'yyyy-MM-dd'),
1317
- {
1318
- shouldDirty: true,
1319
- shouldTouch: true,
1320
- shouldValidate: true,
1321
- }
1322
- );
1323
- form.setValue(
1324
- 'dataFim',
1325
- format(range.to, 'yyyy-MM-dd'),
1326
- {
1327
- shouldDirty: true,
1328
- shouldTouch: true,
1329
- shouldValidate: true,
1330
- }
1331
- );
1332
- }}
1333
- initialFocus
1334
- />
1335
- </PopoverContent>
1336
- </Popover>
1387
+ <SelectTrigger id="horarioInicio">
1388
+ <SelectValue
1389
+ placeholder={t(
1390
+ 'form.fields.startTime.placeholder'
1391
+ )}
1392
+ />
1393
+ </SelectTrigger>
1394
+ <SelectContent>
1395
+ {TIME_OPTIONS.map((time) => (
1396
+ <SelectItem key={time} value={time}>
1397
+ {time}
1398
+ </SelectItem>
1399
+ ))}
1400
+ </SelectContent>
1401
+ </Select>
1402
+ )}
1403
+ />
1337
1404
  <FieldError>
1338
- {form.formState.errors.dataInicio?.message ||
1339
- form.formState.errors.dataFim?.message}
1405
+ {form.formState.errors.horarioInicio?.message}
1340
1406
  </FieldError>
1341
1407
  </Field>
1342
1408
 
1343
- <div className="grid gap-4 md:grid-cols-2">
1344
- <Field>
1345
- <FieldLabel htmlFor="horarioInicio">
1346
- {t('form.fields.startTime.label')}{' '}
1347
- <span className="text-destructive">*</span>
1348
- </FieldLabel>
1349
- <Controller
1350
- name="horarioInicio"
1351
- control={form.control}
1352
- render={({ field }) => (
1353
- <Select
1354
- onValueChange={field.onChange}
1355
- value={field.value}
1356
- >
1357
- <SelectTrigger id="horarioInicio">
1358
- <SelectValue
1359
- placeholder={t(
1360
- 'form.fields.startTime.placeholder'
1361
- )}
1362
- />
1363
- </SelectTrigger>
1364
- <SelectContent>
1365
- {TIME_OPTIONS.map((time) => (
1366
- <SelectItem key={time} value={time}>
1367
- {time}
1368
- </SelectItem>
1369
- ))}
1370
- </SelectContent>
1371
- </Select>
1372
- )}
1373
- />
1374
- <FieldDescription>
1375
- Escolha o horario de inicio na lista para preencher mais
1376
- rapido.
1377
- </FieldDescription>
1378
- <FieldError>
1379
- {form.formState.errors.horarioInicio?.message}
1380
- </FieldError>
1381
- </Field>
1382
-
1383
- <Field>
1384
- <FieldLabel htmlFor="horarioFim">
1385
- {t('form.fields.endTime.label')}{' '}
1386
- <span className="text-destructive">*</span>
1387
- </FieldLabel>
1388
- <Controller
1389
- name="horarioFim"
1390
- control={form.control}
1391
- render={({ field }) => (
1392
- <Select
1393
- onValueChange={field.onChange}
1394
- value={field.value}
1395
- >
1396
- <SelectTrigger id="horarioFim">
1397
- <SelectValue
1398
- placeholder={t(
1399
- 'form.fields.endTime.placeholder'
1400
- )}
1401
- />
1402
- </SelectTrigger>
1403
- <SelectContent>
1404
- {filteredEndTimeOptions.map((time) => (
1405
- <SelectItem key={time} value={time}>
1406
- {time}
1407
- </SelectItem>
1408
- ))}
1409
- </SelectContent>
1410
- </Select>
1411
- )}
1412
- />
1413
- <FieldDescription>
1414
- O termino mostra apenas horarios iguais ou depois do
1415
- inicio.
1416
- </FieldDescription>
1417
- <FieldError>
1418
- {form.formState.errors.horarioFim?.message}
1419
- </FieldError>
1420
- </Field>
1421
- </div>
1409
+ <Field>
1410
+ <FieldLabel htmlFor="horarioFim">
1411
+ {t('form.fields.endTime.label')}{' '}
1412
+ <span className="text-destructive">*</span>
1413
+ </FieldLabel>
1414
+ <Controller
1415
+ name="horarioFim"
1416
+ control={form.control}
1417
+ render={({ field }) => (
1418
+ <Select
1419
+ onValueChange={field.onChange}
1420
+ value={field.value}
1421
+ >
1422
+ <SelectTrigger id="horarioFim">
1423
+ <SelectValue
1424
+ placeholder={t('form.fields.endTime.placeholder')}
1425
+ />
1426
+ </SelectTrigger>
1427
+ <SelectContent>
1428
+ {filteredEndTimeOptions.map((time) => (
1429
+ <SelectItem key={time} value={time}>
1430
+ {time}
1431
+ </SelectItem>
1432
+ ))}
1433
+ </SelectContent>
1434
+ </Select>
1435
+ )}
1436
+ />
1437
+ <FieldError>
1438
+ {form.formState.errors.horarioFim?.message}
1439
+ </FieldError>
1440
+ </Field>
1422
1441
 
1423
1442
  <Field>
1424
1443
  <FieldLabel htmlFor="sessionAccess">
@@ -1436,9 +1455,6 @@ export function ClassFormSheet({
1436
1455
  })
1437
1456
  }
1438
1457
  />
1439
- <FieldDescription>
1440
- {sessionAccessDescription}
1441
- </FieldDescription>
1442
1458
  <FieldError>
1443
1459
  {form.formState.errors.sessionAccess?.message}
1444
1460
  </FieldError>
@@ -1446,17 +1462,17 @@ export function ClassFormSheet({
1446
1462
  </div>
1447
1463
  </div>
1448
1464
 
1449
- <div className="rounded-lg border border-border/70 p-4">
1450
- <div className="space-y-4">
1451
- <div className="space-y-1">
1452
- <h3 className="text-sm font-semibold">
1453
- {t('form.recurrence.sectionTitle')}
1454
- </h3>
1455
- <p className="text-sm text-muted-foreground">
1456
- {t('form.recurrence.sectionDescription')}
1457
- </p>
1458
- </div>
1465
+ <div className="space-y-3">
1466
+ <div className="space-y-1">
1467
+ <h3 className="text-sm font-semibold">
1468
+ {t('form.recurrence.sectionTitle')}
1469
+ </h3>
1470
+ <p className="text-sm text-muted-foreground">
1471
+ {t('form.recurrence.sectionDescription')}
1472
+ </p>
1473
+ </div>
1459
1474
 
1475
+ <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
1460
1476
  <Field>
1461
1477
  <FieldLabel>{t('form.recurrence.label')}</FieldLabel>
1462
1478
  <Select
@@ -1467,7 +1483,7 @@ export function ClassFormSheet({
1467
1483
  )
1468
1484
  }
1469
1485
  >
1470
- <SelectTrigger className="w-full md:w-56">
1486
+ <SelectTrigger>
1471
1487
  <SelectValue />
1472
1488
  </SelectTrigger>
1473
1489
  <SelectContent>
@@ -1499,133 +1515,122 @@ export function ClassFormSheet({
1499
1515
  </FieldError>
1500
1516
  </Field>
1501
1517
 
1502
- {(watchedFormValues.sessionRecurrenceMode === 'weekly' ||
1503
- watchedFormValues.sessionRecurrenceMode === 'weekdays' ||
1504
- (watchedFormValues.sessionRecurrenceMode === 'custom' &&
1505
- customRecurrenceFrequency === 'weekly')) && (
1506
- <Field>
1507
- <FieldLabel>
1508
- {t('form.recurrence.customDialog.repeatOn')}
1509
- </FieldLabel>
1510
- <div className="grid grid-cols-4 gap-2 sm:grid-cols-7">
1511
- {recurrenceDayOptions.map((day) => {
1512
- const active = (
1513
- watchedFormValues.sessionRecurrenceDaysOfWeek ?? []
1514
- ).includes(day.value);
1515
- const isWeekdays =
1516
- watchedFormValues.sessionRecurrenceMode ===
1517
- 'weekdays';
1518
- return (
1519
- <Button
1520
- key={day.value}
1521
- type="button"
1522
- variant={active ? 'default' : 'outline'}
1523
- size="sm"
1524
- className="h-9"
1525
- disabled={isWeekdays}
1526
- title={day.label}
1527
- aria-label={day.label}
1528
- onClick={() =>
1529
- toggleCustomRecurrenceDay(day.value)
1530
- }
1531
- >
1532
- {day.shortLabel}
1533
- </Button>
1534
- );
1535
- })}
1536
- </div>
1537
- <FieldError>
1538
- {
1539
- form.formState.errors.sessionRecurrenceDaysOfWeek
1540
- ?.message
1541
- }
1542
- </FieldError>
1543
- </Field>
1544
- )}
1518
+ <Field>
1519
+ <FieldLabel>
1520
+ {t('form.recurrence.titleMode.label')}
1521
+ </FieldLabel>
1522
+ <Controller
1523
+ name="sessionTitleMode"
1524
+ control={form.control}
1525
+ render={({ field }) => (
1526
+ <Select
1527
+ value={field.value}
1528
+ onValueChange={(value) => {
1529
+ field.onChange(value);
1530
+ if (value === 'default-course-code') {
1531
+ form.setValue(
1532
+ 'sessionTitle',
1533
+ defaultSessionTitle,
1534
+ {
1535
+ shouldDirty: true,
1536
+ shouldTouch: false,
1537
+ shouldValidate: false,
1538
+ }
1539
+ );
1540
+ }
1541
+ }}
1542
+ >
1543
+ <SelectTrigger>
1544
+ <SelectValue />
1545
+ </SelectTrigger>
1546
+ <SelectContent>
1547
+ <SelectItem value="default-course-code">
1548
+ {t('form.recurrence.titleMode.default')}
1549
+ </SelectItem>
1550
+ <SelectItem value="custom">
1551
+ {t('form.recurrence.titleMode.custom')}
1552
+ </SelectItem>
1553
+ </SelectContent>
1554
+ </Select>
1555
+ )}
1556
+ />
1557
+ </Field>
1545
1558
 
1546
- <div className="grid gap-4 md:grid-cols-[minmax(0,0.55fr)_minmax(0,1fr)]">
1547
- <Field>
1548
- <FieldLabel>
1549
- {t('form.recurrence.titleMode.label')}
1550
- </FieldLabel>
1551
- <Controller
1552
- name="sessionTitleMode"
1553
- control={form.control}
1554
- render={({ field }) => (
1555
- <Select
1556
- value={field.value}
1557
- onValueChange={(value) => {
1558
- field.onChange(value);
1559
- if (value === 'default-course-code') {
1560
- form.setValue(
1561
- 'sessionTitle',
1562
- defaultSessionTitle,
1563
- {
1564
- shouldDirty: true,
1565
- shouldTouch: false,
1566
- shouldValidate: false,
1567
- }
1568
- );
1569
- }
1570
- }}
1571
- >
1572
- <SelectTrigger>
1573
- <SelectValue />
1574
- </SelectTrigger>
1575
- <SelectContent>
1576
- <SelectItem value="default-course-code">
1577
- {t('form.recurrence.titleMode.default')}
1578
- </SelectItem>
1579
- <SelectItem value="custom">
1580
- {t('form.recurrence.titleMode.custom')}
1581
- </SelectItem>
1582
- </SelectContent>
1583
- </Select>
1584
- )}
1585
- />
1586
- </Field>
1587
-
1588
- <Field>
1589
- <FieldLabel htmlFor="sessionTitle">
1590
- {t('form.fields.sessionTitle.label')}
1591
- </FieldLabel>
1592
- <Input
1593
- id="sessionTitle"
1594
- value={
1595
- watchedFormValues.sessionTitleMode ===
1596
- 'default-course-code'
1597
- ? defaultSessionTitle
1598
- : (watchedFormValues.sessionTitle ?? '')
1599
- }
1600
- placeholder={t('form.fields.sessionTitle.placeholder')}
1601
- disabled={
1602
- watchedFormValues.sessionTitleMode ===
1603
- 'default-course-code'
1604
- }
1605
- onChange={(event) =>
1606
- form.setValue('sessionTitle', event.target.value, {
1607
- shouldDirty: true,
1608
- shouldTouch: true,
1609
- shouldValidate: false,
1610
- })
1611
- }
1612
- />
1613
- <FieldDescription>
1614
- {watchedFormValues.sessionTitleMode ===
1559
+ <Field>
1560
+ <FieldLabel htmlFor="sessionTitle">
1561
+ {t('form.fields.sessionTitle.label')}
1562
+ </FieldLabel>
1563
+ <Input
1564
+ id="sessionTitle"
1565
+ value={
1566
+ watchedFormValues.sessionTitleMode ===
1615
1567
  'default-course-code'
1616
- ? defaultSessionTitle ||
1617
- t('form.fields.sessionTitle.placeholder')
1618
- : recurrenceSummaryText}
1619
- </FieldDescription>
1620
- <FieldError>
1621
- {form.formState.errors.sessionTitle?.message}
1622
- </FieldError>
1623
- </Field>
1624
- </div>
1568
+ ? defaultSessionTitle
1569
+ : (watchedFormValues.sessionTitle ?? '')
1570
+ }
1571
+ placeholder={t('form.fields.sessionTitle.placeholder')}
1572
+ disabled={
1573
+ watchedFormValues.sessionTitleMode ===
1574
+ 'default-course-code'
1575
+ }
1576
+ onChange={(event) =>
1577
+ form.setValue('sessionTitle', event.target.value, {
1578
+ shouldDirty: true,
1579
+ shouldTouch: true,
1580
+ shouldValidate: false,
1581
+ })
1582
+ }
1583
+ />
1584
+ <FieldError>
1585
+ {form.formState.errors.sessionTitle?.message}
1586
+ </FieldError>
1587
+ </Field>
1625
1588
  </div>
1589
+
1590
+ {(watchedFormValues.sessionRecurrenceMode === 'weekly' ||
1591
+ watchedFormValues.sessionRecurrenceMode === 'weekdays' ||
1592
+ (watchedFormValues.sessionRecurrenceMode === 'custom' &&
1593
+ customRecurrenceFrequency === 'weekly')) && (
1594
+ <Field>
1595
+ <FieldLabel>
1596
+ {t('form.recurrence.customDialog.repeatOn')}
1597
+ </FieldLabel>
1598
+ <div className="grid grid-cols-4 gap-2 sm:grid-cols-7">
1599
+ {recurrenceDayOptions.map((day) => {
1600
+ const active = (
1601
+ watchedFormValues.sessionRecurrenceDaysOfWeek ?? []
1602
+ ).includes(day.value);
1603
+ const isWeekdays =
1604
+ watchedFormValues.sessionRecurrenceMode ===
1605
+ 'weekdays';
1606
+ return (
1607
+ <Button
1608
+ key={day.value}
1609
+ type="button"
1610
+ variant={active ? 'default' : 'outline'}
1611
+ size="sm"
1612
+ className="h-9"
1613
+ disabled={isWeekdays}
1614
+ title={day.label}
1615
+ aria-label={day.label}
1616
+ onClick={() => toggleCustomRecurrenceDay(day.value)}
1617
+ >
1618
+ {day.shortLabel}
1619
+ </Button>
1620
+ );
1621
+ })}
1622
+ </div>
1623
+ <FieldError>
1624
+ {
1625
+ form.formState.errors.sessionRecurrenceDaysOfWeek
1626
+ ?.message
1627
+ }
1628
+ </FieldError>
1629
+ </Field>
1630
+ )}
1626
1631
  </div>
1627
1632
 
1628
- <div className="grid gap-4 md:grid-cols-3">
1633
+ <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
1629
1634
  <Field>
1630
1635
  <FieldLabel>
1631
1636
  {t('form.fields.type.label')}{' '}
@@ -1887,7 +1892,7 @@ export function ClassFormSheet({
1887
1892
  </SheetFooter>
1888
1893
  </form>
1889
1894
  )}
1890
- </SheetContent>
1895
+ </ResizableSheetContent>
1891
1896
  </Sheet>
1892
1897
 
1893
1898
  {/* Custom Recurrence Dialog */}
@@ -2063,10 +2068,15 @@ export function ClassFormSheet({
2063
2068
 
2064
2069
  {/* Course create sheet */}
2065
2070
  <CourseFormSheet
2066
- key="class-form-sheet-course-create"
2071
+ key={`class-form-sheet-course-${editingCourseId ?? 'create'}`}
2067
2072
  open={courseSheetOpen}
2068
- onOpenChange={setCourseSheetOpen}
2069
- editing={false}
2073
+ onOpenChange={(nextOpen) => {
2074
+ setCourseSheetOpen(nextOpen);
2075
+ if (!nextOpen) {
2076
+ setEditingCourseId(null);
2077
+ }
2078
+ }}
2079
+ editing={Boolean(editingCourseId)}
2070
2080
  saving={savingCourse}
2071
2081
  form={courseForm}
2072
2082
  onSubmit={onSubmitCourse}