@magmamath/students-features 1.6.0-rc.1 → 1.6.0

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 (268) hide show
  1. package/dist/commonjs/features/chatbot/components/Chat/AIAvatar.js +33 -0
  2. package/dist/commonjs/features/chatbot/components/Chat/AIAvatar.js.map +1 -0
  3. package/dist/commonjs/features/chatbot/components/Chat/Chat.js +22 -8
  4. package/dist/commonjs/features/chatbot/components/Chat/Chat.js.map +1 -1
  5. package/dist/commonjs/features/chatbot/components/Chat/ChatbotAvatar.js +44 -0
  6. package/dist/commonjs/features/chatbot/components/Chat/ChatbotAvatar.js.map +1 -0
  7. package/dist/commonjs/features/chatbot/components/Chat/MessageItem.js +2 -0
  8. package/dist/commonjs/features/chatbot/components/Chat/MessageItem.js.map +1 -1
  9. package/dist/commonjs/features/chatbot/components/ChatControls/ChatControls.js +15 -19
  10. package/dist/commonjs/features/chatbot/components/ChatControls/ChatControls.js.map +1 -1
  11. package/dist/commonjs/features/chatbot/components/ChatControls/ChatLauncher.js +42 -0
  12. package/dist/commonjs/features/chatbot/components/ChatControls/ChatLauncher.js.map +1 -0
  13. package/dist/commonjs/features/chatbot/components/ChatMessage/ChatMessage.js.map +1 -1
  14. package/dist/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.js +15 -10
  15. package/dist/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.js.map +1 -1
  16. package/dist/commonjs/features/chatbot/components/Chatbot.js +11 -7
  17. package/dist/commonjs/features/chatbot/components/Chatbot.js.map +1 -1
  18. package/dist/commonjs/features/chatbot/constants.js +18 -5
  19. package/dist/commonjs/features/chatbot/constants.js.map +1 -1
  20. package/dist/commonjs/features/chatbot/helpers.js +6 -1
  21. package/dist/commonjs/features/chatbot/helpers.js.map +1 -1
  22. package/dist/commonjs/features/chatbot/index.js +34 -0
  23. package/dist/commonjs/features/chatbot/index.js.map +1 -1
  24. package/dist/commonjs/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.js +13 -10
  25. package/dist/commonjs/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.js.map +1 -1
  26. package/dist/commonjs/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.js +9 -1
  27. package/dist/commonjs/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.js.map +1 -1
  28. package/dist/commonjs/features/fluency/components/Fluency.js +12 -6
  29. package/dist/commonjs/features/fluency/components/Fluency.js.map +1 -1
  30. package/dist/commonjs/features/fluency/components/FluencyStatusOverlay.js +101 -0
  31. package/dist/commonjs/features/fluency/components/FluencyStatusOverlay.js.map +1 -0
  32. package/dist/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.js +13 -5
  33. package/dist/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.js.map +1 -1
  34. package/dist/commonjs/features/fluency/model/FluencyModel.js +21 -0
  35. package/dist/commonjs/features/fluency/model/FluencyModel.js.map +1 -1
  36. package/dist/commonjs/features/fluency/shared/fluency.constants.js +6 -1
  37. package/dist/commonjs/features/fluency/shared/fluency.constants.js.map +1 -1
  38. package/dist/commonjs/features/fluency/shared/fluency.helpers.js +3 -1
  39. package/dist/commonjs/features/fluency/shared/fluency.helpers.js.map +1 -1
  40. package/dist/commonjs/features/pmProgress/model/PmProgressModel.js +7 -1
  41. package/dist/commonjs/features/pmProgress/model/PmProgressModel.js.map +1 -1
  42. package/dist/commonjs/features/pmProgress/model/PmRecommendationsModel.js +20 -4
  43. package/dist/commonjs/features/pmProgress/model/PmRecommendationsModel.js.map +1 -1
  44. package/dist/commonjs/features/pmProgress/shared/pmProgress.helpers.js +22 -1
  45. package/dist/commonjs/features/pmProgress/shared/pmProgress.helpers.js.map +1 -1
  46. package/dist/commonjs/shared/icons/ExcitedLavaIcon.js +4 -2
  47. package/dist/commonjs/shared/icons/ExcitedLavaIcon.js.map +1 -1
  48. package/dist/commonjs/shared/icons/{ChatbotIcon.js → LavaIcon.js} +8 -8
  49. package/dist/commonjs/shared/icons/LavaIcon.js.map +1 -0
  50. package/dist/commonjs/shared/icons/LavaIconInGlasses.js +4 -4
  51. package/dist/commonjs/shared/icons/LavaIconInGlasses.js.map +1 -1
  52. package/dist/commonjs/shared/icons/index.js +4 -4
  53. package/dist/commonjs/shared/icons/index.js.map +1 -1
  54. package/dist/module/features/chatbot/components/Chat/AIAvatar.js +27 -0
  55. package/dist/module/features/chatbot/components/Chat/AIAvatar.js.map +1 -0
  56. package/dist/module/features/chatbot/components/Chat/Chat.js +23 -9
  57. package/dist/module/features/chatbot/components/Chat/Chat.js.map +1 -1
  58. package/dist/module/features/chatbot/components/Chat/ChatbotAvatar.js +38 -0
  59. package/dist/module/features/chatbot/components/Chat/ChatbotAvatar.js.map +1 -0
  60. package/dist/module/features/chatbot/components/Chat/MessageItem.js +2 -0
  61. package/dist/module/features/chatbot/components/Chat/MessageItem.js.map +1 -1
  62. package/dist/module/features/chatbot/components/ChatControls/ChatControls.js +17 -21
  63. package/dist/module/features/chatbot/components/ChatControls/ChatControls.js.map +1 -1
  64. package/dist/module/features/chatbot/components/ChatControls/ChatLauncher.js +36 -0
  65. package/dist/module/features/chatbot/components/ChatControls/ChatLauncher.js.map +1 -0
  66. package/dist/module/features/chatbot/components/ChatMessage/ChatMessage.js.map +1 -1
  67. package/dist/module/features/chatbot/components/ChatMessage/ReceivedMessage.js +16 -11
  68. package/dist/module/features/chatbot/components/ChatMessage/ReceivedMessage.js.map +1 -1
  69. package/dist/module/features/chatbot/components/Chatbot.js +11 -7
  70. package/dist/module/features/chatbot/components/Chatbot.js.map +1 -1
  71. package/dist/module/features/chatbot/constants.js +17 -4
  72. package/dist/module/features/chatbot/constants.js.map +1 -1
  73. package/dist/module/features/chatbot/helpers.js +5 -1
  74. package/dist/module/features/chatbot/helpers.js.map +1 -1
  75. package/dist/module/features/chatbot/index.js +4 -0
  76. package/dist/module/features/chatbot/index.js.map +1 -1
  77. package/dist/module/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.js +14 -11
  78. package/dist/module/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.js.map +1 -1
  79. package/dist/module/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.js +10 -2
  80. package/dist/module/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.js.map +1 -1
  81. package/dist/module/features/fluency/components/Fluency.js +14 -8
  82. package/dist/module/features/fluency/components/Fluency.js.map +1 -1
  83. package/dist/module/features/fluency/components/FluencyStatusOverlay.js +95 -0
  84. package/dist/module/features/fluency/components/FluencyStatusOverlay.js.map +1 -0
  85. package/dist/module/features/fluency/components/select-math-operator/SelectMathOperator.js +13 -5
  86. package/dist/module/features/fluency/components/select-math-operator/SelectMathOperator.js.map +1 -1
  87. package/dist/module/features/fluency/model/FluencyModel.js +22 -1
  88. package/dist/module/features/fluency/model/FluencyModel.js.map +1 -1
  89. package/dist/module/features/fluency/shared/fluency.constants.js +5 -0
  90. package/dist/module/features/fluency/shared/fluency.constants.js.map +1 -1
  91. package/dist/module/features/fluency/shared/fluency.helpers.js +1 -0
  92. package/dist/module/features/fluency/shared/fluency.helpers.js.map +1 -1
  93. package/dist/module/features/pmProgress/model/PmProgressModel.js +7 -1
  94. package/dist/module/features/pmProgress/model/PmProgressModel.js.map +1 -1
  95. package/dist/module/features/pmProgress/model/PmRecommendationsModel.js +20 -4
  96. package/dist/module/features/pmProgress/model/PmRecommendationsModel.js.map +1 -1
  97. package/dist/module/features/pmProgress/shared/pmProgress.helpers.js +20 -0
  98. package/dist/module/features/pmProgress/shared/pmProgress.helpers.js.map +1 -1
  99. package/dist/module/shared/icons/ExcitedLavaIcon.js +4 -2
  100. package/dist/module/shared/icons/ExcitedLavaIcon.js.map +1 -1
  101. package/dist/module/shared/icons/{ChatbotIcon.js → LavaIcon.js} +6 -6
  102. package/dist/module/shared/icons/LavaIcon.js.map +1 -0
  103. package/dist/module/shared/icons/LavaIconInGlasses.js +4 -4
  104. package/dist/module/shared/icons/LavaIconInGlasses.js.map +1 -1
  105. package/dist/module/shared/icons/index.js +1 -1
  106. package/dist/module/shared/icons/index.js.map +1 -1
  107. package/dist/typescript/commonjs/features/celebrations/helpers.d.ts +1 -1
  108. package/dist/typescript/commonjs/features/celebrations/helpers.d.ts.map +1 -1
  109. package/dist/typescript/commonjs/features/chatbot/components/Chat/AIAvatar.d.ts +4 -0
  110. package/dist/typescript/commonjs/features/chatbot/components/Chat/AIAvatar.d.ts.map +1 -0
  111. package/dist/typescript/commonjs/features/chatbot/components/Chat/Chat.d.ts +3 -1
  112. package/dist/typescript/commonjs/features/chatbot/components/Chat/Chat.d.ts.map +1 -1
  113. package/dist/typescript/commonjs/features/chatbot/components/Chat/ChatbotAvatar.d.ts +9 -0
  114. package/dist/typescript/commonjs/features/chatbot/components/Chat/ChatbotAvatar.d.ts.map +1 -0
  115. package/dist/typescript/commonjs/features/chatbot/components/Chat/MessageItem.d.ts +3 -1
  116. package/dist/typescript/commonjs/features/chatbot/components/Chat/MessageItem.d.ts.map +1 -1
  117. package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatControls.d.ts +8 -10
  118. package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatControls.d.ts.map +1 -1
  119. package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatLauncher.d.ts +10 -0
  120. package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatLauncher.d.ts.map +1 -0
  121. package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ChatMessage.d.ts +2 -0
  122. package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ChatMessage.d.ts.map +1 -1
  123. package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts +1 -1
  124. package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts.map +1 -1
  125. package/dist/typescript/commonjs/features/chatbot/components/Chatbot.d.ts +4 -6
  126. package/dist/typescript/commonjs/features/chatbot/components/Chatbot.d.ts.map +1 -1
  127. package/dist/typescript/commonjs/features/chatbot/constants.d.ts +15 -4
  128. package/dist/typescript/commonjs/features/chatbot/constants.d.ts.map +1 -1
  129. package/dist/typescript/commonjs/features/chatbot/helpers.d.ts +2 -0
  130. package/dist/typescript/commonjs/features/chatbot/helpers.d.ts.map +1 -1
  131. package/dist/typescript/commonjs/features/chatbot/index.d.ts +5 -1
  132. package/dist/typescript/commonjs/features/chatbot/index.d.ts.map +1 -1
  133. package/dist/typescript/commonjs/features/chatbot/types/chat.types.d.ts +3 -0
  134. package/dist/typescript/commonjs/features/chatbot/types/chat.types.d.ts.map +1 -1
  135. package/dist/typescript/commonjs/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.d.ts +2 -1
  136. package/dist/typescript/commonjs/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.d.ts.map +1 -1
  137. package/dist/typescript/commonjs/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.d.ts.map +1 -1
  138. package/dist/typescript/commonjs/features/endOfAssignment/types.d.ts +1 -0
  139. package/dist/typescript/commonjs/features/endOfAssignment/types.d.ts.map +1 -1
  140. package/dist/typescript/commonjs/features/fluency/components/Fluency.d.ts.map +1 -1
  141. package/dist/typescript/commonjs/features/fluency/components/FluencyStatusOverlay.d.ts +8 -0
  142. package/dist/typescript/commonjs/features/fluency/components/FluencyStatusOverlay.d.ts.map +1 -0
  143. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.d.ts.map +1 -1
  144. package/dist/typescript/commonjs/features/fluency/model/FluencyModel.d.ts +3 -0
  145. package/dist/typescript/commonjs/features/fluency/model/FluencyModel.d.ts.map +1 -1
  146. package/dist/typescript/commonjs/features/fluency/shared/fluency.constants.d.ts +4 -0
  147. package/dist/typescript/commonjs/features/fluency/shared/fluency.constants.d.ts.map +1 -1
  148. package/dist/typescript/commonjs/features/fluency/shared/fluency.helpers.d.ts +1 -0
  149. package/dist/typescript/commonjs/features/fluency/shared/fluency.helpers.d.ts.map +1 -1
  150. package/dist/typescript/commonjs/features/keyboard/components/KeysList/KeysList.d.ts +1 -1
  151. package/dist/typescript/commonjs/features/keyboard/components/KeysList/helpers.d.ts +2 -2
  152. package/dist/typescript/commonjs/features/pmProgress/model/PmProgressModel.d.ts.map +1 -1
  153. package/dist/typescript/commonjs/features/pmProgress/model/PmRecommendationsModel.d.ts +9 -38
  154. package/dist/typescript/commonjs/features/pmProgress/model/PmRecommendationsModel.d.ts.map +1 -1
  155. package/dist/typescript/commonjs/features/pmProgress/shared/pmProgress.helpers.d.ts +1 -0
  156. package/dist/typescript/commonjs/features/pmProgress/shared/pmProgress.helpers.d.ts.map +1 -1
  157. package/dist/typescript/commonjs/shared/icons/ExcitedLavaIcon.d.ts +1 -1
  158. package/dist/typescript/commonjs/shared/icons/ExcitedLavaIcon.d.ts.map +1 -1
  159. package/dist/typescript/commonjs/shared/icons/LavaIcon.d.ts +4 -0
  160. package/dist/typescript/commonjs/shared/icons/LavaIcon.d.ts.map +1 -0
  161. package/dist/typescript/commonjs/shared/icons/LavaIconInGlasses.d.ts +2 -2
  162. package/dist/typescript/commonjs/shared/icons/LavaIconInGlasses.d.ts.map +1 -1
  163. package/dist/typescript/commonjs/shared/icons/index.d.ts +1 -1
  164. package/dist/typescript/commonjs/shared/icons/index.d.ts.map +1 -1
  165. package/dist/typescript/module/features/celebrations/helpers.d.ts +1 -1
  166. package/dist/typescript/module/features/celebrations/helpers.d.ts.map +1 -1
  167. package/dist/typescript/module/features/chatbot/components/Chat/AIAvatar.d.ts +4 -0
  168. package/dist/typescript/module/features/chatbot/components/Chat/AIAvatar.d.ts.map +1 -0
  169. package/dist/typescript/module/features/chatbot/components/Chat/Chat.d.ts +3 -1
  170. package/dist/typescript/module/features/chatbot/components/Chat/Chat.d.ts.map +1 -1
  171. package/dist/typescript/module/features/chatbot/components/Chat/ChatbotAvatar.d.ts +9 -0
  172. package/dist/typescript/module/features/chatbot/components/Chat/ChatbotAvatar.d.ts.map +1 -0
  173. package/dist/typescript/module/features/chatbot/components/Chat/MessageItem.d.ts +3 -1
  174. package/dist/typescript/module/features/chatbot/components/Chat/MessageItem.d.ts.map +1 -1
  175. package/dist/typescript/module/features/chatbot/components/ChatControls/ChatControls.d.ts +8 -10
  176. package/dist/typescript/module/features/chatbot/components/ChatControls/ChatControls.d.ts.map +1 -1
  177. package/dist/typescript/module/features/chatbot/components/ChatControls/ChatLauncher.d.ts +10 -0
  178. package/dist/typescript/module/features/chatbot/components/ChatControls/ChatLauncher.d.ts.map +1 -0
  179. package/dist/typescript/module/features/chatbot/components/ChatMessage/ChatMessage.d.ts +2 -0
  180. package/dist/typescript/module/features/chatbot/components/ChatMessage/ChatMessage.d.ts.map +1 -1
  181. package/dist/typescript/module/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts +1 -1
  182. package/dist/typescript/module/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts.map +1 -1
  183. package/dist/typescript/module/features/chatbot/components/Chatbot.d.ts +4 -6
  184. package/dist/typescript/module/features/chatbot/components/Chatbot.d.ts.map +1 -1
  185. package/dist/typescript/module/features/chatbot/constants.d.ts +15 -4
  186. package/dist/typescript/module/features/chatbot/constants.d.ts.map +1 -1
  187. package/dist/typescript/module/features/chatbot/helpers.d.ts +2 -0
  188. package/dist/typescript/module/features/chatbot/helpers.d.ts.map +1 -1
  189. package/dist/typescript/module/features/chatbot/index.d.ts +5 -1
  190. package/dist/typescript/module/features/chatbot/index.d.ts.map +1 -1
  191. package/dist/typescript/module/features/chatbot/types/chat.types.d.ts +3 -0
  192. package/dist/typescript/module/features/chatbot/types/chat.types.d.ts.map +1 -1
  193. package/dist/typescript/module/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.d.ts +2 -1
  194. package/dist/typescript/module/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.d.ts.map +1 -1
  195. package/dist/typescript/module/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.d.ts.map +1 -1
  196. package/dist/typescript/module/features/endOfAssignment/types.d.ts +1 -0
  197. package/dist/typescript/module/features/endOfAssignment/types.d.ts.map +1 -1
  198. package/dist/typescript/module/features/fluency/components/Fluency.d.ts.map +1 -1
  199. package/dist/typescript/module/features/fluency/components/FluencyStatusOverlay.d.ts +8 -0
  200. package/dist/typescript/module/features/fluency/components/FluencyStatusOverlay.d.ts.map +1 -0
  201. package/dist/typescript/module/features/fluency/components/select-math-operator/SelectMathOperator.d.ts.map +1 -1
  202. package/dist/typescript/module/features/fluency/model/FluencyModel.d.ts +3 -0
  203. package/dist/typescript/module/features/fluency/model/FluencyModel.d.ts.map +1 -1
  204. package/dist/typescript/module/features/fluency/shared/fluency.constants.d.ts +4 -0
  205. package/dist/typescript/module/features/fluency/shared/fluency.constants.d.ts.map +1 -1
  206. package/dist/typescript/module/features/fluency/shared/fluency.helpers.d.ts +1 -0
  207. package/dist/typescript/module/features/fluency/shared/fluency.helpers.d.ts.map +1 -1
  208. package/dist/typescript/module/features/keyboard/components/KeysList/KeysList.d.ts +1 -1
  209. package/dist/typescript/module/features/keyboard/components/KeysList/helpers.d.ts +2 -2
  210. package/dist/typescript/module/features/pmProgress/model/PmProgressModel.d.ts.map +1 -1
  211. package/dist/typescript/module/features/pmProgress/model/PmRecommendationsModel.d.ts +9 -38
  212. package/dist/typescript/module/features/pmProgress/model/PmRecommendationsModel.d.ts.map +1 -1
  213. package/dist/typescript/module/features/pmProgress/shared/pmProgress.helpers.d.ts +1 -0
  214. package/dist/typescript/module/features/pmProgress/shared/pmProgress.helpers.d.ts.map +1 -1
  215. package/dist/typescript/module/shared/icons/ExcitedLavaIcon.d.ts +1 -1
  216. package/dist/typescript/module/shared/icons/ExcitedLavaIcon.d.ts.map +1 -1
  217. package/dist/typescript/module/shared/icons/LavaIcon.d.ts +4 -0
  218. package/dist/typescript/module/shared/icons/LavaIcon.d.ts.map +1 -0
  219. package/dist/typescript/module/shared/icons/LavaIconInGlasses.d.ts +2 -2
  220. package/dist/typescript/module/shared/icons/LavaIconInGlasses.d.ts.map +1 -1
  221. package/dist/typescript/module/shared/icons/index.d.ts +1 -1
  222. package/dist/typescript/module/shared/icons/index.d.ts.map +1 -1
  223. package/package.json +13 -20
  224. package/src/features/chatbot/components/Chat/AIAvatar.tsx +22 -0
  225. package/src/features/chatbot/components/Chat/Chat.tsx +30 -8
  226. package/src/features/chatbot/components/Chat/ChatbotAvatar.tsx +44 -0
  227. package/src/features/chatbot/components/Chat/MessageItem.tsx +4 -0
  228. package/src/features/chatbot/components/ChatControls/ChatControls.tsx +26 -21
  229. package/src/features/chatbot/components/ChatControls/ChatLauncher.tsx +44 -0
  230. package/src/features/chatbot/components/ChatMessage/ChatMessage.tsx +2 -0
  231. package/src/features/chatbot/components/ChatMessage/ReceivedMessage.tsx +27 -8
  232. package/src/features/chatbot/components/Chatbot.tsx +11 -7
  233. package/src/features/chatbot/constants.ts +18 -3
  234. package/src/features/chatbot/helpers.ts +14 -1
  235. package/src/features/chatbot/index.ts +10 -1
  236. package/src/features/chatbot/types/chat.types.ts +4 -0
  237. package/src/features/endOfAssignment/components/CorrectAnswer/AnimatedCard.tsx +18 -8
  238. package/src/features/endOfAssignment/components/CorrectAnswer/CorrectAnswer.tsx +12 -2
  239. package/src/features/endOfAssignment/types.ts +1 -0
  240. package/src/features/fluency/components/Fluency.tsx +17 -9
  241. package/src/features/fluency/components/FluencyStatusOverlay.tsx +101 -0
  242. package/src/features/fluency/components/select-math-operator/SelectMathOperator.tsx +13 -5
  243. package/src/features/fluency/model/FluencyModel.ts +25 -1
  244. package/src/features/fluency/shared/fluency.constants.ts +5 -0
  245. package/src/features/fluency/shared/fluency.helpers.ts +3 -0
  246. package/src/features/pmProgress/model/PmProgressModel.ts +4 -1
  247. package/src/features/pmProgress/model/PmRecommendationsModel.ts +22 -6
  248. package/src/features/pmProgress/shared/pmProgress.helpers.ts +33 -0
  249. package/src/i18n/.generated/schema.json +7 -3
  250. package/src/shared/icons/ExcitedLavaIcon.tsx +5 -1
  251. package/src/shared/icons/{ChatbotIcon.tsx → LavaIcon.tsx} +5 -3
  252. package/src/shared/icons/LavaIconInGlasses.tsx +5 -3
  253. package/src/shared/icons/index.ts +1 -1
  254. package/dist/commonjs/features/chatbot/components/Chat/ChatIcon.js +0 -37
  255. package/dist/commonjs/features/chatbot/components/Chat/ChatIcon.js.map +0 -1
  256. package/dist/commonjs/shared/icons/ChatbotIcon.js.map +0 -1
  257. package/dist/module/features/chatbot/components/Chat/ChatIcon.js +0 -31
  258. package/dist/module/features/chatbot/components/Chat/ChatIcon.js.map +0 -1
  259. package/dist/module/shared/icons/ChatbotIcon.js.map +0 -1
  260. package/dist/typescript/commonjs/features/chatbot/components/Chat/ChatIcon.d.ts +0 -7
  261. package/dist/typescript/commonjs/features/chatbot/components/Chat/ChatIcon.d.ts.map +0 -1
  262. package/dist/typescript/commonjs/shared/icons/ChatbotIcon.d.ts +0 -4
  263. package/dist/typescript/commonjs/shared/icons/ChatbotIcon.d.ts.map +0 -1
  264. package/dist/typescript/module/features/chatbot/components/Chat/ChatIcon.d.ts +0 -7
  265. package/dist/typescript/module/features/chatbot/components/Chat/ChatIcon.d.ts.map +0 -1
  266. package/dist/typescript/module/shared/icons/ChatbotIcon.d.ts +0 -4
  267. package/dist/typescript/module/shared/icons/ChatbotIcon.d.ts.map +0 -1
  268. package/src/features/chatbot/components/Chat/ChatIcon.tsx +0 -30
@@ -1,31 +1,47 @@
1
1
  import React from 'react'
2
2
  import { Platform, StyleSheet, View } from 'react-native'
3
3
  import { BORDER_RADIUS, SPACING } from '@magmamath/react-native-ui'
4
- import { CHATBOT_ICON_SIZE, MESSAGE_WIDTH } from '../../constants'
5
- import { ChatbotIcon } from '@magmamath/students-features'
4
+ import { TEST_IDS } from '@magmamath/students-qa'
5
+
6
+ import {
7
+ AI_AVATAR_CONTAINER_WIDTH,
8
+ ChatbotVariant,
9
+ LAVA_ICON_SIZE,
10
+ MESSAGE_WIDTH,
11
+ } from '../../constants'
12
+ import { getChatbotAvatarVariant } from '../../helpers'
6
13
  import { ColorScheme } from '../../types/style.types'
7
14
  import { MessageVariant } from '../../types/model.types'
8
15
  import { VariantProps } from './ChatMessage'
9
16
  import { MessageContent } from './MessageContent'
10
- import { TEST_IDS } from '@magmamath/students-qa'
17
+ import { ChatbotAvatar } from '../Chat/ChatbotAvatar'
11
18
 
12
19
  export const ReceivedMessage = ({
13
20
  message,
14
21
  isTranslated,
15
22
  t2sState,
16
23
  withIcon,
24
+ chatbotVariant = ChatbotVariant.LAVA,
17
25
  colorScheme = ColorScheme.Blue,
18
26
  withErrorSpotting,
19
27
  highlightedWordIndex,
20
28
  TTSHighlightRenderer,
21
29
  }: VariantProps) => {
22
30
  const text = isTranslated ? message.translatedMessage : message.message
31
+ const avatarVariant = getChatbotAvatarVariant(chatbotVariant)
23
32
 
24
33
  return (
25
34
  <View style={styles.container} testID={TEST_IDS.CHAT_MESSAGE_RECEIVED}>
26
- <View style={[styles.iconWrapper, { opacity: withIcon ? 1 : 0 }]}>
27
- <ChatbotIcon width={CHATBOT_ICON_SIZE.width} height={CHATBOT_ICON_SIZE.height} />
35
+ <View
36
+ style={[
37
+ styles.chatbotAvatarContainer,
38
+ chatbotVariant === ChatbotVariant.AI && styles.chatbotAIAvatarContainer,
39
+ { opacity: withIcon ? 1 : 0 },
40
+ ]}
41
+ >
42
+ <ChatbotAvatar variant={avatarVariant} />
28
43
  </View>
44
+
29
45
  <View style={styles.message}>
30
46
  <MessageContent
31
47
  message={message}
@@ -52,7 +68,7 @@ const styles = StyleSheet.create({
52
68
  message: {
53
69
  width: MESSAGE_WIDTH,
54
70
  flexDirection: 'row',
55
- padding: 8,
71
+ padding: SPACING['200'],
56
72
  shadowColor: '#333',
57
73
  shadowOffset: { width: 0, height: 1 },
58
74
  shadowOpacity: 0.25,
@@ -63,9 +79,12 @@ const styles = StyleSheet.create({
63
79
  backgroundColor: '#F2F2F4',
64
80
  ...Platform.select({ web: { backfaceVisibility: 'hidden' } }),
65
81
  },
66
- iconWrapper: {
67
- width: CHATBOT_ICON_SIZE.width + SPACING[200],
82
+ chatbotAvatarContainer: {
68
83
  alignItems: 'flex-start',
69
84
  justifyContent: 'flex-end',
85
+ width: LAVA_ICON_SIZE + SPACING[200],
86
+ },
87
+ chatbotAIAvatarContainer: {
88
+ width: AI_AVATAR_CONTAINER_WIDTH,
70
89
  },
71
90
  })
@@ -4,7 +4,7 @@ import { useStoreMap, useUnit } from 'effector-react'
4
4
  import { ChatbotModel } from '../model/ChatBotModel'
5
5
  import { Chat } from './Chat/Chat'
6
6
  import { ChatControls } from './ChatControls/ChatControls'
7
- import { AUDIO_CONFIG, DEFAULT_VOICE } from '../constants'
7
+ import { AUDIO_CONFIG, ChatbotVariant, DEFAULT_VOICE } from '../constants'
8
8
  import { ChatBotModelContext } from '../context/ChatBotModelContext'
9
9
  import { ColorScheme } from '../types/style.types'
10
10
  import { TTSHighlightRenderer } from '../types/t2s.types'
@@ -19,11 +19,12 @@ type ChatbotProps = {
19
19
  audioConfig: typeof AUDIO_CONFIG
20
20
  }
21
21
  ButtonWrapper?: ComponentType<PropsWithChildren>
22
- iconSize?: { width: number; height: number } // TODO: use number instead
22
+ iconSize?: number
23
23
  isInputDisabled?: boolean
24
24
  colorScheme?: ColorScheme
25
25
  TTSHighlightRenderer?: TTSHighlightRenderer
26
26
  maxHeight?: number
27
+ variant?: ChatbotVariant
27
28
  }
28
29
 
29
30
  export const Chatbot = ({
@@ -31,6 +32,7 @@ export const Chatbot = ({
31
32
  isHintFeedback,
32
33
  isTextToSpeechEnabled = false,
33
34
  isInputDisabled,
35
+ variant = ChatbotVariant.LAVA,
34
36
  textToSpeechConfig,
35
37
  ButtonWrapper,
36
38
  iconSize,
@@ -69,23 +71,25 @@ export const Chatbot = ({
69
71
  <ChatBotModelContext.Provider value={model}>
70
72
  <Chat
71
73
  model={model}
74
+ onPressClose={closeChat}
72
75
  colorScheme={colorScheme}
73
76
  isHintFeedback={isHintFeedback}
74
77
  isTextToSpeechEnabled={isTextToSpeechEnabled}
75
78
  isInputDisabled={isInputDisabled}
79
+ chatbotVariant={variant}
76
80
  maxHeight={maxHeight}
77
81
  MessageWrapper={ButtonWrapper}
78
82
  TTSHighlightRenderer={TTSHighlightRenderer}
79
- onPressClose={closeChat}
80
83
  />
81
84
 
82
85
  <ChatControls
83
86
  model={model}
84
- onPressChatIcon={openChat}
85
- onPressHelpButton={sendHelpRequest}
86
- iconSize={iconSize}
87
+ onPressChatLauncher={openChat}
88
+ onPressQuickAction={sendHelpRequest}
89
+ chatbotIconSize={iconSize}
90
+ chatbotVariant={variant}
91
+ withQuickActionButton={withQuickActionButton && !hasBeenOpened}
87
92
  ButtonWrapper={isInputDisabled ? undefined : ButtonWrapper}
88
- withHelpButton={withQuickActionButton && !hasBeenOpened}
89
93
  />
90
94
  </ChatBotModelContext.Provider>
91
95
  )
@@ -1,8 +1,7 @@
1
- import { ButtonColor, COLORS, IS_WEB } from '@magmamath/react-native-ui'
1
+ import { COLORS, IS_WEB } from '@magmamath/react-native-ui'
2
2
  import { Platform } from 'react-native'
3
3
  import { MessageVariant } from './types/model.types'
4
4
  import { ColorScheme } from './types/style.types'
5
- import { ANIMATION_DURATION } from '../gifCelebrations/constants'
6
5
 
7
6
  export const AUDIO_CONFIG = {
8
7
  audioEncoding: 'LINEAR16',
@@ -90,4 +89,20 @@ export const SCROLL_BOTTOM_THRESHOLD = 0.5
90
89
  export const MESSAGE_WIDTH = 304
91
90
  export const INPUT_WIDTH = IS_WEB ? MESSAGE_WIDTH : 301
92
91
  export const CHAT_CONTAINER_WIDTH = 370
93
- export const CHATBOT_ICON_SIZE = { width: 51, height: 73 }
92
+ export const LAVA_ICON_SIZE = 51
93
+ export const AI_ICON_SIZE = 25
94
+ export const AI_AVATAR_BORDER_RADIUS = 25
95
+ export const AI_AVATAR_CONTAINER_WIDTH = 59
96
+ export const FLOATING_AVATAR_BOTTOM = IS_WEB ? 67.4 : 59
97
+
98
+ export enum ChatbotVariant {
99
+ LAVA = 'LAVA',
100
+ AI = 'AI',
101
+ }
102
+
103
+ export enum ChatbotAvatarVariant {
104
+ AI = 'AI',
105
+ LAVA = 'LAVA',
106
+ THINKING_LAVA = 'THINKING_LAVA',
107
+ EXCITED_LAVA = 'EXCITED_LAVA',
108
+ }
@@ -1,11 +1,24 @@
1
1
  import { IS_WEB } from '@magmamath/react-native-ui'
2
2
  // https://stackoverflow.com/questions/56575859/google-translate-api-does-not-return-apostrophe-as-apostrophe-in-python
3
- import { KATEX_REPLACEMENTS, KATEX_REPLACEMENTS_REVERSE } from './constants'
3
+ import {
4
+ ChatbotAvatarVariant,
5
+ ChatbotVariant,
6
+ KATEX_REPLACEMENTS,
7
+ KATEX_REPLACEMENTS_REVERSE,
8
+ } from './constants'
4
9
  import { GetAlternativesResponse, PostMessagePayload } from './types/api.types'
5
10
  import { getText as t } from '../../i18n/i18n'
6
11
  import { ThreadItem } from './model/ThreadItem'
7
12
  import { ChatRequestPayload, ChatRequestType } from './types/model.types'
8
13
 
14
+ export const getChatbotAvatarVariant = (
15
+ variant: ChatbotVariant,
16
+ isLoading = false,
17
+ ): ChatbotAvatarVariant => {
18
+ if (variant === ChatbotVariant.AI) return ChatbotAvatarVariant.AI
19
+ return isLoading ? ChatbotAvatarVariant.THINKING_LAVA : ChatbotAvatarVariant.LAVA
20
+ }
21
+
9
22
  export const decodeHTMLEntities = (input: string) => {
10
23
  return input.replace(/&#39;/g, "'")
11
24
  }
@@ -1,11 +1,20 @@
1
1
  export { Chatbot } from './components/Chatbot'
2
+ export { ChatbotAvatar } from './components/Chat/ChatbotAvatar'
3
+ export { ChatLauncher } from './components/ChatControls/ChatLauncher'
2
4
  export { ChatbotModel } from './model/ChatBotModel'
3
- export { AudioStatus, type AudioProvider, type TTSHighlightRenderer, type TTSHighlightRendererProps } from './types/t2s.types'
5
+ export {
6
+ AudioStatus,
7
+ type AudioProvider,
8
+ type TTSHighlightRenderer,
9
+ type TTSHighlightRendererProps,
10
+ } from './types/t2s.types'
4
11
  export {
5
12
  MessageVariant,
6
13
  type ChatbotModelProps,
7
14
  type IChatDrawBoardAdapter,
8
15
  } from './types/model.types'
16
+ export { ChatbotAvatarVariant, ChatbotVariant } from './constants'
17
+ export { getChatbotAvatarVariant } from './helpers'
9
18
  export type { RequestOptionalConfig } from '../../lib/effector/createControllerEffect'
10
19
  export type {
11
20
  PostMessageResponse,
@@ -17,3 +17,7 @@ export type ScrollState = {
17
17
  export type FadeOverlaysProps = {
18
18
  fadeRef: MutableRefObject<FadeUpdateFn | null>
19
19
  }
20
+
21
+ export type AvatarProps = {
22
+ size?: number
23
+ }
@@ -41,6 +41,7 @@ type AnimatedCardProps = {
41
41
  gbdAmount?: number
42
42
  delay?: number
43
43
  onAnimationEnd?: () => void
44
+ disableStarsAnimation?: boolean
44
45
  }
45
46
 
46
47
  export const AnimatedCard = memo(
@@ -53,6 +54,7 @@ export const AnimatedCard = memo(
53
54
  gbdAmount = 0,
54
55
  delay = 0,
55
56
  onAnimationEnd,
57
+ disableStarsAnimation = false,
56
58
  }: AnimatedCardProps) => {
57
59
  const celebrationsRef = useRef<CelebrationsRef>(null)
58
60
 
@@ -171,15 +173,23 @@ export const AnimatedCard = memo(
171
173
 
172
174
  return (
173
175
  <Animated.View style={styles.cardContainer}>
174
- {variant === AnimatedCardVariant.CORRECT_ANSWER ? (
175
- <CorrectAnswerSparks
176
- color={COLORS.GREEN_3}
177
- shouldStartAnimation={shouldTriggerSparkles}
178
- />
179
- ) : (
180
- <GoodDrawingSparks color={COLORS.ORANGE_3} shouldStartAnimation={shouldTriggerSparkles} />
176
+ {!disableStarsAnimation && (
177
+ <>
178
+ {variant === AnimatedCardVariant.CORRECT_ANSWER ? (
179
+ <CorrectAnswerSparks
180
+ color={COLORS.GREEN_3}
181
+ shouldStartAnimation={shouldTriggerSparkles}
182
+ />
183
+ ) : (
184
+ <GoodDrawingSparks
185
+ color={COLORS.ORANGE_3}
186
+ shouldStartAnimation={shouldTriggerSparkles}
187
+ />
188
+ )}
189
+
190
+ <Celebrations modelRef={celebrationsRef} style={styles.celebrations} />
191
+ </>
181
192
  )}
182
- <Celebrations modelRef={celebrationsRef} style={styles.celebrations} />
183
193
 
184
194
  <Animated.View style={[styles.card, animatedCardStyle]}>
185
195
  <Animated.View style={styles.cardContent}>
@@ -1,7 +1,7 @@
1
1
  import React, { useCallback, useState } from 'react'
2
2
  import { View, StyleSheet } from 'react-native'
3
3
  import { useUnit } from 'effector-react'
4
- import { SPACING, Typography, COLORS, FONT_FAMILY } from '@magmamath/react-native-ui'
4
+ import { SPACING, Typography, COLORS, FONT_FAMILY, IS_MOBILE } from '@magmamath/react-native-ui'
5
5
 
6
6
  import { AnimatedCard } from './AnimatedCard'
7
7
 
@@ -25,6 +25,7 @@ export const CorrectAnswer = ({ textContent, model, onPracticePress }: EOAModalC
25
25
  hasRecommendations,
26
26
  isExam = false,
27
27
  isAssessment = false,
28
+ isMatureMode = false,
28
29
  newerAssignmentAvailable,
29
30
  } = popUpData ?? {}
30
31
 
@@ -67,7 +68,11 @@ export const CorrectAnswer = ({ textContent, model, onPracticePress }: EOAModalC
67
68
  ]}
68
69
  >
69
70
  <View style={styles.header}>
70
- <Typography variant="large" style={styles.title}>
71
+ <Typography
72
+ variant="large"
73
+ style={[styles.title, IS_MOBILE && styles.mobileTitle]}
74
+ //different fontFamily style for mobile because of a bug in rn
75
+ >
71
76
  {textContent?.title}
72
77
  </Typography>
73
78
  <Typography variant="h4" style={styles.subtitle}>
@@ -89,6 +94,7 @@ export const CorrectAnswer = ({ textContent, model, onPracticePress }: EOAModalC
89
94
  solvedAmount={stats?.solvedAmount}
90
95
  problemsAmount={stats?.problemsAmount}
91
96
  shouldTriggerSparkles={cardsAnimationCompleted}
97
+ disableStarsAnimation={isMatureMode}
92
98
  onAnimationEnd={onCorrectAnswerAnimationEnd}
93
99
  />
94
100
  )}
@@ -100,6 +106,7 @@ export const CorrectAnswer = ({ textContent, model, onPracticePress }: EOAModalC
100
106
  gbdAmount={stats?.goodDrawingAmount}
101
107
  shouldTriggerSparkles={cardsAnimationCompleted}
102
108
  onAnimationEnd={onGBDAnimationEnd}
109
+ disableStarsAnimation={isMatureMode}
103
110
  delay={GOOD_DRAWING_CARD_APPEARENCE_DELAY}
104
111
  />
105
112
  )}
@@ -133,6 +140,9 @@ const styles = StyleSheet.create({
133
140
  color: COLORS.NEUTRAL_9,
134
141
  fontFamily: FONT_FAMILY.buenosAires,
135
142
  },
143
+ mobileTitle: {
144
+ fontFamily: 'BuenosAires-Black',
145
+ },
136
146
  subtitle: {
137
147
  color: COLORS.NEUTRAL_7,
138
148
  paddingVertical: SPACING[100],
@@ -38,6 +38,7 @@ export type EOAModalContentProps = {
38
38
 
39
39
  export type EOAModalData = {
40
40
  isExam: boolean
41
+ isMatureMode: boolean
41
42
  isAssessment: boolean
42
43
  newerAssignmentAvailable?: boolean
43
44
  examFinished?: boolean
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { useGate } from 'effector-react'
2
+ import { useGate, useUnit } from 'effector-react'
3
3
  import { View, StyleSheet } from 'react-native'
4
4
  import { Typography, HeadingVariants, SPACING, COLORS } from '@magmamath/react-native-ui'
5
5
  import { useText } from '../../../i18n/i18n'
@@ -8,6 +8,7 @@ import { DayStreakCounter } from './day-streak-counter/DayStreakCounter'
8
8
  import { SelectMathOperator } from './select-math-operator/SelectMathOperator'
9
9
  import { FluencyMatrix } from './matrix/FluencyMatrix'
10
10
  import { MobileMenu } from './mobile-menu/MobileMenu'
11
+ import { FluencyStatusOverlay } from './FluencyStatusOverlay'
11
12
  import { FluencyProvider } from '../context/FluencyContext'
12
13
  import type { FluencyModel } from '../model/FluencyModel'
13
14
  import type { FluencyMode } from '../shared/fluency.constants'
@@ -32,6 +33,7 @@ export const Fluency = ({
32
33
  }: FluencyProps) => {
33
34
  useGate(model.gate, { config })
34
35
  const t = useText()
36
+ const status = useUnit(model.$status)
35
37
 
36
38
  return (
37
39
  <FluencyProvider value={{ model, onStartPress, onPracticePress, onModeSelectPress }}>
@@ -43,15 +45,21 @@ export const Fluency = ({
43
45
  </Typography>
44
46
  </View>
45
47
 
46
- <View style={styles.header}>
47
- <StartBanner />
48
- <DayStreakCounter />
49
- </View>
48
+ {status ? (
49
+ <FluencyStatusOverlay status={status} />
50
+ ) : (
51
+ <>
52
+ <View style={styles.header}>
53
+ <StartBanner />
54
+ <DayStreakCounter />
55
+ </View>
50
56
 
51
- <View style={styles.matrix}>
52
- <SelectMathOperator />
53
- <FluencyMatrix />
54
- </View>
57
+ <View style={styles.matrix}>
58
+ <SelectMathOperator />
59
+ <FluencyMatrix />
60
+ </View>
61
+ </>
62
+ )}
55
63
  </View>
56
64
  </FluencyProvider>
57
65
  )
@@ -0,0 +1,101 @@
1
+ import React, { ReactNode } from 'react'
2
+ import { StyleSheet, View } from 'react-native'
3
+ import {
4
+ COLORS,
5
+ ErrorIcon,
6
+ HeadingVariants,
7
+ InfoIcon,
8
+ SPACING,
9
+ Typography,
10
+ } from '@magmamath/react-native-ui'
11
+ import { FluencyStatus } from '../shared/fluency.constants'
12
+ import type { TranslationKey } from '../../../i18n/i18n'
13
+ import { useText } from '../../../i18n/i18n'
14
+
15
+ type StatusVariant = {
16
+ icon: ReactNode
17
+ circleColor: string
18
+ titleKey: TranslationKey
19
+ subtitleKey: TranslationKey
20
+ }
21
+
22
+ const FLUENCY_STATUS_VARIANTS: Record<FluencyStatus, StatusVariant> = {
23
+ [FluencyStatus.ERROR]: {
24
+ icon: <ErrorIcon color={COLORS.PRIMARY_RED} size={40} />,
25
+ circleColor: COLORS.RED_1,
26
+ titleKey: 'student.fluency.errorTitle',
27
+ subtitleKey: 'student.fluency.errorSubtitle',
28
+ },
29
+ [FluencyStatus.EMPTY]: {
30
+ icon: <InfoIcon color={COLORS.NEUTRAL_6} size={40} />,
31
+ circleColor: COLORS.NEUTRAL_2,
32
+ titleKey: 'student.fluency.emptyTitle',
33
+ subtitleKey: 'student.fluency.emptySubtitle',
34
+ },
35
+ }
36
+
37
+ type FluencyStatusOverlayProps = {
38
+ status: FluencyStatus
39
+ }
40
+
41
+ export const FluencyStatusOverlay = ({ status }: FluencyStatusOverlayProps) => {
42
+ const t = useText()
43
+
44
+ const variant = FLUENCY_STATUS_VARIANTS[status]
45
+ if (!variant) return null
46
+
47
+ return (
48
+ <View style={styles.container}>
49
+ <View style={styles.content}>
50
+ <View style={[styles.iconCircle, { backgroundColor: variant.circleColor }]}>
51
+ {variant.icon}
52
+ </View>
53
+ <View style={styles.text}>
54
+ <Typography variant={HeadingVariants.H2} style={styles.title}>
55
+ {t(variant.titleKey)}
56
+ </Typography>
57
+ <Typography variant={HeadingVariants.H7} style={styles.subtitle}>
58
+ {t(variant.subtitleKey)}
59
+ </Typography>
60
+ </View>
61
+ </View>
62
+ </View>
63
+ )
64
+ }
65
+
66
+ const styles = StyleSheet.create({
67
+ container: {
68
+ flex: 1,
69
+ alignItems: 'center',
70
+ justifyContent: 'center',
71
+ },
72
+ content: {
73
+ alignItems: 'center',
74
+ gap: SPACING[500],
75
+ paddingBottom: SPACING[800],
76
+ },
77
+ iconCircle: {
78
+ width: 88,
79
+ height: 88,
80
+ borderRadius: 44,
81
+ alignItems: 'center',
82
+ justifyContent: 'center',
83
+ },
84
+ text: {
85
+ alignItems: 'center',
86
+ gap: SPACING[200],
87
+ maxWidth: 340,
88
+ },
89
+ title: {
90
+ color: COLORS.NEUTRAL_9,
91
+ textAlign: 'center',
92
+ fontSize: 24,
93
+ fontWeight: '500',
94
+ },
95
+ subtitle: {
96
+ color: COLORS.NEUTRAL_7,
97
+ textAlign: 'center',
98
+ fontSize: 16,
99
+ fontWeight: '400',
100
+ },
101
+ })
@@ -17,14 +17,22 @@ import { useText } from '../../../../i18n/i18n'
17
17
  export const SelectMathOperator = () => {
18
18
  const t = useText()
19
19
  const { model, onModeSelectPress } = useFluency()
20
- const fluencyMode = useUnit(model.matrix.$mode)
21
- const matrix = useUnit(model.matrix.$data)
20
+ const { fluencyMode, matrix } = useUnit({
21
+ fluencyMode: model.matrix.$mode,
22
+ matrix: model.matrix.$data,
23
+ })
24
+
25
+ const visibleModes = matrix
26
+ ? FLUENCY_MODES.filter(
27
+ ({ mode }) => Object.keys(matrix.operations?.[mode]?.facts ?? {}).length > 0,
28
+ )
29
+ : FLUENCY_MODES
22
30
 
23
31
  return (
24
32
  <View style={styles.container}>
25
- {FLUENCY_MODES.map(({ mode, label, symbol, select }, index) => {
33
+ {visibleModes.map(({ mode, label, symbol, select }, index) => {
26
34
  const isSelectedMode = mode === fluencyMode
27
- const progress = (matrix?.operations[mode].completionRate ?? 0) * 100
35
+ const progress = (matrix?.operations?.[mode]?.completionRate ?? 0) * 100
28
36
 
29
37
  return (
30
38
  <MathOperatorRow
@@ -45,7 +53,7 @@ export const SelectMathOperator = () => {
45
53
  model.matrix.setMode(mode)
46
54
  onModeSelectPress?.(mode)
47
55
  }}
48
- showDivider={index < FLUENCY_MODES.length - 1}
56
+ showDivider={index < visibleModes.length - 1}
49
57
  />
50
58
  )
51
59
  })}
@@ -5,7 +5,8 @@ import { FluencyDaysStreakModel } from './FluencyDaysStreakModel'
5
5
  import { FluencyMatrixModel } from './FluencyMatrixModel'
6
6
  import { FluencyApiModel } from './FluencyApiModel'
7
7
  import { FluencySolvingModel } from './FluencySolvingModel'
8
- import { MatrixConfig } from '../shared/fluency.constants'
8
+ import { FluencyStatus, MatrixConfig } from '../shared/fluency.constants'
9
+ import { allFactsEmpty } from '../shared/fluency.helpers'
9
10
  import type {
10
11
  FluencyAttemptPayload,
11
12
  FluencyConfig,
@@ -16,6 +17,7 @@ import type {
16
17
  export class FluencyModel {
17
18
  public readonly gate = createGate<FluencyModelGateProps>()
18
19
  public readonly $config = createStore<FluencyConfig | null>(null)
20
+ public readonly $status = createStore<FluencyStatus | null>(null)
19
21
 
20
22
  public readonly api: FluencyApiModel
21
23
  public readonly streak: FluencyDaysStreakModel
@@ -29,6 +31,7 @@ export class FluencyModel {
29
31
  this.solving = new FluencySolvingModel(this.matrix, this.$config)
30
32
 
31
33
  this.init()
34
+ this.setupStatusTracking()
32
35
  }
33
36
 
34
37
  private init() {
@@ -63,4 +66,25 @@ export class FluencyModel {
63
66
  target: this.api.postAttemptFx,
64
67
  })
65
68
  }
69
+
70
+ private setupStatusTracking() {
71
+ sample({
72
+ clock: this.gate.open,
73
+ fn: () => null as FluencyStatus | null,
74
+ target: this.$status,
75
+ })
76
+
77
+ sample({
78
+ clock: [this.api.getMatrixFx.fail, this.api.getWeeklyStatsFx.fail],
79
+ fn: () => FluencyStatus.ERROR,
80
+ target: this.$status,
81
+ })
82
+
83
+ sample({
84
+ clock: this.api.getMatrixFx.doneData,
85
+ filter: allFactsEmpty,
86
+ fn: () => FluencyStatus.EMPTY,
87
+ target: this.$status,
88
+ })
89
+ }
66
90
  }
@@ -106,3 +106,8 @@ export const FLUENCY_MODE_PRESETS: Record<FluencyMode, FluencyModePreset> = Obje
106
106
  ) as Record<FluencyMode, FluencyModePreset>
107
107
 
108
108
  export const ONE_DAY_MS = 86_400_000
109
+
110
+ export enum FluencyStatus {
111
+ ERROR = 'ERROR',
112
+ EMPTY = 'EMPTY',
113
+ }
@@ -117,6 +117,9 @@ export const buildMatrixGrid = (data: GetMatrixResponse, mode: FluencyMode): Mat
117
117
  return [headerRow, ...dataRows]
118
118
  }
119
119
 
120
+ export const allFactsEmpty = (response: GetMatrixResponse): boolean =>
121
+ Object.values(response.operations).every((op) => Object.keys(op.facts).length === 0)
122
+
120
123
  export const generateStreakDates = (stats: GetWeeklyStatsResponse) => {
121
124
  const todayMs = new Date().setHours(0, 0, 0, 0)
122
125
  const startMs = new Date(stats.weekStart).setHours(0, 0, 0, 0)
@@ -43,7 +43,10 @@ export class PmProgressModel {
43
43
 
44
44
  sample({
45
45
  clock: this.tree.initTreeFx.done,
46
- fn: ({ result: [tree] }) => tree,
46
+ fn: ({ params: { user }, result: [tree] }) => ({
47
+ tree,
48
+ lockedGrades: user.setting.practiceModeLockedGrades,
49
+ }),
47
50
  target: this.recommendations.initRecommendationsFx,
48
51
  })
49
52
  }
@@ -2,6 +2,12 @@ import { PmProgressApi } from './PmProgressApi'
2
2
  import { createEffect, createEvent, createStore, sample } from 'effector'
3
3
  import { Recommendations, RecsResponse, TreeMappingResponse } from '../shared/pmProgress.types'
4
4
  import { RECOMMENDATIONS_LIMIT_PARAM, SolvingFlow } from '../shared/pmProgress.constants'
5
+ import { filterLockedGradeRecs } from '../shared/pmProgress.helpers'
6
+
7
+ type FetchMagmaRecsParams = {
8
+ tree: TreeMappingResponse
9
+ lockedGrades: number[]
10
+ }
5
11
 
6
12
  const EMPTY_RECS: Recommendations = { items: [], offset: 0, limit: 0, total: 0 }
7
13
 
@@ -22,14 +28,24 @@ export class PmRecommendationsModel {
22
28
  ),
23
29
  )
24
30
 
25
- public readonly fetchMagmaRecsFx = createEffect((tree: TreeMappingResponse) =>
26
- this.fetchRecs(tree, SolvingFlow.MAGMA, () =>
27
- this.api.getMagmaRecsFx({ limit: RECOMMENDATIONS_LIMIT_PARAM }),
28
- ),
31
+ public readonly fetchMagmaRecsFx = createEffect(
32
+ async ({ tree, lockedGrades }: FetchMagmaRecsParams) => {
33
+ const recs = await this.fetchRecs(tree, SolvingFlow.MAGMA, () =>
34
+ this.api.getMagmaRecsFx({ limit: RECOMMENDATIONS_LIMIT_PARAM }),
35
+ )
36
+ return {
37
+ ...recs,
38
+ items: filterLockedGradeRecs(recs.items, tree.treeMapping, lockedGrades),
39
+ }
40
+ },
29
41
  )
30
42
 
31
- public readonly initRecommendationsFx = createEffect((tree: TreeMappingResponse) =>
32
- Promise.all([this.fetchTeacherRecsFx(tree), this.fetchMagmaRecsFx(tree)]),
43
+ public readonly initRecommendationsFx = createEffect(
44
+ ({ tree, lockedGrades }: FetchMagmaRecsParams) =>
45
+ Promise.all([
46
+ this.fetchTeacherRecsFx(tree),
47
+ this.fetchMagmaRecsFx({ tree, lockedGrades }),
48
+ ]),
33
49
  )
34
50
 
35
51
  private fetchRecs = async (