Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
// ===================== MODALS =====================
function showSupportModal ( ) {
const classOptions = DB . classes . map ( c => ` <option value=" ${ c . id } "> ${ c . name } </option> ` ) . join ( '' ) ;
showModal ( ` <div class="modal"><div class="mhd"><h2>⚙️ Support</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< p class = "sm muted mb16" > Réinitialisez l 'association d' un élève à sa classe . L 'élève devra resaisir son code dans l' application pour se rattacher à nouveau . Sa progression n ' est pas effacée . < / p >
< div class = "fg" > < label > Classe < / l a b e l > < s e l e c t i d = " s u p p o r t C l a s s I d " > $ { c l a s s O p t i o n s } < / s e l e c t > < / d i v >
< div class = "fg" > < label > Code élève < / l a b e l > < i n p u t t y p e = " t e x t " i d = " s u p p o r t C o d e M o d a l " p l a c e h o l d e r = " E x . : A 3 K 7 " s t y l e = " f o n t - f a m i l y : m o n o s p a c e ; f o n t - w e i g h t : 7 0 0 ; l e t t e r - s p a c i n g : . 1 e m ; t e x t - t r a n s f o r m : u p p e r c a s e ; " > < / d i v >
< div id = "supportModalFeedback" class = "xs muted mt8" > < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Fermer < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - p " o n c l i c k = " r e s e t S t u d e n t M o d a l ( ) " > R é i n i t i a l i s e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function resetStudentModal ( ) {
const classId = document . getElementById ( 'supportClassId' ) . value ;
const code = document . getElementById ( 'supportCodeModal' ) . value . trim ( ) . toUpperCase ( ) ;
const fb = document . getElementById ( 'supportModalFeedback' ) ;
const c = cls ( classId ) ;
if ( ! c || ! code ) { showToast ( 'Renseignez la classe et le code.' ) ; return ; }
const stu = c . students . find ( s => s . code === code ) ;
if ( ! stu ) { if ( fb ) fb . textContent = ` Aucun élève avec le code " ${ code } " dans ${ c . name } . ` ; return ; }
if ( fb ) fb . textContent = '' ;
showToast ( ` Élève ${ code } réinitialisé ✓ ` , 'ok' ) ;
document . getElementById ( 'supportCodeModal' ) . value = '' ;
}
function confirmDeleteActivity ( actId ) {
const a = act ( actId ) ; if ( ! a ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Supprimer le module</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< div class = "alert alert-warn" > ⚠ ️ Supprimer < strong > $ { a . name } < / s t r o n g > r e t i r e r a c e m o d u l e d e t o u t e s l e s c l a s s e s a u x q u e l l e s i l e s t a s s i g n é . C e t t e a c t i o n e s t i r r é v e r s i b l e . < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - d " o n c l i c k = " d e l e t e A c t i v i t y ( ' $ { a c t I d } ' ) " > S u p p r i m e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function deleteActivity ( actId ) {
const a = act ( actId ) ; if ( ! a ) return ;
DB . classes . forEach ( c => { c . activities = c . activities . filter ( id => id !== actId ) ; } ) ;
DB . activities = DB . activities . filter ( a => a . id !== actId ) ;
closeModal ( ) ; showToast ( 'Module supprimé' , 'ok' ) ;
2026-05-23 16:41:53 +02:00
S . navigate ( 'mes-activites' , { year : S . params . year } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function toggleClassMenu ( classId ) {
const m = document . getElementById ( 'cmenu_' + classId ) ;
if ( ! m ) return ;
const isOpen = m . style . display !== 'none' ;
document . querySelectorAll ( '[id^="cmenu_"]' ) . forEach ( el => el . style . display = 'none' ) ;
m . style . display = isOpen ? 'none' : 'block' ;
if ( ! isOpen ) setTimeout ( ( ) => document . addEventListener ( 'click' , ( ) => m . style . display = 'none' , { once : true } ) , 0 ) ;
}
function closeClassMenu ( classId ) {
const m = document . getElementById ( 'cmenu_' + classId ) ; if ( m ) m . style . display = 'none' ;
}
function showModal ( html ) { document . getElementById ( 'modalContainer' ) . innerHTML = ` <div class="ov" onclick="if(event.target===this)closeModal()"> ${ html } </div> ` ; }
function closeModal ( ) { document . getElementById ( 'modalContainer' ) . innerHTML = '' ; }
function showTipsModal ( ) { showModal ( ` <div class="modal modal-lg"><div class="mhd"><h2>💡 Conseils de rédaction</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< div class = "tip" > < div class = "tip-title" > 🎯 Discriminer , pas piéger < / d i v > < d i v c l a s s = " t i p - b o d y " > C h a q u e q u e s t i o n d o i t d i f f é r e n c i e r c e q u i e s t m a î t r i s é o u n o n . É v i t e z l e s p i è g e s a r t i f i c i e l s s a n s v a l e u r p é d a g o g i q u e . < / d i v > < / d i v >
< div class = "tip" > < div class = "tip-title" > 🪤 Faux - vrai < / d i v > < d i v c l a s s = " t i p - b o d y " > I n c l u e z d e s a f f i r m a t i o n s q u i s e m b l e n t v r a i e s m a i s s o n t f a u s s e s . E l l e s r é v è l e n t l e s f a u s s e s c e r t i t u d e s . < / d i v > < / d i v >
< div class = "tip" > < div class = "tip-title" > 🧩 Réponses plausibles < / d i v > < d i v c l a s s = " t i p - b o d y " > L e s m a u v a i s e s r é p o n s e s d o i v e n t ê t r e s u f f i s a m m e n t p l a u s i b l e s p o u r t e s t e r l a c o n n a i s s a n c e . < / d i v > < / d i v >
< div class = "tip" > < div class = "tip-title" > 💬 Feedback guidant < / d i v > < d i v c l a s s = " t i p - b o d y " > E x p l i q u e z < s t r o n g > p o u r q u o i < / s t r o n g > c ' e s t f a u x . « P a s t o u t à f a i t ! V o i c i c e q u i s ' e s t v r a i m e n t p a s s é … » < / d i v > < / d i v >
< div class = "tip tip-blue" > < div class = "tip-title" > ⏱ Durée cible < / d i v > < d i v c l a s s = " t i p - b o d y " > 1 0 q u e s t i o n s ≈ 1 0 – 1 5 m i n u t e s . A u - d e l à , l ' a t t e n t i o n c h u t e . < / d i v > < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-p" onclick = "closeModal()" > Fermer < / b u t t o n > < / d i v > < / d i v > ` ) ; }
function showRenameClassModal ( classId ) {
const c = cls ( classId ) ; if ( ! c ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Renommer la classe</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< div class = "fg" > < label > Nom de la classe < / l a b e l > < i n p u t t y p e = " t e x t " i d = " r e n a m e C l a s s I n p u t " v a l u e = " $ { c . n a m e } " > < / d i v >
< div class = "alert alert-warn" style = "margin-top:12px;" > ⚠ ️ Ce changement sera visible par tous les enseignants qui ont accès à cette classe . < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - p " o n c l i c k = " r e n a m e C l a s s ( ' $ { c l a s s I d } ' ) " > R e n o m m e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
setTimeout ( ( ) => document . getElementById ( 'renameClassInput' ) ? . focus ( ) , 50 ) ;
}
function renameClass ( classId ) {
const c = cls ( classId ) ; const input = document . getElementById ( 'renameClassInput' ) ;
if ( ! c || ! input ) return ;
const name = input . value . trim ( ) ; if ( ! name ) { showToast ( 'Saisissez un nom.' ) ; return ; }
c . name = name ; closeModal ( ) ; showToast ( '"' + name + '" ✓' , 'ok' ) ;
2026-05-23 16:41:53 +02:00
S . navigate ( 'une-classe' , { classId , tab : S . params . tab || 'eleves' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function showNewClassModal ( ) { showModal ( ` <div class="modal"><div class="mhd"><h2>Nouvelle classe</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< div class = "fg" > < label > Nom de la classe < / l a b e l > < i n p u t t y p e = " t e x t " i d = " n e w C l a s s N a m e " p l a c e h o l d e r = " E x . : 5 è m e A " > < / d i v >
< div class = "fg" > < label > Année scolaire < / l a b e l > < s e l e c t i d = " n e w C l a s s Y e a r " > < o p t i o n v a l u e = " 2 0 2 4 - 2 0 2 5 " > 2 0 2 4 – 2 0 2 5 < / o p t i o n > < o p t i o n v a l u e = " 2 0 2 5 - 2 0 2 6 " s e l e c t e d > 2 0 2 5 – 2 0 2 6 < / o p t i o n > < o p t i o n v a l u e = " 2 0 2 6 - 2 0 2 7 " > 2 0 2 6 – 2 0 2 7 < / o p t i o n > < / s e l e c t > < / d i v >
< div class = "alert alert-info" > ℹ ️ Un code de partage unique sera généré automatiquement . < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - p " o n c l i c k = " c r e a t e C l a s s ( ) " > C r é e r < / b u t t o n > < / d i v > < / d i v > ` ) ; }
function createClass ( ) {
const name = document . getElementById ( 'newClassName' ) . value . trim ( ) ; const year = document . getElementById ( 'newClassYear' ) . value . trim ( ) ;
if ( ! name ) { showToast ( 'Donnez un nom.' ) ; return ; }
const id = 'c' + Date . now ( ) ; const code = 'GC-' + name . replace ( /\s/g , '' ) . toUpperCase ( ) . slice ( 0 , 4 ) + '-' + Math . random ( ) . toString ( 36 ) . slice ( 2 , 6 ) . toUpperCase ( ) ;
DB . classes . push ( { id , name , code , year , students : [ ] , activities : [ ] } ) ; DB . freeAccess [ id ] = new Set ( ) ;
closeModal ( ) ; showToast ( '"' + name + '" créé·e !' , 'ok' ) ; S . navigate ( 'une-classe' , { classId : id , tab : 'eleves' } ) ;
}
function showImportClassModal ( ) { showModal ( ` <div class="modal"><div class="mhd"><h2>Importer une classe</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< div class = "alert alert-info" > ℹ ️ Saisissez le code partagé par un autre enseignant . < / d i v >
< div class = "fg" > < label > Code de classe < / l a b e l > < i n p u t t y p e = " t e x t " p l a c e h o l d e r = " E x . : G C - 5 A - 2 0 2 5 " > < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - p " o n c l i c k = " s h o w T o a s t ( ' I m p o r t s i m u l é ' , ' o k ' ) ; c l o s e M o d a l ( ) " > I m p o r t e r < / b u t t o n > < / d i v > < / d i v > ` ) ; }
function showAddStudentModal ( classId ) { showModal ( ` <div class="modal"><div class="mhd"><h2>Ajouter un élève</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" >
< div class = "alert alert-info" > ℹ ️ L 'élève trouve son code dans les paramètres de l' app . < / d i v >
< div class = "fg" > < label > Code élève < / l a b e l > < i n p u t t y p e = " t e x t " i d = " n e w S t u C o d e " p l a c e h o l d e r = " E x . : X 4 K 2 " s t y l e = " f o n t - s i z e : 1 6 p x ; f o n t - f a m i l y : m o n o s p a c e ; f o n t - w e i g h t : 7 0 0 ; l e t t e r - s p a c i n g : . 1 e m ; " > < / d i v >
< / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - p " o n c l i c k = " a d d S t u d e n t ( ' $ { c l a s s I d } ' ) " > A j o u t e r < / b u t t o n > < / d i v > < / d i v > ` ) ; }
function addStudent ( classId ) {
const code = document . getElementById ( 'newStuCode' ) . value . trim ( ) . toUpperCase ( ) ;
if ( ! code ) { showToast ( 'Saisissez un code élève.' ) ; return ; }
const c = cls ( classId ) ; if ( ! c ) return ;
const id = 's' + Date . now ( ) ; c . students . push ( { id , code } ) ; DB . results [ id ] = { } ; DB . progression [ id ] = { c1 : 0 , c2 : 0 , c3 : 0 , c4 : 0 } ;
2026-05-23 16:41:53 +02:00
closeModal ( ) ; showToast ( 'Élève ' + code + ' ajouté !' , 'ok' ) ; S . navigate ( 'une-classe' , { classId , tab : 'eleves' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function showAssignActivityModal ( classId ) {
const c = cls ( classId ) ; const ua = DB . activities . filter ( a => a . status === 'published' && ! c . activities . includes ( a . id ) ) ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Assigner une activité</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" > $ { ua . length === 0 ? '<p class="muted sm">Toutes les modules publiés sont déjà assignés.</p>' : ua . map ( a => `
< div style = "border:1px solid var(--border);border-radius:8px;padding:13px;margin-bottom:10px;" >
< div class = "fbet" > < div > < div class = "semi" > $ { a . name } < / d i v > < d i v c l a s s = " x s m u t e d " > $ { a . q u e s t i o n s . l e n g t h } q u e s t i o n s < / d i v > < / d i v >
< button class = "btn btn-p btn-sm" onclick = "assignActivity('${classId}','${a.id}')" > Assigner < / b u t t o n > < / d i v >
< / d i v > ` ) . j o i n ( ' ' ) }
< / d i v > < d i v c l a s s = " m f o o t " > < b u t t o n c l a s s = " b t n b t n - s " o n c l i c k = " c l o s e M o d a l ( ) " > F e r m e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function assignActivity ( classId , actId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
if ( ! c . activities . includes ( actId ) ) c . activities . push ( actId ) ;
if ( ! a . assignedClasses . includes ( classId ) ) a . assignedClasses . push ( classId ) ;
closeModal ( ) ; showToast ( '"' + a . name + '" assigné à ' + c . name + ' !' , 'ok' ) ;
2026-05-23 16:41:53 +02:00
S . navigate ( 'une-classe' , { classId , tab : 'activite' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function assignFromAct ( actId , classId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
if ( ! c . activities . includes ( actId ) ) c . activities . push ( actId ) ;
if ( ! a . assignedClasses . includes ( classId ) ) a . assignedClasses . push ( classId ) ;
2026-05-23 16:41:53 +02:00
showToast ( c . name + ' assignée !' , 'ok' ) ; S . navigate ( 'une-activite' , { activityId : actId , tab : 'classes' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
2026-05-23 18:34:13 +02:00
function showImportActivityModal ( ) {
showModal ( ` <div class="modal">
< div class = "mhd" > < h2 > Importer un module par ID < / h 2 > < b u t t o n c l a s s = " b t n - i c o " o n c l i c k = " c l o s e M o d a l ( ) " > ✕ < / b u t t o n > < / d i v >
< div class = "mbody" >
< div class = "alert alert-info" > ℹ ️ L ' import crée une copie indépendante et modifiable dans vos modules . < / d i v >
< div class = "fg" > < label > ID du module < / l a b e l > < i n p u t t y p e = " t e x t " i d = " i m p o r t A c t I d " p l a c e h o l d e r = " E x . : l i b 2 " a u t o f o c u s > < / d i v >
< div id = "importActFeedback" class = "xs muted mt8" > < / d i v >
< / d i v >
< div class = "mfoot" >
< button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n >
< button class = "btn btn-p" onclick = "doImportActivityById()" > Importer < / b u t t o n >
< / d i v >
< / d i v > ` ) ;
}
function doImportActivityById ( ) {
const id = ( document . getElementById ( 'importActId' ) . value || '' ) . trim ( ) ;
const fb = document . getElementById ( 'importActFeedback' ) ;
if ( ! id ) { if ( fb ) fb . textContent = 'Saisissez un ID.' ; return ; }
const lib = DB . libraryActivities . find ( a => a . id === id ) ;
if ( ! lib ) { if ( fb ) fb . textContent = 'Aucun module trouvé avec cet ID.' ; return ; }
closeModal ( ) ;
importLibraryActivity ( id ) ;
}
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
function confirmDesassign ( classId , actId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Désassigner le module ?</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" > < p style = "font-size:13px;line-height:1.6;" > Désassigner < strong > $ { a . name } < / s t r o n g > d e < s t r o n g > $ { c . n a m e } < / s t r o n g > ? < b r > L e s r é s u l t a t s d é j à e n r e g i s t r é s s o n t c o n s e r v é s . < / p > < / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - d " o n c l i c k = " d o D e s a s s i g n ( ' $ { c l a s s I d } ' , ' $ { a c t I d } ' ) " > D é s a s s i g n e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function doDesassign ( classId , actId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
c . activities = c . activities . filter ( id => id !== actId ) ; a . assignedClasses = a . assignedClasses . filter ( id => id !== classId ) ;
2026-05-23 16:41:53 +02:00
closeModal ( ) ; showToast ( 'Désassignée.' ) ; S . navigate ( 'une-classe' , { classId , tab : 'activite' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function confirmDesassignFromAct ( actId , classId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Désassigner la classe ?</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" > < p style = "font-size:13px;line-height:1.6;" > Désassigner < strong > $ { c . name } < / s t r o n g > d e < s t r o n g > $ { a . n a m e } < / s t r o n g > ? < b r > L e s r é s u l t a t s s o n t c o n s e r v é s . < / p > < / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - d " o n c l i c k = " d o D e s a s s i g n F r o m A c t ( ' $ { a c t I d } ' , ' $ { c l a s s I d } ' ) " > D é s a s s i g n e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function doDesassignFromAct ( actId , classId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
c . activities = c . activities . filter ( id => id !== actId ) ; a . assignedClasses = a . assignedClasses . filter ( id => id !== classId ) ;
2026-05-23 16:41:53 +02:00
closeModal ( ) ; showToast ( c . name + ' désassigné.' ) ; S . navigate ( 'une-activite' , { activityId : actId , tab : 'classes' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function confirmDeleteClass ( classId ) {
const c = cls ( classId ) ; if ( ! c ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Supprimer la classe ?</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" > < p style = "font-size:13px;line-height:1.6;" > Supprimer < strong > $ { c . name } < / s t r o n g > e t s e s < s t r o n g > $ { c . s t u d e n t s . l e n g t h } é l è v e s < / s t r o n g > ? < b r > A c t i o n i r r é v e r s i b l e . < / p > < / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - d " o n c l i c k = " d o D e l e t e C l a s s ( ' $ { c l a s s I d } ' ) " > S u p p r i m e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function doDeleteClass ( classId ) {
DB . classes = DB . classes . filter ( c => c . id !== classId ) ; DB . activities . forEach ( a => { a . assignedClasses = a . assignedClasses . filter ( id => id !== classId ) ; } ) ;
closeModal ( ) ; showToast ( 'Classe supprimée.' ) ; S . navigate ( 'mes-classes' ) ;
}
function confirmDeleteStudent ( classId , stuId ) {
const c = cls ( classId ) ; const s = c ? . students . find ( s => s . id === stuId ) ; if ( ! c || ! s ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Supprimer l'élève ?</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" > < p style = "font-size:13px;line-height:1.6;" > Supprimer le code < strong > $ { s . code } < / s t r o n g > d e < s t r o n g > $ { c . n a m e } < / s t r o n g > ? < / p > < / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - d " o n c l i c k = " d o D e l e t e S t u d e n t ( ' $ { c l a s s I d } ' , ' $ { s t u I d } ' ) " > S u p p r i m e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function deleteStudent ( classId , stuId ) { confirmDeleteStudent ( classId , stuId ) ; }
function doDeleteStudent ( classId , stuId ) {
const c = cls ( classId ) ; if ( ! c ) return ;
2026-05-23 16:41:53 +02:00
c . students = c . students . filter ( s => s . id !== stuId ) ; closeModal ( ) ; showToast ( 'Élève retiré.' ) ; S . navigate ( 'une-classe' , { classId , tab : 'eleves' } , false ) ;
Refactor proto en architecture multi-fichiers pour le vibe coding
Split du fichier HTML monolithique (1533 lignes, 884KB) en modules séparés :
CSS découpé en 4 fichiers (variables, layout, components, features),
JS découpé en 13 fichiers (db, state, helpers, render, modals, 7 vues).
Ajout CLAUDE.md documentant l'architecture.
Correction : routes tableau-de-bord et acces-libre absentes du dispatch render().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:02 +02:00
}
function confirmResetResults ( classId , actId ) {
const c = cls ( classId ) ; const a = act ( actId ) ; if ( ! c || ! a ) return ;
showModal ( ` <div class="modal"><div class="mhd"><h2>Réinitialiser les résultats ?</h2><button class="btn-ico" onclick="closeModal()">✕</button></div>
< div class = "mbody" > < p style = "font-size:13px;line-height:1.6;" > Réinitialiser les résultats de < strong > $ { c . name } < / s t r o n g > p o u r < s t r o n g > $ { a . n a m e } < / s t r o n g > ? < b r > L e s é l è v e s p o u r r o n t r e c o m m e n c e r . A c t i o n i r r é v e r s i b l e . < / p > < / d i v >
< div class = "mfoot" > < button class = "btn btn-s" onclick = "closeModal()" > Annuler < / b u t t o n > < b u t t o n c l a s s = " b t n b t n - d " o n c l i c k = " d o R e s e t R e s u l t s ( ' $ { c l a s s I d } ' , ' $ { a c t I d } ' ) " > R é i n i t i a l i s e r < / b u t t o n > < / d i v > < / d i v > ` ) ;
}
function doResetResults ( classId , actId ) {
const c = cls ( classId ) ; if ( ! c ) return ;
c . students . forEach ( s => { if ( DB . results [ s . id ] ) delete DB . results [ s . id ] [ actId ] ; } ) ;
closeModal ( ) ; showToast ( 'Résultats réinitialisés pour ' + c . name + '.' ) ; render ( ) ;
}