split cards
This commit is contained in:
@@ -212,6 +212,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
const [programStatus, setProgramStatus] = useState(null)
|
||||
const [studentProgram, setStudentProgram] = useState(null)
|
||||
const [activeAssetIndex, setActiveAssetIndex] = useState(0)
|
||||
const [activeSectionIndex, setActiveSectionIndex] = useState(0)
|
||||
const [assetFullscreenOpen, setAssetFullscreenOpen] = useState(false)
|
||||
const [progressPanelOpen, setProgressPanelOpen] = useState(false)
|
||||
const [settingsPanelOpen, setSettingsPanelOpen] = useState(false)
|
||||
@@ -323,6 +324,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
|
||||
useEffect(() => {
|
||||
setActiveAssetIndex(0)
|
||||
setActiveSectionIndex(0)
|
||||
}, [studentProgram?.id])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -588,6 +590,30 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
}
|
||||
}
|
||||
|
||||
function goToPreviousLessonStep() {
|
||||
if (activeSectionIndex > 0) {
|
||||
setActiveSectionIndex((index) => index - 1)
|
||||
return
|
||||
}
|
||||
if (activeAssetIndex > 0) {
|
||||
const previousAsset = lessonAssets[activeAssetIndex - 1]
|
||||
setActiveAssetIndex((index) => index - 1)
|
||||
setActiveSectionIndex(Math.max((previousAsset?.sections?.length || 1) - 1, 0))
|
||||
}
|
||||
}
|
||||
|
||||
function goToNextLessonStep() {
|
||||
const sectionCount = activeSections.length || 1
|
||||
if (activeSectionIndex < sectionCount - 1) {
|
||||
setActiveSectionIndex((index) => index + 1)
|
||||
return
|
||||
}
|
||||
if (activeAssetIndex < lessonAssets.length - 1) {
|
||||
setActiveAssetIndex((index) => index + 1)
|
||||
setActiveSectionIndex(0)
|
||||
}
|
||||
}
|
||||
|
||||
async function finishSpeechPlayback(debugMessage) {
|
||||
setSpeaking(false)
|
||||
if (audioPlaybackUrlRef.current) {
|
||||
@@ -941,6 +967,21 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
const activeLessonTitle = studentProgram?.title || lessonFocus?.label || 'Cours du jour'
|
||||
const lessonAssets = studentProgram?.assets || []
|
||||
const activeAsset = lessonAssets[activeAssetIndex] || lessonAssets[0] || null
|
||||
const activeSections = activeAsset?.sections || []
|
||||
const activeSection = activeSections[activeSectionIndex] || null
|
||||
const totalLessonSteps = lessonAssets.reduce(
|
||||
(total, asset) => total + Math.max(asset.sections?.length || 0, 1),
|
||||
0
|
||||
)
|
||||
const completedBeforeAsset = lessonAssets
|
||||
.slice(0, activeAssetIndex)
|
||||
.reduce((total, asset) => total + Math.max(asset.sections?.length || 0, 1), 0)
|
||||
const activeLessonStep = totalLessonSteps
|
||||
? completedBeforeAsset + (activeSection ? activeSectionIndex + 1 : 1)
|
||||
: 0
|
||||
const lessonStepPercent = totalLessonSteps
|
||||
? Math.min(100, Math.round((activeLessonStep / totalLessonSteps) * 100))
|
||||
: 0
|
||||
const lessonSummary = lastAssistantMessage?.content || 'Aucune ancienne séance trouvée pour le moment. Professeur TOP commencera par une reprise courte.'
|
||||
const lastStudentWork = lastUserMessage?.content || 'Aucune réponse récente enregistrée.'
|
||||
const nextLessonAdvice = studentProgram
|
||||
@@ -1033,7 +1074,7 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
<span className="stage-label">Professeur TOP</span>
|
||||
{activeAsset && (
|
||||
<span className="asset-counter">
|
||||
Fiche {activeAssetIndex + 1}/{lessonAssets.length}
|
||||
{lessonStepPercent}% · Fiche {activeAssetIndex + 1}/{lessonAssets.length}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -1045,21 +1086,21 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
{activeAsset && (
|
||||
<div className="lesson-asset-view" aria-label="Fiche de leçon active">
|
||||
<div className="lesson-asset-toolbar">
|
||||
<strong>{activeAsset.title}</strong>
|
||||
<strong>{activeSection?.title || activeAsset.title}</strong>
|
||||
<div className="lesson-asset-actions">
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button"
|
||||
onClick={() => setActiveAssetIndex((index) => Math.max(index - 1, 0))}
|
||||
disabled={activeAssetIndex === 0}
|
||||
onClick={goToPreviousLessonStep}
|
||||
disabled={activeLessonStep <= 1}
|
||||
>
|
||||
Précédente
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button"
|
||||
onClick={() => setActiveAssetIndex((index) => Math.min(index + 1, lessonAssets.length - 1))}
|
||||
disabled={activeAssetIndex >= lessonAssets.length - 1}
|
||||
onClick={goToNextLessonStep}
|
||||
disabled={activeLessonStep >= totalLessonSteps}
|
||||
>
|
||||
Suivante
|
||||
</button>
|
||||
@@ -1071,7 +1112,10 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
onClick={() => setAssetFullscreenOpen(true)}
|
||||
aria-label="Agrandir la fiche"
|
||||
>
|
||||
<img src={activeAsset.url} alt={activeAsset.title} />
|
||||
<img
|
||||
src={activeSection?.url || activeAsset.url}
|
||||
alt={activeSection?.title || activeAsset.title}
|
||||
/>
|
||||
<span>Agrandir la fiche</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -1154,28 +1198,33 @@ function TutorApp({ currentUser, onLogout }) {
|
||||
{assetFullscreenOpen && activeAsset && (
|
||||
<div className="asset-fullscreen" role="dialog" aria-label="Fiche agrandie">
|
||||
<div className="asset-fullscreen-bar">
|
||||
<strong>Fiche {activeAssetIndex + 1}/{lessonAssets.length}</strong>
|
||||
<strong>
|
||||
Étape {activeLessonStep}/{totalLessonSteps} · {activeSection?.title || activeAsset.title}
|
||||
</strong>
|
||||
<button type="button" className="secondary-button" onClick={() => setAssetFullscreenOpen(false)}>
|
||||
Fermer
|
||||
</button>
|
||||
</div>
|
||||
<div className="asset-fullscreen-stage">
|
||||
<img src={activeAsset.url} alt={activeAsset.title} />
|
||||
<img
|
||||
src={activeSection?.url || activeAsset.url}
|
||||
alt={activeSection?.title || activeAsset.title}
|
||||
/>
|
||||
</div>
|
||||
<div className="asset-fullscreen-controls">
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button"
|
||||
onClick={() => setActiveAssetIndex((index) => Math.max(index - 1, 0))}
|
||||
disabled={activeAssetIndex === 0}
|
||||
onClick={goToPreviousLessonStep}
|
||||
disabled={activeLessonStep <= 1}
|
||||
>
|
||||
Précédente
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button"
|
||||
onClick={() => setActiveAssetIndex((index) => Math.min(index + 1, lessonAssets.length - 1))}
|
||||
disabled={activeAssetIndex >= lessonAssets.length - 1}
|
||||
onClick={goToNextLessonStep}
|
||||
disabled={activeLessonStep >= totalLessonSteps}
|
||||
>
|
||||
Suivante
|
||||
</button>
|
||||
|
||||
@@ -824,7 +824,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
}
|
||||
|
||||
.lesson-asset-open img {
|
||||
max-height: 24dvh;
|
||||
max-height: 31dvh;
|
||||
}
|
||||
|
||||
.asset-fullscreen {
|
||||
@@ -832,7 +832,8 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
}
|
||||
|
||||
.asset-fullscreen-stage img {
|
||||
width: max(100%, 1120px);
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.asset-fullscreen-controls {
|
||||
|
||||
Reference in New Issue
Block a user