conquiers-ta-vie-proto/js/modals.js

229 lines
16 KiB
JavaScript
Raw Normal View History

// ===================== 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</label><select id="supportClassId">${classOptions}</select></div>
<div class="fg"><label>Code élève</label><input type="text" id="supportCodeModal" placeholder="Ex. : A3K7" style="font-family:monospace;font-weight:700;letter-spacing:.1em;text-transform:uppercase;"></div>
<div id="supportModalFeedback" class="xs muted mt8"></div>
</div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Fermer</button><button class="btn btn-p" onclick="resetStudentModal()">Réinitialiser</button></div></div>`);
}
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}</strong> retirera ce module de toutes les classes auxquelles il est assigné. Cette action est irréversible.</div>
</div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-d" onclick="deleteActivity('${actId}')">Supprimer</button></div></div>`);
}
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');
S.navigate('mes-activites',{year:S.params.year},false);
}
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</div><div class="tip-body">Chaque question doit différencier ce qui est maîtrisé ou non. Évitez les pièges artificiels sans valeur pédagogique.</div></div>
<div class="tip"><div class="tip-title">🪤 Faux-vrai</div><div class="tip-body">Incluez des affirmations qui semblent vraies mais sont fausses. Elles révèlent les fausses certitudes.</div></div>
<div class="tip"><div class="tip-title">🧩 Réponses plausibles</div><div class="tip-body">Les mauvaises réponses doivent être suffisamment plausibles pour tester la connaissance.</div></div>
<div class="tip"><div class="tip-title">💬 Feedback guidant</div><div class="tip-body">Expliquez <strong>pourquoi</strong> c'est faux. « Pas tout à fait ! Voici ce qui s'est vraiment passé »</div></div>
<div class="tip tip-blue"><div class="tip-title"> Durée cible</div><div class="tip-body">10 questions 1015 minutes. Au-delà, l'attention chute.</div></div>
</div>
<div class="mfoot"><button class="btn btn-p" onclick="closeModal()">Fermer</button></div></div>`);}
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</label><input type="text" id="renameClassInput" value="${c.name}"></div>
<div class="alert alert-warn" style="margin-top:12px;"> Ce changement sera visible par tous les enseignants qui ont accès à cette classe.</div>
</div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-p" onclick="renameClass('${classId}')">Renommer</button></div></div>`);
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');
S.navigate('une-classe',{classId,tab:S.params.tab||'eleves'},false);
}
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</label><input type="text" id="newClassName" placeholder="Ex. : 5ème A"></div>
<div class="fg"><label>Année scolaire</label><select id="newClassYear"><option value="2024-2025">2024 2025</option><option value="2025-2026" selected>2025 2026</option><option value="2026-2027">2026 2027</option></select></div>
<div class="alert alert-info"> Un code de partage unique sera généré automatiquement.</div>
</div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-p" onclick="createClass()">Créer</button></div></div>`);}
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.</div>
<div class="fg"><label>Code de classe</label><input type="text" placeholder="Ex. : GC-5A-2025"></div>
</div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-p" onclick="showToast('Import simulé','ok');closeModal()">Importer</button></div></div>`);}
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.</div>
<div class="fg"><label>Code élève</label><input type="text" id="newStuCode" placeholder="Ex. : X4K2" style="font-size:16px;font-family:monospace;font-weight:700;letter-spacing:.1em;"></div>
</div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-p" onclick="addStudent('${classId}')">Ajouter</button></div></div>`);}
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};
closeModal();showToast('Élève '+code+' ajouté !','ok');S.navigate('une-classe',{classId,tab:'eleves'},false);
}
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}</div><div class="xs muted">${a.questions.length} questions</div></div>
<button class="btn btn-p btn-sm" onclick="assignActivity('${classId}','${a.id}')">Assigner</button></div>
</div>`).join('')}
</div><div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Fermer</button></div></div>`);
}
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');
S.navigate('une-classe',{classId,tab:'activite'},false);
}
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);
showToast(c.name+' assignée !','ok');S.navigate('une-activite',{activityId:actId,tab:'classes'},false);
}
function showImportActivityModal(){
showModal(`<div class="modal">
<div class="mhd"><h2>Importer un module par ID</h2><button class="btn-ico" onclick="closeModal()"></button></div>
<div class="mbody">
<div class="alert alert-info"> L'import crée une copie indépendante et modifiable dans vos modules.</div>
<div class="fg"><label>ID du module</label><input type="text" id="importActId" placeholder="Ex. : lib2" autofocus></div>
<div id="importActFeedback" class="xs muted mt8"></div>
</div>
<div class="mfoot">
<button class="btn btn-s" onclick="closeModal()">Annuler</button>
<button class="btn btn-p" onclick="doImportActivityById()">Importer</button>
</div>
</div>`);
}
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);
}
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}</strong> de <strong>${c.name}</strong> ?<br>Les résultats déjà enregistrés sont conservés.</p></div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-d" onclick="doDesassign('${classId}','${actId}')">Désassigner</button></div></div>`);
}
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);
closeModal();showToast('Désassignée.');S.navigate('une-classe',{classId,tab:'activite'},false);
}
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}</strong> de <strong>${a.name}</strong> ?<br>Les résultats sont conservés.</p></div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-d" onclick="doDesassignFromAct('${actId}','${classId}')">Désassigner</button></div></div>`);
}
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);
closeModal();showToast(c.name+' désassigné.');S.navigate('une-activite',{activityId:actId,tab:'classes'},false);
}
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}</strong> et ses <strong>${c.students.length} élèves</strong> ?<br>Action irréversible.</p></div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-d" onclick="doDeleteClass('${classId}')">Supprimer</button></div></div>`);
}
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}</strong> de <strong>${c.name}</strong> ?</p></div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-d" onclick="doDeleteStudent('${classId}','${stuId}')">Supprimer</button></div></div>`);
}
function deleteStudent(classId,stuId){confirmDeleteStudent(classId,stuId);}
function doDeleteStudent(classId,stuId){
const c=cls(classId);if(!c)return;
c.students=c.students.filter(s=>s.id!==stuId);closeModal();showToast('Élève retiré.');S.navigate('une-classe',{classId,tab:'eleves'},false);
}
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}</strong> pour <strong>${a.name}</strong> ?<br>Les élèves pourront recommencer. Action irréversible.</p></div>
<div class="mfoot"><button class="btn btn-s" onclick="closeModal()">Annuler</button><button class="btn btn-d" onclick="doResetResults('${classId}','${actId}')">Réinitialiser</button></div></div>`);
}
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();
}