From 8b024bf0f322385242452185e0ea4aaca9a8a46c Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Sat, 2 May 2026 19:59:05 +0200 Subject: [PATCH] Bug Cards --- backend/app/services.py | 2 ++ frontend/src/App.jsx | 51 ++++++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/backend/app/services.py b/backend/app/services.py index 6ade526..60e1c6e 100644 --- a/backend/app/services.py +++ b/backend/app/services.py @@ -184,6 +184,8 @@ def build_lesson_reply(db: Session, student_id: int, user_message: str, lesson_c "Si un nombre n'est pas affiché ou autorisé dans ce contexte, tu n'en parles pas. " "Ne propose jamais 'un autre nombre' si le contexte ne donne pas cet autre nombre. " "Si l'élève veut continuer mais que la card courante est terminée, mets `advance_lesson_step` à true. " + "Quand `advance_lesson_step` vaut true, ta réponse doit seulement dire: " + "`Très bien, on passe à la suite.` Ne répète pas le nombre de la card terminée. " "N'utilise pas l'historique des séances précédentes pour choisir le thème de ta réponse. " "Ta réponse visible doit être très courte: maximum 24 mots, 1 phrase d'explication " "puis éventuellement 1 question courte. Évite les phrases longues avec plusieurs propositions. " diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 7f2fd99..783c4dd 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -730,15 +730,40 @@ function TutorApp({ currentUser, onLogout }) { } function goToNextLessonStep() { + const nextStep = getNextLessonStep() + if (!nextStep) return + setActiveAssetIndex(nextStep.assetIndex) + setActiveSectionIndex(nextStep.sectionIndex) + } + + function getNextLessonStep() { const sectionCount = activeSections.length || 1 if (activeSectionIndex < sectionCount - 1) { - setActiveSectionIndex((index) => index + 1) - return + return { + assetIndex: activeAssetIndex, + sectionIndex: activeSectionIndex + 1, + asset: activeAsset, + section: activeSections[activeSectionIndex + 1], + } } if (activeAssetIndex < lessonAssets.length - 1) { - setActiveAssetIndex((index) => index + 1) - setActiveSectionIndex(0) + const nextAsset = lessonAssets[activeAssetIndex + 1] + return { + assetIndex: activeAssetIndex + 1, + sectionIndex: 0, + asset: nextAsset, + section: nextAsset?.sections?.[0] || null, + } } + return null + } + + function buildNextCardInstruction(nextStep) { + const title = nextStep?.section?.title || nextStep?.asset?.title || 'la suite' + if (title.toLowerCase().startsWith('exemple')) { + return `Très bien, on passe à ${title}. Lis seulement le nombre affiché.` + } + return `Très bien, on passe à ${title}. Regarde cette card.` } function getSectionKey(asset, section) { @@ -926,15 +951,25 @@ function TutorApp({ currentUser, onLogout }) { ...getLessonContextPayload(), }), }) - appendMessage('assistant', data.reply) - setCurrentInstruction(data.reply) if (data.advance_lesson_step) { rememberActiveCard({ score: 100, validated: true }) - goToNextLessonStep() + const nextStep = getNextLessonStep() + const transitionReply = nextStep + ? buildNextCardInstruction(nextStep) + : 'Très bien, cette fiche est terminée.' + if (nextStep) { + setActiveAssetIndex(nextStep.assetIndex) + setActiveSectionIndex(nextStep.sectionIndex) + } + appendMessage('assistant', transitionReply) + setCurrentInstruction(transitionReply) + speak(transitionReply) } else { rememberActiveCard({ score: 40, validated: false }) + appendMessage('assistant', data.reply) + setCurrentInstruction(data.reply) + speak(data.reply) } - speak(data.reply) } async function transcribeRecording(audioBlob, mimeType, { autoSend = false } = {}) {