Bugs react

This commit is contained in:
2026-05-02 20:26:03 +02:00
parent 3167f35d58
commit f91a334815

View File

@@ -232,6 +232,8 @@ function TutorApp({ currentUser, onLogout }) {
const monitorGainRef = useRef(null) const monitorGainRef = useRef(null)
const silenceStartedAtRef = useRef(null) const silenceStartedAtRef = useRef(null)
const hasSpeechInSegmentRef = useRef(false) const hasSpeechInSegmentRef = useRef(false)
const activeAssetIndexRef = useRef(0)
const activeSectionIndexRef = useRef(0)
const isRecordingRef = useRef(false) const isRecordingRef = useRef(false)
const isAutoListeningRef = useRef(false) const isAutoListeningRef = useRef(false)
const isTranscribingRef = useRef(false) const isTranscribingRef = useRef(false)
@@ -281,10 +283,31 @@ function TutorApp({ currentUser, onLogout }) {
setAudioDebug((prev) => [`${timestamp} ${message}`, ...prev].slice(0, 12)) setAudioDebug((prev) => [`${timestamp} ${message}`, ...prev].slice(0, 12))
} }
function setLessonPosition(assetIndex, sectionIndex) {
activeAssetIndexRef.current = assetIndex
activeSectionIndexRef.current = sectionIndex
setActiveAssetIndex(assetIndex)
setActiveSectionIndex(sectionIndex)
}
useEffect(() => { useEffect(() => {
isRecordingRef.current = isRecording isRecordingRef.current = isRecording
}, [isRecording]) }, [isRecording])
useEffect(() => {
activeAssetIndexRef.current = activeAssetIndex
}, [activeAssetIndex])
useEffect(() => {
activeSectionIndexRef.current = activeSectionIndex
}, [activeSectionIndex])
useEffect(() => {
setInput('')
setAssessmentAnswer('')
setLastStudentTransmission('')
}, [activeAssetIndex, activeSectionIndex])
useEffect(() => { useEffect(() => {
isAutoListeningRef.current = isAutoListening isAutoListeningRef.current = isAutoListening
}, [isAutoListening]) }, [isAutoListening])
@@ -431,6 +454,10 @@ function TutorApp({ currentUser, onLogout }) {
if (!selectedStudentId) return if (!selectedStudentId) return
try { try {
setErrorMessage('') setErrorMessage('')
setInput('')
setAssessmentAnswer('')
setLastStudentTransmission('')
setVoiceStatus('')
setSessionMessageStartIndex(messages.length) setSessionMessageStartIndex(messages.length)
setSessionCardStates({}) setSessionCardStates({})
const data = await apiFetch(`/session/start?student_id=${selectedStudentId}`, { method: 'POST' }) const data = await apiFetch(`/session/start?student_id=${selectedStudentId}`, { method: 'POST' })
@@ -533,7 +560,8 @@ function TutorApp({ currentUser, onLogout }) {
content: message.content, content: message.content,
created_at: message.created_at || null, created_at: message.created_at || null,
})) }))
if (currentInstruction) { const lastConversationItem = conversation[conversation.length - 1]
if (currentInstruction && lastConversationItem?.content !== currentInstruction) {
conversation.push({ conversation.push({
id: 'current-instruction', id: 'current-instruction',
role: 'assistant', role: 'assistant',
@@ -628,8 +656,7 @@ function TutorApp({ currentUser, onLogout }) {
section_index: data.start_section_index || 0, section_index: data.start_section_index || 0,
} }
setProgramStart(nextStart) setProgramStart(nextStart)
setActiveAssetIndex(nextStart.asset_index) setLessonPosition(nextStart.asset_index, nextStart.section_index)
setActiveSectionIndex(nextStart.section_index)
} catch (error) { } catch (error) {
setErrorMessage(error.message || 'Impossible de charger la leçon de lélève.') 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, section_index: data.start_section_index || 0,
} }
setProgramStart(nextStart) setProgramStart(nextStart)
setActiveAssetIndex(nextStart.asset_index) setLessonPosition(nextStart.asset_index, nextStart.section_index)
setActiveSectionIndex(nextStart.section_index)
} catch (error) { } catch (error) {
setErrorMessage(error.message || 'Impossible daffecter cette leçon.') setErrorMessage(error.message || 'Impossible daffecter cette leçon.')
} }
@@ -695,8 +721,7 @@ function TutorApp({ currentUser, onLogout }) {
section_index: data.start_section_index || 0, section_index: data.start_section_index || 0,
} }
setProgramStart(nextStart) setProgramStart(nextStart)
setActiveAssetIndex(nextStart.asset_index) setLessonPosition(nextStart.asset_index, nextStart.section_index)
setActiveSectionIndex(nextStart.section_index)
} catch (error) { } catch (error) {
setErrorMessage(error.message || 'Impossible de programmer la reprise.') 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() { function goToPreviousLessonStep() {
if (activeSectionIndex > 0) { const position = getLessonPosition()
setActiveSectionIndex((index) => index - 1) if (position.sectionIndex > 0) {
setLessonPosition(position.assetIndex, position.sectionIndex - 1)
return return
} }
if (activeAssetIndex > 0) { if (position.assetIndex > 0) {
const previousAsset = lessonAssets[activeAssetIndex - 1] const previousAsset = lessonAssets[position.assetIndex - 1]
setActiveAssetIndex((index) => index - 1) setLessonPosition(position.assetIndex - 1, Math.max((previousAsset?.sections?.length || 1) - 1, 0))
setActiveSectionIndex(Math.max((previousAsset?.sections?.length || 1) - 1, 0))
} }
} }
function goToNextLessonStep() { function goToNextLessonStep() {
const nextStep = getNextLessonStep() const nextStep = getNextLessonStep()
if (!nextStep) return if (!nextStep) return
setActiveAssetIndex(nextStep.assetIndex) setLessonPosition(nextStep.assetIndex, nextStep.sectionIndex)
setActiveSectionIndex(nextStep.sectionIndex)
} }
function getNextLessonStep() { function getNextLessonStep() {
const sectionCount = activeSections.length || 1 const position = getLessonPosition()
if (activeSectionIndex < sectionCount - 1) { const sectionCount = position.sections.length || 1
if (position.sectionIndex < sectionCount - 1) {
return { return {
assetIndex: activeAssetIndex, assetIndex: position.assetIndex,
sectionIndex: activeSectionIndex + 1, sectionIndex: position.sectionIndex + 1,
asset: activeAsset, asset: position.asset,
section: activeSections[activeSectionIndex + 1], section: position.sections[position.sectionIndex + 1],
} }
} }
if (activeAssetIndex < lessonAssets.length - 1) { if (position.assetIndex < lessonAssets.length - 1) {
const nextAsset = lessonAssets[activeAssetIndex + 1] const nextAsset = lessonAssets[position.assetIndex + 1]
return { return {
assetIndex: activeAssetIndex + 1, assetIndex: position.assetIndex + 1,
sectionIndex: 0, sectionIndex: 0,
asset: nextAsset, asset: nextAsset,
section: nextAsset?.sections?.[0] || null, section: nextAsset?.sections?.[0] || null,
@@ -780,13 +814,16 @@ function TutorApp({ currentUser, onLogout }) {
function answerValidatesCurrentCard(text) { function answerValidatesCurrentCard(text) {
const answer = normalizeAnswer(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 (/\b(oui|ok|d accord)\b/.test(answer) && /compr/.test(answer)) return true
if (key === 'Fiche1Card1') { if (key === 'Fiche1Card1') {
return /compr/.test(answer) || (answer.includes('345') && answer.includes('208')) return /compr/.test(answer) || (answer.includes('345') && answer.includes('208'))
} }
if (key === 'Fiche1Card2') { 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') { if (key === 'Fiche1Card3') {
return answer.includes('milliers') && (answer.includes('unites') || answer.includes('simples')) return answer.includes('milliers') && (answer.includes('unites') || answer.includes('simples'))
@@ -808,13 +845,14 @@ function TutorApp({ currentUser, onLogout }) {
} }
function getActiveCardState(score = 0, validated = false) { function getActiveCardState(score = 0, validated = false) {
if (!studentProgram || !activeAsset) return null const { asset, section } = getLessonPosition()
const sectionTitle = activeSection?.title || activeAsset.title if (!studentProgram || !asset) return null
const sectionKey = getSectionKey(activeAsset, activeSection) const sectionTitle = section?.title || asset.title
const sectionKey = getSectionKey(asset, section)
return { return {
lesson_id: studentProgram.id, lesson_id: studentProgram.id,
asset_path: activeAsset.path, asset_path: asset.path,
asset_title: activeAsset.title, asset_title: asset.title,
section_key: sectionKey, section_key: sectionKey,
section_title: sectionTitle, section_title: sectionTitle,
comprehension_score: score, comprehension_score: score,
@@ -861,12 +899,13 @@ function TutorApp({ currentUser, onLogout }) {
} }
function getLessonContextPayload() { function getLessonContextPayload() {
const { asset, section } = getLessonPosition()
return { return {
lesson_title: activeLessonTitle, lesson_title: activeLessonTitle,
asset_title: activeAsset?.title || null, asset_title: asset?.title || null,
section_title: activeSection?.title || activeAsset?.title || null, section_title: section?.title || asset?.title || null,
section_context_key: activeSection?.context_key || null, section_context_key: section?.context_key || null,
section_context: activeSection?.context || null, section_context: section?.context || null,
step_percent: lessonStepPercent, step_percent: lessonStepPercent,
} }
} }
@@ -996,8 +1035,7 @@ function TutorApp({ currentUser, onLogout }) {
? buildNextCardInstruction(nextStep) ? buildNextCardInstruction(nextStep)
: 'Très bien, cette fiche est terminée.' : 'Très bien, cette fiche est terminée.'
if (nextStep) { if (nextStep) {
setActiveAssetIndex(nextStep.assetIndex) setLessonPosition(nextStep.assetIndex, nextStep.sectionIndex)
setActiveSectionIndex(nextStep.sectionIndex)
} }
appendMessage('assistant', transitionReply) appendMessage('assistant', transitionReply)
setCurrentInstruction(transitionReply) setCurrentInstruction(transitionReply)
@@ -1415,8 +1453,9 @@ function TutorApp({ currentUser, onLogout }) {
placeholder={ placeholder={
assessment assessment
? 'Ta réponse au mini-test...' ? 'Ta réponse au mini-test...'
: lastStudentTransmission || 'Dicte ou écris ta réponse...' : 'Dicte ou écris ta réponse...'
} }
autoComplete="off"
/> />
<button type="button" onClick={startVoiceInput} disabled={isTranscribing}> <button type="button" onClick={startVoiceInput} disabled={isTranscribing}>
{isAutoListening ? 'Stop micro' : isTranscribing ? 'Transcription...' : 'Dicter'} {isAutoListening ? 'Stop micro' : isTranscribing ? 'Transcription...' : 'Dicter'}