central view

This commit is contained in:
2026-04-25 21:04:22 +02:00
parent fadd28439e
commit 96a566fa09
4 changed files with 63 additions and 23 deletions

View File

@@ -182,6 +182,7 @@ function TutorApp({ currentUser, onLogout }) {
password: '',
})
const [messages, setMessages] = useState([])
const [currentInstruction, setCurrentInstruction] = useState('')
const [input, setInput] = useState('')
const [progress, setProgress] = useState([])
const [assessment, setAssessment] = useState(null)
@@ -225,11 +226,6 @@ function TutorApp({ currentUser, onLogout }) {
[voiceProfiles, selectedVoiceProfileId]
)
const latestAssistantMessage = useMemo(
() => [...messages].reverse().find((message) => message.role === 'assistant') || null,
[messages]
)
const averageScore = useMemo(() => {
if (!progress.length) return 0
const total = progress.reduce((sum, item) => sum + item.mastery_score, 0)
@@ -263,6 +259,7 @@ function TutorApp({ currentUser, onLogout }) {
}, [speaking])
useEffect(() => {
setCurrentInstruction('')
if (selectedStudentId) {
loadProgress(selectedStudentId)
loadMessages(selectedStudentId)
@@ -370,6 +367,7 @@ function TutorApp({ currentUser, onLogout }) {
setErrorMessage('')
const data = await apiFetch(`/session/start?student_id=${selectedStudentId}`, { method: 'POST' })
appendMessage('assistant', data.reply)
setCurrentInstruction(data.reply)
speak(data.reply)
await loadProgress(selectedStudentId)
} catch (error) {
@@ -398,6 +396,7 @@ function TutorApp({ currentUser, onLogout }) {
const data = await apiFetch(`/assessment/next/${selectedStudentId}`)
setAssessment(data)
setAssessmentAnswer('')
setCurrentInstruction(data.question)
} catch (error) {
setErrorMessage(error.message || 'Impossible de charger le mini-test.')
}
@@ -419,6 +418,7 @@ function TutorApp({ currentUser, onLogout }) {
})
appendMessage('user', `Reponse au mini-test: ${assessmentAnswer}`)
appendMessage('assistant', data.feedback)
setCurrentInstruction(data.feedback)
speak(data.feedback)
setAssessment(null)
setAssessmentAnswer('')
@@ -564,6 +564,7 @@ function TutorApp({ currentUser, onLogout }) {
body: JSON.stringify({ student_id: Number(selectedStudentId), message: text }),
})
appendMessage('assistant', data.reply)
setCurrentInstruction(data.reply)
speak(data.reply)
}
@@ -890,17 +891,17 @@ function TutorApp({ currentUser, onLogout }) {
</div>
<section className="instruction-stage">
<span className="stage-label">Derniere instruction</span>
{latestAssistantMessage ? (
<p>{latestAssistantMessage.content}</p>
<span className="stage-label">Cours en cours</span>
{currentInstruction ? (
<p>{currentInstruction}</p>
) : (
<p className="muted">
Demarre la seance pour afficher ici la consigne de Professeur TOP.
Demarre la seance pour que Professeur TOP reprenne ou tu t'etais arrete et lance le cours du jour.
</p>
)}
</section>
<section className="messages">
<section className="messages" aria-label="Journal compact de la seance">
{messages.length === 0 && <p className="muted">Le dialogue apparaîtra ici.</p>}
{messages.map((message) => (
<div key={message.id} className={`message ${message.role}`}>

View File

@@ -5,7 +5,11 @@
}
* { box-sizing: border-box; }
body { margin: 0; }
html, body, #root { height: 100%; }
body {
margin: 0;
overflow: hidden;
}
button, input, select {
font: inherit;
border-radius: 12px;
@@ -27,9 +31,10 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
.layout {
display: grid;
grid-template-columns: 360px 1fr;
min-height: 100vh;
height: 100vh;
gap: 1rem;
padding: 1rem;
overflow: hidden;
}
.card {
background: white;
@@ -37,7 +42,16 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
box-shadow: 0 10px 30px rgba(20,33,61,0.08);
padding: 1rem;
}
.sidebar, .main { display: flex; flex-direction: column; gap: 1rem; }
.sidebar, .main {
display: flex;
flex-direction: column;
gap: 1rem;
min-height: 0;
overflow: hidden;
}
.sidebar {
overflow-y: auto;
}
.stack { display: flex; flex-direction: column; gap: 0.75rem; }
.small-gap { gap: 0.5rem; }
.hero { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
@@ -59,7 +73,8 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
font-size: 0.95rem;
}
.instruction-stage {
min-height: 180px;
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
justify-content: center;
@@ -71,9 +86,11 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
}
.instruction-stage p {
margin: 0;
font-size: 1.25rem;
font-size: 1.35rem;
line-height: 1.5;
white-space: pre-wrap;
max-height: 100%;
overflow: auto;
}
.stage-label {
color: #2563eb;
@@ -82,18 +99,19 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
text-transform: uppercase;
}
.messages {
flex: 1;
min-height: 220px;
flex: 0 0 150px;
min-height: 0;
overflow: auto;
background: #f8fafc;
border-radius: 20px;
padding: 1rem;
}
.message {
max-width: 80%;
margin-bottom: 0.75rem;
padding: 0.9rem 1rem;
border-radius: 18px;
max-width: 92%;
margin-bottom: 0.45rem;
padding: 0.55rem 0.75rem;
border-radius: 12px;
font-size: 0.92rem;
}
.message.user {
margin-left: auto;
@@ -102,13 +120,20 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
.message.assistant {
background: #eaf7e7;
}
.message p { margin: 0.35rem 0 0; white-space: pre-wrap; }
.message p {
margin: 0.25rem 0 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.composer {
display: grid;
grid-template-columns: 1fr auto auto;
gap: 0.75rem;
flex: 0 0 auto;
}
.assessment {
flex: 0 0 auto;
background: #fff7ed;
padding: 1rem;
border-radius: 18px;