Bugs react
This commit is contained in:
@@ -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 d’affecter cette leçon.')
|
setErrorMessage(error.message || 'Impossible d’affecter 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'}
|
||||||
|
|||||||
Reference in New Issue
Block a user