From f91a33481526664c8ae8b5a9c70f87acf3b8d8da Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Sat, 2 May 2026 20:26:03 +0200 Subject: [PATCH] Bugs react --- frontend/src/App.jsx | 115 +++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 38 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 380b955..fe2a962 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -232,6 +232,8 @@ function TutorApp({ currentUser, onLogout }) { const monitorGainRef = useRef(null) const silenceStartedAtRef = useRef(null) const hasSpeechInSegmentRef = useRef(false) + const activeAssetIndexRef = useRef(0) + const activeSectionIndexRef = useRef(0) const isRecordingRef = useRef(false) const isAutoListeningRef = useRef(false) const isTranscribingRef = useRef(false) @@ -281,10 +283,31 @@ function TutorApp({ currentUser, onLogout }) { setAudioDebug((prev) => [`${timestamp} ${message}`, ...prev].slice(0, 12)) } + function setLessonPosition(assetIndex, sectionIndex) { + activeAssetIndexRef.current = assetIndex + activeSectionIndexRef.current = sectionIndex + setActiveAssetIndex(assetIndex) + setActiveSectionIndex(sectionIndex) + } + useEffect(() => { isRecordingRef.current = isRecording }, [isRecording]) + useEffect(() => { + activeAssetIndexRef.current = activeAssetIndex + }, [activeAssetIndex]) + + useEffect(() => { + activeSectionIndexRef.current = activeSectionIndex + }, [activeSectionIndex]) + + useEffect(() => { + setInput('') + setAssessmentAnswer('') + setLastStudentTransmission('') + }, [activeAssetIndex, activeSectionIndex]) + useEffect(() => { isAutoListeningRef.current = isAutoListening }, [isAutoListening]) @@ -431,6 +454,10 @@ function TutorApp({ currentUser, onLogout }) { if (!selectedStudentId) return try { setErrorMessage('') + setInput('') + setAssessmentAnswer('') + setLastStudentTransmission('') + setVoiceStatus('') setSessionMessageStartIndex(messages.length) setSessionCardStates({}) const data = await apiFetch(`/session/start?student_id=${selectedStudentId}`, { method: 'POST' }) @@ -533,7 +560,8 @@ function TutorApp({ currentUser, onLogout }) { content: message.content, created_at: message.created_at || null, })) - if (currentInstruction) { + const lastConversationItem = conversation[conversation.length - 1] + if (currentInstruction && lastConversationItem?.content !== currentInstruction) { conversation.push({ id: 'current-instruction', role: 'assistant', @@ -628,8 +656,7 @@ function TutorApp({ currentUser, onLogout }) { section_index: data.start_section_index || 0, } setProgramStart(nextStart) - setActiveAssetIndex(nextStart.asset_index) - setActiveSectionIndex(nextStart.section_index) + setLessonPosition(nextStart.asset_index, nextStart.section_index) } catch (error) { setErrorMessage(error.message || 'Impossible de charger la leçon de l’élève.') } @@ -671,8 +698,7 @@ function TutorApp({ currentUser, onLogout }) { section_index: data.start_section_index || 0, } setProgramStart(nextStart) - setActiveAssetIndex(nextStart.asset_index) - setActiveSectionIndex(nextStart.section_index) + setLessonPosition(nextStart.asset_index, nextStart.section_index) } catch (error) { setErrorMessage(error.message || 'Impossible d’affecter cette leçon.') } @@ -695,8 +721,7 @@ function TutorApp({ currentUser, onLogout }) { section_index: data.start_section_index || 0, } setProgramStart(nextStart) - setActiveAssetIndex(nextStart.asset_index) - setActiveSectionIndex(nextStart.section_index) + setLessonPosition(nextStart.asset_index, nextStart.section_index) } catch (error) { setErrorMessage(error.message || 'Impossible de programmer la reprise.') } @@ -721,39 +746,48 @@ function TutorApp({ currentUser, onLogout }) { } } + function getLessonPosition() { + const assetIndex = activeAssetIndexRef.current + const sectionIndex = activeSectionIndexRef.current + const asset = lessonAssets[assetIndex] || lessonAssets[0] || null + const sections = asset?.sections || [] + const section = sections[sectionIndex] || null + return { assetIndex, sectionIndex, asset, sections, section } + } + function goToPreviousLessonStep() { - if (activeSectionIndex > 0) { - setActiveSectionIndex((index) => index - 1) + const position = getLessonPosition() + if (position.sectionIndex > 0) { + setLessonPosition(position.assetIndex, position.sectionIndex - 1) return } - if (activeAssetIndex > 0) { - const previousAsset = lessonAssets[activeAssetIndex - 1] - setActiveAssetIndex((index) => index - 1) - setActiveSectionIndex(Math.max((previousAsset?.sections?.length || 1) - 1, 0)) + if (position.assetIndex > 0) { + const previousAsset = lessonAssets[position.assetIndex - 1] + setLessonPosition(position.assetIndex - 1, Math.max((previousAsset?.sections?.length || 1) - 1, 0)) } } function goToNextLessonStep() { const nextStep = getNextLessonStep() if (!nextStep) return - setActiveAssetIndex(nextStep.assetIndex) - setActiveSectionIndex(nextStep.sectionIndex) + setLessonPosition(nextStep.assetIndex, nextStep.sectionIndex) } function getNextLessonStep() { - const sectionCount = activeSections.length || 1 - if (activeSectionIndex < sectionCount - 1) { + const position = getLessonPosition() + const sectionCount = position.sections.length || 1 + if (position.sectionIndex < sectionCount - 1) { return { - assetIndex: activeAssetIndex, - sectionIndex: activeSectionIndex + 1, - asset: activeAsset, - section: activeSections[activeSectionIndex + 1], + assetIndex: position.assetIndex, + sectionIndex: position.sectionIndex + 1, + asset: position.asset, + section: position.sections[position.sectionIndex + 1], } } - if (activeAssetIndex < lessonAssets.length - 1) { - const nextAsset = lessonAssets[activeAssetIndex + 1] + if (position.assetIndex < lessonAssets.length - 1) { + const nextAsset = lessonAssets[position.assetIndex + 1] return { - assetIndex: activeAssetIndex + 1, + assetIndex: position.assetIndex + 1, sectionIndex: 0, asset: nextAsset, section: nextAsset?.sections?.[0] || null, @@ -780,13 +814,16 @@ function TutorApp({ currentUser, onLogout }) { function answerValidatesCurrentCard(text) { const answer = normalizeAnswer(text) - const key = activeSection?.context_key || '' + const { section } = getLessonPosition() + const key = section?.context_key || '' if (/\b(oui|ok|d accord)\b/.test(answer) && /compr/.test(answer)) return true if (key === 'Fiche1Card1') { return /compr/.test(answer) || (answer.includes('345') && answer.includes('208')) } if (key === 'Fiche1Card2') { - return answer.includes('trois') && answer.includes('quarante') && answer.includes('mille') && answer.includes('huit') + const digitRead = answer.replace(/\D/g, '') === '345208' + const wordRead = answer.includes('trois') && answer.includes('quarante') && answer.includes('mille') && answer.includes('huit') + return digitRead || wordRead } if (key === 'Fiche1Card3') { return answer.includes('milliers') && (answer.includes('unites') || answer.includes('simples')) @@ -808,13 +845,14 @@ function TutorApp({ currentUser, onLogout }) { } function getActiveCardState(score = 0, validated = false) { - if (!studentProgram || !activeAsset) return null - const sectionTitle = activeSection?.title || activeAsset.title - const sectionKey = getSectionKey(activeAsset, activeSection) + const { asset, section } = getLessonPosition() + if (!studentProgram || !asset) return null + const sectionTitle = section?.title || asset.title + const sectionKey = getSectionKey(asset, section) return { lesson_id: studentProgram.id, - asset_path: activeAsset.path, - asset_title: activeAsset.title, + asset_path: asset.path, + asset_title: asset.title, section_key: sectionKey, section_title: sectionTitle, comprehension_score: score, @@ -861,12 +899,13 @@ function TutorApp({ currentUser, onLogout }) { } function getLessonContextPayload() { + const { asset, section } = getLessonPosition() return { lesson_title: activeLessonTitle, - asset_title: activeAsset?.title || null, - section_title: activeSection?.title || activeAsset?.title || null, - section_context_key: activeSection?.context_key || null, - section_context: activeSection?.context || null, + asset_title: asset?.title || null, + section_title: section?.title || asset?.title || null, + section_context_key: section?.context_key || null, + section_context: section?.context || null, step_percent: lessonStepPercent, } } @@ -996,8 +1035,7 @@ function TutorApp({ currentUser, onLogout }) { ? buildNextCardInstruction(nextStep) : 'Très bien, cette fiche est terminée.' if (nextStep) { - setActiveAssetIndex(nextStep.assetIndex) - setActiveSectionIndex(nextStep.sectionIndex) + setLessonPosition(nextStep.assetIndex, nextStep.sectionIndex) } appendMessage('assistant', transitionReply) setCurrentInstruction(transitionReply) @@ -1415,8 +1453,9 @@ function TutorApp({ currentUser, onLogout }) { placeholder={ assessment ? 'Ta réponse au mini-test...' - : lastStudentTransmission || 'Dicte ou écris ta réponse...' + : 'Dicte ou écris ta réponse...' } + autoComplete="off" />