Pooja English Spoken

Attendance Report

Date: '+escHtml(teacherAttendanceCache.date)+'

Total: '+rows.length+' · Present: '+rows.filter(r=>r.status==='Present').length+' · Absent: '+rows.filter(r=>r.status==='Absent').length+' · Not marked: '+rows.filter(r=>r.status==='Not marked').length+'

'+bodyRows+'
Student IDNameBatchStatusCheck-in

Generated from Pooja AI English Coach attendance records.

'; w.document.open();w.document.write(html);w.document.close(); w.addEventListener('load',()=>setTimeout(()=>w.print(),250),{once:true}); } function exportTeacherAttendanceCsv(){ const rows=teacherAttendanceCache.rows||[]; if(!rows.length){alert('No attendance data to export.');return;} const head=['Date','Student ID','Student Name','Batch','Status','Check-in Time']; const lines=[head,...rows.map(r=>[teacherAttendanceCache.date,r.student_id,r.name,r.batch,r.status,r.check_in_at])].map(row=>row.map(v=>'"'+String(v??'').replace(/"/g,'""')+'"').join(',')); const blob=new Blob(['\ufeff'+lines.join('\r\n')],{type:'text/csv;charset=utf-8;'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download='attendance-'+teacherAttendanceCache.date+'.csv';document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),1000); } function showTeacherSection(section){ const overview=$('teacherOverviewView'), attendance=$('teacherAttendanceView'), students=$('teacherStudentsView'), ai=$('teacherAiLearnersView'), daily=$('teacherDailyLearningView'), enquiries=$('teacherEnquiriesView'), feedback=$('teacherFeedbackView'), homework=$('teacherHomeworkView'), certificates=$('teacherCertificatesView'), files=$('teacherFilesView'), growth=$('teacherGrowthView'), stats=$('teacherOverviewStats'); if(!overview||!attendance||!students||!ai||!daily||!enquiries||!feedback||!homework||!certificates||!files||!growth)return; const isAttendance=section==='attendance', isStudents=section==='students', isAi=section==='ai_learners', isDaily=section==='daily_learning', isEnquiries=section==='enquiries', isFeedback=section==='feedback', isHomework=section==='homework', isCertificates=section==='certificates', isFiles=section==='files', isGrowth=section==='growth'; overview.classList.toggle('hidden',isAttendance||isStudents||isAi||isDaily||isEnquiries||isFeedback||isHomework||isCertificates||isFiles||isGrowth); attendance.classList.toggle('hidden',!isAttendance); students.classList.toggle('hidden',!isStudents); ai.classList.toggle('hidden',!isAi); daily.classList.toggle('hidden',!isDaily); enquiries.classList.toggle('hidden',!isEnquiries); feedback.classList.toggle('hidden',!isFeedback); homework.classList.toggle('hidden',!isHomework); certificates.classList.toggle('hidden',!isCertificates); files.classList.toggle('hidden',!isFiles); growth.classList.toggle('hidden',!isGrowth); stats?.classList.toggle('hidden',isAttendance||isStudents||isAi||isDaily||isEnquiries||isFeedback||isHomework||isCertificates||isFiles||isGrowth); $('teacherOverviewBtn')?.classList.toggle('active',!isAttendance&&!isStudents&&!isAi&&!isDaily&&!isEnquiries&&!isFeedback&&!isHomework&&!isCertificates&&!isFiles); $('teacherAttendanceBtn')?.classList.toggle('active',isAttendance); $('teacherStudentsBtn')?.classList.toggle('active',isStudents); $('teacherAiLearnersBtn')?.classList.toggle('active',isAi); $('teacherDailyBtn')?.classList.toggle('active',isDaily); $('teacherEnquiriesBtn')?.classList.toggle('active',isEnquiries); $('teacherFeedbackBtn')?.classList.toggle('active',isFeedback); $('teacherHomeworkBtn')?.classList.toggle('active',isHomework); $('teacherCertificatesBtn')?.classList.toggle('active',isCertificates); $('teacherFilesBtn')?.classList.toggle('active',isFiles); $('teacherGrowthBtn')?.classList.toggle('active',isGrowth); if(isGrowth)loadTeacherGrowthHistory(); if(isAttendance)loadTeacherAttendance(); if(isStudents)renderStudentTable(trainerDataCache?.users||[]); if(isAi)renderAiLearners(trainerDataCache?.ai_learners||[],trainerDataCache?.class_enquiries||[]); if(isDaily){const today=new Intl.DateTimeFormat('en-CA',{timeZone:'Asia/Kolkata'}).format(new Date());if($('dailyLearningDate')){$('dailyLearningDate').max=today;if(!$('dailyLearningDate').value)$('dailyLearningDate').value=today;}window.dailyLearningDateData=null;loadDailyLearningForDate();} if(isEnquiries)renderClassEnquiries(trainerDataCache?.class_enquiries||[]); if(isFeedback)renderStudentFeedback(trainerDataCache?.student_feedback||[],trainerDataCache?.users||[]); if(isHomework)renderDailyAiHomework(trainerDataCache?.users||[]); if(isCertificates)loadTeacherCertificates(); if(isFiles)loadTeacherFiles(); window.scrollTo({top:0,behavior:'smooth'}); } /* ================= TEACHER GROWTH HUB FRONTEND ================= */ let teacherGrowthCurrent=null; function growthEsc(v){return String(v==null?'':v).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));} function growthNotice(message,isError){const el=$('growthStatus');if(!el)return;el.textContent=message;el.classList.remove('hidden');el.style.color=isError?'#b42318':'#176b43';} async function generateTeacherGrowthLesson(){ const btn=$('growthGenerateBtn');if(btn){btn.disabled=true;btn.textContent='⏳ Preparing your power pack…';} growthNotice('AI is preparing the lesson. Please wait…',false); try{ const d=await api('teacher_growth_generate',{category:$('growthCategory')?.value||'Technology & AI'}); if(!d.ok){growthNotice(d.error||'Could not generate the lesson.',true);return;} teacherGrowthCurrent=d.item;renderTeacherGrowthLesson(d.item);growthNotice('Lesson generated and saved successfully.',false);await loadTeacherGrowthHistory(); }catch(e){growthNotice('Network error. Please try again.',true);} finally{if(btn){btn.disabled=false;btn.textContent="✨ Show Today's Power Pack";}} } function selectGrowthCategory(btn){document.querySelectorAll('.growth-category').forEach(b=>b.classList.toggle('active',b===btn));const el=$('growthCategory');if(el)el.value=btn.dataset.category||'Technology & AI';} function renderTeacherGrowthLesson(x){ const host=$('growthCurrentLesson');if(!host||!x)return; const points=Array.isArray(x.key_points)?x.key_points:[],vocab=Array.isArray(x.vocabulary)?x.vocabulary:[],quiz=Array.isArray(x.quiz)?x.quiz:[],sentences=Array.isArray(x.daily_sentences)?x.daily_sentences:[],news=Array.isArray(x.news_items)?x.news_items:[]; let h='
'+growthEsc(x.category||'Daily Power Pack')+''+growthEsc(x.date||'')+'

'+growthEsc(x.title||'Your Daily English Power Pack')+'

'+growthEsc(x.overview||'Small daily practice. Stronger English. Smarter conversations.')+'

⚡ LET’S GO!
'; if(x.hindi_explanation)h+='
🇮🇳 Quick samajh

'+growthEsc(x.hindi_explanation)+'

'+(x.english_explanation?'

'+growthEsc(x.english_explanation)+'

':'')+'
'; if(sentences.length){h+='
💬

50 Daily-Use English Sentences

Read aloud · Learn the natural way to say it

';sentences.forEach((q,i)=>{h+='
'+(i+1)+'
'+growthEsc(q.hindi||'')+'
'+growthEsc(q.english||'')+'
';});h+='
';} if(news.length){h+='
📰

News in a Nutshell

Short, interesting reads — no long articles

';news.forEach((n,i)=>{h+='
STORY '+(i+1)+''+growthEsc(n.published_date||x.date||'')+'

'+growthEsc(n.headline||'Interesting update')+'

'+growthEsc(n.summary||'')+'

✨ '+growthEsc(n.why_interesting||'Why it matters: explore and discuss this topic.')+'
';if(Array.isArray(n.vocabulary)&&n.vocabulary.length)h+='
'+n.vocabulary.map(v=>''+growthEsc(v.word||'')+' · '+growthEsc(v.meaning_hi||'')+'').join('')+'
';if(n.source_url&&/^https?:\/\//i.test(n.source_url))h+='Read source ↗';else h+=''+growthEsc(n.source_name||'Background topic')+' · Please verify latest details';h+='
';});h+='
';} if(vocab.length){h+='
🧠

Vocabulary Booster

Words you can actually use in conversations

'+vocab.map(v=>'
'+growthEsc(v.word||'Word')+'
'+growthEsc(v.meaning_hi||'')+'
'+growthEsc(v.example||'')+'
').join('')+'
';} if(x.fun_fact)h+='
🤯
Did you know?

'+growthEsc(x.fun_fact)+'

'; if(x.guess_the_word&&x.guess_the_word.clue)h+='
🎮 Guess the Word — play a 10-second challenge

'+growthEsc(x.guess_the_word.clue)+'

'; if(x.discussion_question)h+='
💬 One interesting question

'+growthEsc(x.discussion_question)+'

'; if(quiz.length){h+='
🏆

Quick Challenge

Three questions. Test your new knowledge.

';quiz.forEach((q,i)=>{h+='
'+(i+1)+'. '+growthEsc(q.question||'')+'';(q.options||[]).forEach((op,j)=>{h+='';});h+='
';});h+='
';} h+='
💾 Save today’s progress (optional)

'+growthEsc(x.source_note||'For breaking news, open the publisher source and verify details.')+'

'; host.innerHTML=h; } function copyGrowthSentences(){const x=teacherGrowthCurrent;if(!x)return;const txt=(x.daily_sentences||[]).map((q,i)=>(i+1)+'. '+(q.hindi||'')+' — '+(q.english||'')).join('\n');if(navigator.clipboard?.writeText)navigator.clipboard.writeText(txt).then(()=>growthNotice('50 sentences copied.',false)).catch(()=>growthNotice('Copy is unavailable in this browser.',true));else growthNotice('Copy is unavailable in this browser.',true);} function speakGrowthText(text){if(!('speechSynthesis' in window)){growthNotice('Audio playback is not supported in this browser.',true);return;}window.speechSynthesis.cancel();const u=new SpeechSynthesisUtterance(String(text||''));u.lang='en-IN';u.rate=.9;window.speechSynthesis.speak(u);} function checkTeacherGrowthQuiz(){ const x=teacherGrowthCurrent;if(!x)return;let score=0,total=0; (x.quiz||[]).forEach((q,i)=>{const chosen=document.querySelector('input[name="growthq'+i+'"]:checked'),fb=$('growthQuizFeedback'+i);total++;const correct=Number(q.answer);if(chosen&&Number(chosen.value)===correct)score++;if(fb){fb.textContent=(chosen&&Number(chosen.value)===correct?'Correct. ':'Correct answer: '+String((q.options||[])[correct]||'')+'. ')+(q.explanation||'');fb.style.color=chosen&&Number(chosen.value)===correct?'#176b43':'#b45309';}}); growthNotice('Quiz result: '+score+' / '+total+'. Review the explanations and try again if needed.',false); } async function saveTeacherGrowthProgress(id,status){ const notes=$('growthTeacherNotes')?.value||'';const d=await api('teacher_growth_save',{id:String(id),status:status,notes:notes}); if(!d.ok){growthNotice(d.error||'Could not save progress.',true);return;} if(teacherGrowthCurrent&&Number(teacherGrowthCurrent.id)===Number(id)){teacherGrowthCurrent.status=status;teacherGrowthCurrent.teacher_notes=notes;if(status==='Completed')teacherGrowthCurrent.completed_at=new Date().toISOString();} growthNotice(status==='Completed'?'Great work — this lesson is marked completed.':'Your notes have been saved.',false);await loadTeacherGrowthHistory(); } function copyTeacherGrowthLesson(){ const x=teacherGrowthCurrent;if(!x)return; const txt=[x.title,x.category,x.overview,'50 DAILY SENTENCES:',...(x.daily_sentences||[]).map((q,i)=>(i+1)+'. '+(q.hindi||'')+' — '+(q.english||'')),'NEWS:',...(x.news_items||[]).map(n=>(n.headline||'')+'\n'+(n.summary||'')+'\n'+(n.source_url||'')),'Vocabulary:',...(x.vocabulary||[]).map(v=>(v.word||'')+' — '+(v.meaning_hi||'')+' — '+(v.example||'')),'Fun fact: '+(x.fun_fact||''),'Discussion: '+(x.discussion_question||'')].filter(Boolean).join('\n'); if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(txt).then(()=>growthNotice('Lesson copied.',false)).catch(()=>growthNotice('Copy is unavailable in this browser.',true));else growthNotice('Copy is unavailable in this browser.',true); } async function loadTeacherGrowthHistory(){ const host=$('growthHistory');if(!host)return; const d=await api('teacher_growth_history');if(!d.ok){host.innerHTML='
Could not load history. Please refresh.
';return;} const items=Array.isArray(d.items)?d.items:[]; $('growthTotal').textContent=items.length;$('growthCompleted').textContent=items.filter(x=>x.status==='Completed').length; const day=new Date().toLocaleDateString('en-IN',{weekday:'long',day:'numeric',month:'short',timeZone:'Asia/Kolkata'});$('growthTodayLabel').textContent=day; if(!items.length){host.innerHTML='
No lessons yet. Choose a topic above and generate your first lesson.
';return;} host.innerHTML=items.map(x=>'
'+growthEsc(x.title||x.category)+'
'+growthEsc(x.date||'')+' · '+growthEsc(x.category||'')+'
'+growthEsc(x.status||'In Progress')+'
').join(''); const latest=items[0];if(!teacherGrowthCurrent&&latest){teacherGrowthCurrent=latest;renderTeacherGrowthLesson(latest);} } function openTeacherGrowthItem(id){ api('teacher_growth_history').then(d=>{if(!d.ok)return;const x=(d.items||[]).find(v=>Number(v.id)===Number(id));if(x){teacherGrowthCurrent=x;renderTeacherGrowthLesson(x);$('growthCurrentLesson')?.scrollIntoView({behavior:'smooth',block:'start'});}}); } function formatTeacherFileSize(bytes){const n=Number(bytes||0);if(n<1024)return n+' B';if(n<1048576)return (n/1024).toFixed(1)+' KB';return (n/1048576).toFixed(1)+' MB';} function fileIcon(ext){ext=(ext||'').toLowerCase();if(ext==='pdf')return '📕';if(['doc','docx'].includes(ext))return '📘';if(['ppt','pptx'].includes(ext))return '📙';if(['xls','xlsx'].includes(ext))return '📗';if(['jpg','jpeg','png','webp'].includes(ext))return '🖼️';return '📄';} async function loadTeacherFiles(){ const el=$('teacherFilesList');if(!el)return;el.innerHTML='
Loading files...
'; const d=await api('teacher_files'); if(!d.ok){el.innerHTML='
'+esc(d.error||'Could not load files.')+'
';return;} const files=d.files||[]; if(!files.length){el.innerHTML='
📁No files uploaded yetUpload your first teaching resource above.
';return;} el.innerHTML=files.map(f=>'
'+fileIcon(f.extension)+' '+esc(f.original_name||'File')+'
'+esc((f.extension||'').toUpperCase())+' · '+formatTeacherFileSize(f.size)+' · '+esc(f.uploaded_at||'')+'
⬇️ Download
').join(''); } async function uploadTeacherFile(e){ e.preventDefault();const input=$('teacherFileInput'),status=$('teacherFileUploadStatus'),btn=e.submitter; if(!input?.files?.length)return; const fd=new FormData();fd.append('file',input.files[0]); if(btn)btn.disabled=true;status.className='result';status.textContent='Uploading...'; const d=await api('upload_teacher_file',fd); if(d.ok){status.className='result ok';status.textContent='File uploaded successfully.';input.value='';loadTeacherFiles();} else{status.className='result';status.textContent=d.error||'Upload failed.';} if(btn)btn.disabled=false; } function viewTeacherFile(id,ext,name){ ext=String(ext||'').toLowerCase(); const isImage=['jpg','jpeg','png','webp'].includes(ext); const isPdf=ext==='pdf'; const isTxt=ext==='txt'; const canPreview=isImage||isPdf||isTxt; const overlay=document.createElement('div'); overlay.id='teacherFileViewer'; overlay.style.cssText='position:fixed;inset:0;background:rgba(15,23,42,.72);z-index:99999;display:flex;align-items:center;justify-content:center;padding:10px;box-sizing:border-box;'; const safeName=esc(name||'File'); const src='?action=view_teacher_file&id='+encodeURIComponent(id); let content=''; if(isImage){ content='
'+ ''+safeName+'
'; }else if(isPdf||isTxt){ content='
'; }else{ content='
'+fileIcon(ext)+'

Preview is not available for this file type

Word, PowerPoint and Excel files are stored safely on the server. Use Download to open the original file.

⬇️ Download File
'; } overlay.innerHTML='
'+ '
👁️ '+safeName+'
⬇️ Download
'+content+'
'; document.body.appendChild(overlay); const close=()=>overlay.remove(); $('closeTeacherFileViewer')?.addEventListener('click',close); overlay.addEventListener('click',e=>{if(e.target===overlay)close();}); document.addEventListener('keydown',function handler(e){if(e.key==='Escape'){close();document.removeEventListener('keydown',handler);}}); } async function deleteTeacherFile(id){ if(!confirm('Delete this uploaded file permanently from the server? This will remove the file and its portal record.'))return; const d=await api('delete_teacher_file',{id:id}); if(!d.ok){alert(d.error||'Could not delete file.');return;} loadTeacherFiles(); } async function trainerLogout(){ const ok=confirm('Logout from Teacher Dashboard?'); if(!ok)return; document.body.classList.remove('teacher-only-mode'); $('trainer')?.classList.remove('teacher-only-panel'); $('app')?.querySelectorAll(':scope > *').forEach(function(el){el.style.display='';el.classList.remove('hidden');}); await api('trainer_logout'); location.reload(); } function trainerLogin(){ api('trainer_login',{pin:$('trainerPin').value}).then(async d=>{ if(!d.ok){ $('trainerError').className='result'; $('trainerError').textContent=d.error||'Incorrect trainer PIN.'; return; } location.href=location.pathname+'?teacher=1'; }); } let trainerDataCache=null; function openAddStudent(){ const modal=$('addStudentModal'); if(!modal)return; const formIds=['newStudentName','newStudentCourse','newStudentPhone','newStudentWhatsapp','newStudentEmail','newStudentBatch','newStudentGoal','newStudentTotalFee','newStudentPaidFee','newStudentBalanceFee','newStudentAddress']; formIds.forEach(id=>{if($(id))$(id).value='';}); if($('newStudentJoining'))$('newStudentJoining').value=''; if($('newStudentDueDate'))$('newStudentDueDate').value=''; if($('newStudentPhoto'))$('newStudentPhoto').value=''; if($('newStudentLevel'))$('newStudentLevel').value='Beginner'; if($('newStudentResult')){$('newStudentResult').textContent='';$('newStudentResult').classList.add('hidden');} modal.classList.remove('hidden'); setTimeout(()=>$('newStudentName')?.focus(),50); } function closeAddStudent(){$('addStudentModal')?.classList.add('hidden');} async function createStudent(){ const name=($('newStudentName')?.value||'').trim();if(!name){alert('Student name is required.');return;} const fd=new FormData(); fd.append('name',name);fd.append('level',$('newStudentLevel').value);fd.append('course',$('newStudentCourse').value.trim());fd.append('phone',$('newStudentPhone').value.trim());fd.append('whatsapp',$('newStudentWhatsapp').value.trim());fd.append('email',$('newStudentEmail').value.trim());fd.append('batch',$('newStudentBatch').value.trim());fd.append('joining_date',$('newStudentJoining').value);fd.append('goal',$('newStudentGoal').value.trim());fd.append('total_fee',$('newStudentTotalFee').value.trim());fd.append('paid_fee',$('newStudentPaidFee').value.trim());fd.append('balance_fee',$('newStudentBalanceFee').value.trim());fd.append('fee_due_date',$('newStudentDueDate').value);fd.append('address',$('newStudentAddress').value.trim()); if($('newStudentPhoto')?.files?.[0])fd.append('profile_photo',$('newStudentPhoto').files[0]); const d=await api('create_student',fd);const box=$('newStudentResult');if(!d.ok){box.textContent=d.error||'Could not create student.';box.classList.remove('hidden');return;} box.innerHTML='Student created: '+esc(d.name)+' · '+esc(d.student_id)+' · Temporary PIN: '+esc(d.pin)+'';box.classList.remove('hidden'); ['newStudentName','newStudentCourse','newStudentPhone','newStudentWhatsapp','newStudentEmail','newStudentBatch','newStudentGoal','newStudentTotalFee','newStudentPaidFee','newStudentBalanceFee','newStudentAddress'].forEach(id=>{if($(id))$(id).value='';}); if($('newStudentJoining'))$('newStudentJoining').value='';if($('newStudentDueDate'))$('newStudentDueDate').value='';if($('newStudentPhoto'))$('newStudentPhoto').value=''; await loadTrainerData(); closeAddStudent(); } function editStudent(studentId){ const u=(trainerDataCache?.users||[]).find(x=>String(x.student_id).toUpperCase()===String(studentId).toUpperCase());if(!u)return; $('editStudentId').value=u.student_id||'';$('editStudentIdReadonly').value=u.student_id||'';$('editName').value=u.name||'';$('editPhone').value=u.phone||'';$('editWhatsapp').value=u.whatsapp||'';$('editEmail').value=u.email||'';$('editAddress').value=u.address||'';$('editLevel').value=u.level||'Beginner';$('editCourse').value=u.course||'';$('editBatch').value=u.batch||'';$('editJoining').value=u.joining_date||'';$('editGoal').value=u.goal||'';$('editTotalFee').value=u.total_fee||'';$('editPaidFee').value=u.paid_fee||'';$('editBalanceFee').value=u.balance_fee||'';$('editDueDate').value=u.fee_due_date||'';$('editStatus').value=u.account_status||'Active';$('editStudentHeading').textContent=u.name||'Student';$('editStudentIdLabel').textContent=u.student_id||''; $('studentEditResult').classList.add('hidden');$('editStudentPhoto').value=''; setStudentPhotoPreview('editPhotoPreview',u.profile_photo); $('studentEditModal').classList.remove('hidden'); } function setStudentPhotoPreview(id,path){const el=$(id);if(!el)return;el.innerHTML=path?'Student photo':'👤';} $('editStudentPhoto')?.addEventListener('change',function(){const f=this.files?.[0];if(!f)return;if(f.size>2*1024*1024){alert('Photo must be 2 MB or smaller.');this.value='';return;}const reader=new FileReader();reader.onload=e=>{$('editPhotoPreview').innerHTML='Preview';};reader.readAsDataURL(f);}); async function saveStudentEdit(e){ e.preventDefault(); const fd=new FormData();fd.append('student_id',$('editStudentId').value);fd.append('name',$('editName').value.trim());fd.append('phone',$('editPhone').value.trim());fd.append('whatsapp',$('editWhatsapp').value.trim());fd.append('email',$('editEmail').value.trim());fd.append('address',$('editAddress').value.trim());fd.append('level',$('editLevel').value);fd.append('course',$('editCourse').value.trim());fd.append('batch',$('editBatch').value.trim());fd.append('joining_date',$('editJoining').value);fd.append('goal',$('editGoal').value.trim());fd.append('total_fee',$('editTotalFee').value.trim());fd.append('paid_fee',$('editPaidFee').value.trim());fd.append('balance_fee',$('editBalanceFee').value.trim());fd.append('fee_due_date',$('editDueDate').value);fd.append('account_status',$('editStatus').value); if($('editStudentPhoto')?.files?.[0])fd.append('profile_photo',$('editStudentPhoto').files[0]); const d=await api('update_student',fd);const box=$('studentEditResult');if(!d.ok){box.textContent=d.error||'Could not update student.';box.classList.remove('hidden');return;} box.textContent='Student profile updated successfully.';box.classList.remove('hidden');await loadTrainerData();setTimeout(closeStudentEdit,350); } function closeStudentEdit(){$('studentEditModal')?.classList.add('hidden');} async function resetStudentPin(studentId){const d=await api('update_student',{student_id:studentId,name:(trainerDataCache?.users||[]).find(x=>x.student_id===studentId)?.name||'Student',reset_pin:'1'});if(d.ok)alert('New temporary PIN for '+studentId+': '+d.pin);else alert(d.error||'Could not reset PIN.');if(d.ok)loadTrainerData();} let teacherNotificationCache={messages:[],completed_today:[],unread:0}; let teacherNotificationTimer=null; function positionTeacherNotificationDropdown(){ const dd=$('teacherNotificationDropdown'),bell=$('teacherNotificationBell');if(!dd||!bell)return; if(dd.parentElement!==document.body)document.body.appendChild(dd); const rect=bell.getBoundingClientRect(),vw=Math.max(document.documentElement.clientWidth,window.innerWidth||0),vh=Math.max(document.documentElement.clientHeight,window.innerHeight||0),mobile=vw<=600; dd.style.setProperty('position','fixed','important');dd.style.setProperty('box-sizing','border-box','important');dd.style.setProperty('z-index','2147483000','important');dd.style.setProperty('flex-direction','column','important');dd.style.setProperty('overflow','hidden','important'); const width=Math.max(0,Math.min(mobile?380:390,vw-24)),left=mobile?Math.max(12,(vw-width)/2):Math.max(12,Math.min(vw-width,rect.right-width)),top=Math.max(8,Math.min(rect.bottom+8,vh-180)); dd.style.setProperty('left',left+'px','important');dd.style.setProperty('right','auto','important');dd.style.setProperty('width',width+'px','important');dd.style.setProperty('max-width',width+'px','important');dd.style.setProperty('top',top+'px','important');dd.style.setProperty('max-height',Math.max(150,vh-top-12)+'px','important'); const list=$('teacherNotificationList');if(list)list.style.setProperty('max-height',Math.max(100,vh-top-175)+'px','important'); } function closeTeacherNotifications(){const dd=$('teacherNotificationDropdown');if(!dd)return;dd.style.removeProperty('display');dd.classList.add('hidden');} function toggleTeacherNotifications(){ const dd=$('teacherNotificationDropdown');if(!dd)return; const opening=dd.classList.contains('hidden');if(dd.parentElement!==document.body)document.body.appendChild(dd);dd.style.removeProperty('display');dd.classList.toggle('hidden',!opening); if(opening){positionTeacherNotificationDropdown();refreshTeacherNotifications();} } window.addEventListener('resize',()=>{const dd=$('teacherNotificationDropdown');if(dd&&!dd.classList.contains('hidden'))positionTeacherNotificationDropdown();}); window.addEventListener('orientationchange',()=>{const dd=$('teacherNotificationDropdown');if(dd&&!dd.classList.contains('hidden'))setTimeout(positionTeacherNotificationDropdown,100);}); async function refreshTeacherNotifications(){ if($('trainerPanel')?.classList.contains('hidden'))return; const d=await api('teacher_notifications');if(!d.ok)return; teacherNotificationCache=d; const badge=$('teacherNotificationBadge');if(badge){badge.textContent=(d.unread||0)>99?'99+':String(d.unread||0);badge.classList.toggle('hidden',!(d.unread>0));} const summary=$('teacherNotificationSummary'); if(summary)summary.innerHTML=''+Number(d.completed_count||0)+' student'+(Number(d.completed_count||0)===1?' has':'s have')+' completed today’s AI homework ('+esc(d.date||'Today')+')'; const list=$('teacherNotificationList');if(!list)return; const msgs=Array.isArray(d.messages)?d.messages:[],done=Array.isArray(d.completed_today)?d.completed_today:[]; let html=''; if(done.length){html+='
✓ HOMEWORK COMPLETED TODAY
'+done.map(x=>'
✅
'+esc(x.name||'Student')+' completed homework

'+esc(x.homework_title||'AI Daily Homework')+'

'+esc(x.student_id||'')+(x.submitted_at?' · '+esc(x.submitted_at):'')+(x.score!==null&&x.score!==''?' · Score: '+esc(x.score):'')+'
').join('');} const unreadMsgs=msgs.filter(x=>!x.read); if(msgs.length){html+='
💬 STUDENT MESSAGES
'+msgs.slice(0,12).map(x=>'
💬
'+esc(x.name||'Student')+(!x.read?' · NEW':'')+'

'+esc(x.message||'')+'

'+esc(x.student_id||'')+(x.created_at?' · '+esc(x.created_at):'')+'
').join('');} if(!done.length&&!msgs.length)html='
No student messages or completed homework yet today.
'; list.innerHTML=html; } async function markTeacherNotificationsRead(){ const ids=(teacherNotificationCache.messages||[]).filter(x=>!x.read).map(x=>String(x.id)); if(ids.length){await api('teacher_mark_notifications_read',{ids:JSON.stringify(ids)});} await refreshTeacherNotifications(); } async function openTeacherStudentMessage(id){ const n=(teacherNotificationCache.messages||[]).find(x=>String(x.id)===String(id)); if(n)await api('teacher_mark_notifications_read',{ids:JSON.stringify([String(id)])}); $('teacherNotificationDropdown')?.classList.add('hidden'); await loadTrainerData(); showTeacherSection('feedback'); } function startTeacherNotificationPolling(){ if(teacherNotificationTimer)clearInterval(teacherNotificationTimer); refreshTeacherNotifications(); teacherNotificationTimer=setInterval(()=>{if(!$('trainerPanel')?.classList.contains('hidden'))refreshTeacherNotifications();},30000); } document.addEventListener('click',function(e){const wrap=$('teacherNotificationWrap'),dd=$('teacherNotificationDropdown');if(wrap&&dd&&!wrap.contains(e.target)&&!dd.contains(e.target))closeTeacherNotifications();}); async function loadTrainerData(){ const d=await api('trainer_data'); if(!d.ok){enterTeacherShell(true);$('trainerError').textContent=d.error||'Teacher session expired. Please log in again.';$('trainerError').classList.remove('hidden');return;} trainerDataCache=d;populateTeacherMessageStudents(d);$('trainerLogin').classList.add('hidden');$('trainerPanel').classList.remove('hidden');startTeacherNotificationPolling(); const keepAttendance=!$('teacherAttendanceView')?.classList.contains('hidden'); const keepStudents=!$('teacherStudentsView')?.classList.contains('hidden'); const keepAi=!$('teacherAiLearnersView')?.classList.contains('hidden'); const keepDaily=!$('teacherDailyLearningView')?.classList.contains('hidden'); const keepEnquiries=!$('teacherEnquiriesView')?.classList.contains('hidden'); const keepHomework=!$('teacherHomeworkView')?.classList.contains('hidden'); const keepGrowth=!$('teacherGrowthView')?.classList.contains('hidden'); showTeacherSection(keepGrowth?'growth':(keepAttendance?'attendance':(keepStudents?'students':(keepAi?'ai_learners':(keepDaily?'daily_learning':(keepEnquiries?'enquiries':(keepHomework?'homework':'overview'))))))); const newEnquiries=(d.class_enquiries||[]).filter(x=>String(x.status||'New')==='New').length; const newFeedback=(d.student_feedback||[]).filter(x=>!x.teacher_read_at).length; const badge=$('teacherEnquiryBadge'); if(badge){badge.textContent=newEnquiries;badge.classList.toggle('hidden',newEnquiries===0);} let sec=0;d.users.forEach(u=>sec+=(+u.total_seconds||0)); $('tStudents').textContent=d.users.length;$('tActive').textContent=d.active_today||0;$('tPending').textContent=d.pending_homework||0;$('tAttention').textContent=(d.attention||[]).length; renderStudentTable(d.users);renderDailyLearning(d.users);renderDailyAiHomework(d.users);renderAttention(d.attention||[]);renderRecommendations(d.recommendations||[]);renderProgressSnapshot(d);renderTrainerInsights(d);renderTrainerDrafts(d.drafts||[]);renderTrainerMistakes(d.mistakes||[]);renderTrainerHomework(d.attempts||[]);renderHomeworkManagement(d.drafts||[],d.published_homework||[]); const sel=$('hwStudent');if(sel)sel.innerHTML=''+d.users.map(u=>'').join(''); } let teacherCertificatesCache=[]; async function loadTeacherCertificates(){ const d=await api('trainer_certificates'); if(!d.ok){alert(d.error||'Could not load certificates.');return;} teacherCertificatesCache=Array.isArray(d.students)?d.students:[]; filterTeacherCertificates(); } function filterTeacherCertificates(){ const q=String($('certificateSearch')?.value||'').trim().toLowerCase(); const f=String($('certificateStatusFilter')?.value||''); let rows=teacherCertificatesCache.filter(r=>{ const cert=r.certificate||{}; const issued=!!cert.certificate_no; const eligible=!!r.eligible; if(f==='eligible'&&!eligible)return false; if(f==='issued'&&!issued)return false; if(f==='inprogress'&&(eligible||issued))return false; if(q && !((r.name||'').toLowerCase().includes(q)||(r.student_id||'').toLowerCase().includes(q)||(cert.certificate_no||'').toLowerCase().includes(q)))return false; return true; }); const tb=$('teacherCertificatesTable');if(!tb)return; if(!rows.length){tb.innerHTML='
No students match the selected filter.
';return;} tb.innerHTML=rows.map(r=>{ const cert=r.certificate||{}; const issued=!!cert.certificate_no; const eligible=!!r.eligible; const approved=!!r.approved; const status=issued?(cert.status==='Revoked'?'🚫 Revoked':'🎓 Issued'):(eligible?(approved?'✅ Approved':'🟠 Awaiting Approval'):'⏳ In Progress'); const safeSid=String(r.student_id||'').replace(/'/g,"\\'"); const action=issued?'':eligible?(approved?'':''):'Complete 60 days'; return ''+esc(r.name||'Student')+'
'+esc(r.student_id||'')+'
'+esc(r.course||'Spoken English')+'Day '+Number(r.course_day||0)+'/60'+status+''+esc(cert.certificate_no||'—')+''+action+''; }).join(''); } async function approveCertificate(studentId){ if(!confirm('Approve '+studentId+' for certificate issuance after successful 60-day completion?'))return; const d=await api('approve_certificate',{student_id:studentId}); if(!d.ok){alert(d.error||'Could not approve certificate.');return;} alert('✅ Certificate approved.');await loadTeacherCertificates(); } async function issueCertificate(studentId){ if(!confirm('Issue the official 60-day course completion certificate for '+studentId+'?'))return; const d=await api('generate_certificate',{student_id:studentId}); if(!d.ok){alert(d.error||'Could not issue certificate.');return;} await loadTeacherCertificates(); previewCertificate(Number(d.certificate?.id||0)); } function previewCertificate(id){ const row=teacherCertificatesCache.find(r=>Number(r.certificate?.id||0)===Number(id)); const c=row?.certificate;if(!c)return; const card=$('certificatePreviewCard'),area=$('certificatePreviewArea');if(!card||!area)return; area.innerHTML='
POOJA ENGLISH SPOKEN
CERTIFICATE OF COMPLETION
This certificate is proudly presented to
'+esc(c.student_name)+'
for successfully completing the
'+esc(c.course||'Spoken English')+'
60-Day English Learning Programme
Certificate No.'+esc(c.certificate_no)+'
Completion Date'+esc(c.completion_date)+'
Level'+esc(c.level||'')+'
Learn • Speak • Grow
'; card.style.display='block';card.scrollIntoView({behavior:'smooth',block:'start'}); } function closeCertificatePreview(){if($('certificatePreviewCard'))$('certificatePreviewCard').style.display='none';} function printCertificate(){ const el=$('printCertificate');if(!el)return; const w=window.open('','_blank','width=1100,height=800');if(!w){alert('Please allow pop-ups to print the certificate.');return;} w.document.write('Certificate'+el.outerHTML+'');w.document.close();setTimeout(()=>{w.focus();w.print();},400); } function toggleStudentPin(id){ const el=$(id);if(!el)return; const shown=el.dataset.shown==='1'; if(shown){el.textContent='••••••';el.dataset.shown='0';} else{el.textContent=el.dataset.pin||'Not set';el.dataset.shown='1';} } function renderStudentTable(users){ const q=($('studentSearch')?.value||'').toLowerCase().trim(),level=$('studentLevelFilter')?.value||'',activity=$('studentActivityFilter')?.value||'',today=new Intl.DateTimeFormat('en-CA',{timeZone:'Asia/Kolkata'}).format(new Date()); const filtered=(users||[]).filter(u=>{ const hay=(String(u.name||'')+' '+String(u.student_id||'')).toLowerCase(); if(q&&!hay.includes(q))return false; if(level&&u.level!==level)return false; const active=String(u.last_seen||'').startsWith(today); const attention=(trainerDataCache?.attention||[]).some(x=>+x.id===+u.id); if(activity==='active'&&!active)return false; if(activity==='attention'&&!attention)return false; return true; }); $('studentTable').innerHTML=filtered.length?filtered.map(u=>{ const photo=u.profile_photo?'':'👤'; const status=u.account_status||'Active'; const cls=status.toLowerCase()==='active'?'active':'inactive'; const balance=String(u.balance_fee||'').trim(), total=String(u.total_fee||'').trim(); const fee=balance?'₹'+esc(balance)+' Due':(total?'₹'+esc(total)+'':'Not set'); const sid=JSON.stringify(String(u.student_id||'')); const uname=JSON.stringify(String(u.name||'Student')); const pin=String(u.login_pin||''); const pinId='pin_'+String(u.id||''); const pinCell=pin?'•••••• ':'Not set'; return `
${photo}${esc(u.name)}${esc(u.language_mode==='hinglish'?'Hinglish':'English')}
${esc(u.student_id||'—')} ${esc(u.level||'—')} ${esc(u.course||'—')} ${fee} ${esc(status)} ${pinCell} `; }).join(''):'No students match your search or filters.'; } function renderDailyAiHomework(users){ const today=new Intl.DateTimeFormat('en-CA',{timeZone:'Asia/Kolkata'}).format(new Date()); const dateEl=$('dailyAiHomeworkDate');if(dateEl)dateEl.value=today; const total=(users||[]).length;const sent=(users||[]).filter(u=>!!u.daily_homework_exists).length; const completed=(users||[]).filter(u=>!!u.daily_homework_exists&&!!u.daily_homework_completed).length; const pending=Math.max(0,sent-completed); const pill=$('dailyAiHomeworkCountPill');if(pill)pill.textContent=sent+' / '+total+' SENT'; const summary=$('dailyAiHomeworkSummary'); if(summary) summary.innerHTML='Today: '+esc(today)+'   ·   '+sent+' homework sent   ·   '+completed+' completed   ·   '+pending+' pending submission   ·   '+Math.max(0,total-sent)+' not sent.'; filterDailyAiHomework(); } function filterDailyAiHomework(){ const users=trainerDataCache?.users||[]; const q=($('dailyAiHomeworkSearch')?.value||'').toLowerCase().trim(); const level=$('dailyAiHomeworkLevelFilter')?.value||''; const status=$('dailyAiHomeworkStatusFilter')?.value||''; const list=users.filter(u=>{ const hay=(String(u.name||'')+' '+String(u.student_id||'')).toLowerCase(); if(q&&!hay.includes(q))return false; if(level&&u.level!==level)return false; const sent=!!u.daily_homework_exists,completed=!!u.daily_homework_completed; if(status==='sent'&&!sent)return false; if(status==='missing'&&sent)return false; if(status==='completed'&&(!sent||!completed))return false; if(status==='pending'&&(!sent||completed))return false; return true; }); const el=$('dailyAiHomeworkTable');if(!el)return; el.innerHTML=list.length?list.map(u=>{ const sent=!!u.daily_homework_exists,completed=!!u.daily_homework_completed; const day=u.daily_homework_course_day?('Day '+u.daily_homework_course_day+'/60'):'—'; const homework=sent?(u.daily_homework_title||'Personalized Homework'):'Not prepared yet'; const topic=sent?(u.daily_homework_topic||'Personal Practice'):''; const completion=completed?('✓ COMPLETED'+esc(u.daily_homework_submitted_at?new Date(u.daily_homework_submitted_at).toLocaleString('en-IN'):'Submitted')+(u.daily_homework_score!==null&&u.daily_homework_score!==''?' · Score: '+esc(u.daily_homework_score):'')+''):(sent?'⏳ PENDING':'—'); return '
👤'+esc(u.name||'Student')+''+esc(u.student_id||'—')+'
'+esc(u.level||'—')+''+esc(day)+''+(sent?'✓ SENT':'⏳ NOT SENT')+''+completion+''+esc(homework)+''+(topic?''+esc(topic)+'':'')+''+(sent?esc(u.daily_homework_question_count||0)+' + speaking':'—')+''+(sent?'':'Waiting')+''; }).join(''):'No students match the filters.'; } async function openDailyAiHomework(studentId){ const box=$('studentProfileContent');if(!box)return; box.innerHTML='
Loading complete AI homework...
';$('studentProfileModal').classList.remove('hidden'); const d=await api('trainer_daily_homework_detail',{student_id:studentId}); if(!d.ok){box.innerHTML='
'+esc(d.error||'Could not load homework.')+'
';return;} renderTeacherDailyHomeworkEditor(d.student,d.homework,d.attempts||[]); } function renderTeacherDailyHomeworkEditor(student,hw,attempts){ const questions=Array.isArray(hw.questions)?hw.questions:[]; const safeAttempts=Array.isArray(attempts)?attempts.slice().sort((a,b)=>String(b.submitted_at||'').localeCompare(String(a.submitted_at||''))):[]; const attemptHtml=safeAttempts.length?safeAttempts.map((a,ai)=>{ const ans=Array.isArray(a.answers)?a.answers:[]; const score=Number(a.score||0); return '

📊 AI Evaluation · Attempt '+(safeAttempts.length-ai)+'

'+esc(score)+'/100

'+esc(a.correct||0)+'/'+esc(a.total||ans.length)+' correct · '+esc(a.submitted_at||'')+'

'+esc(a.ai_feedback|| (score>=80?'Excellent work! Keep practising.':score>=60?'Good effort. Review the corrections below.':'Keep practising and review the corrections below.'))+'

'+(Array.isArray(a.strengths)&&a.strengths.length?'

Strengths: '+a.strengths.map(x=>esc(x)).join(' · ')+'

':'')+(Array.isArray(a.areas_to_improve)&&a.areas_to_improve.length?'

Areas to improve: '+a.areas_to_improve.map(x=>esc(x)).join(' · ')+'

':'')+(a.next_practice?'

Next practice: '+esc(a.next_practice)+'

':'')+'
'+ans.map((x,i)=>'
'+(i+1)+'. '+(x.correct?'✓ Correct':'✗ Needs practice')+'
'+esc(x.question||'')+'
Student answer: '+esc(x.answer||'—')+''+(x.correct?'':'Better answer: '+esc(x.better_answer||'—')+'')+(x.explanation?''+esc(x.explanation)+'':'')+'
').join('')+'
'; }).join(''):'
No submitted attempt/evaluation is saved for this homework yet.
'; const rows=questions.map((q,i)=>teacherHomeworkQuestionRow(q,i)).join(''); const box=$('studentProfileContent'); box.innerHTML='
🤖
AI Daily Homework · '+esc(hw.date||'Today')+'

'+esc(student.name||'Student')+'

'+esc(student.student_id||'')+' · '+esc(student.level||'')+' · Day '+esc(hw.course_day||'—')+'/60

✓ SENT
'+attemptHtml+ '
Teacher Control: Edit the AI-generated homework, add/remove questions, change answers/explanations, update the speaking task, then save the final version.
'+ '
'+ '

📝 Questions ('+questions.length+')

'+rows+'
'+ '
'+ '
'; } function teacherHomeworkQuestionRow(q,i){ q=q||{};return '
Question '+(i+1)+'
'; } function addTeacherDailyQuestion(){ const wrap=$('teacherDhQuestions');if(!wrap)return;const i=wrap.querySelectorAll('[data-dh-question]').length;wrap.insertAdjacentHTML('beforeend',teacherHomeworkQuestionRow({type:'short_answer',question:'',answer:'',explanation:''},i)); } function removeTeacherDailyQuestion(btn){const wrap=$('teacherDhQuestions');if(!wrap)return;if(wrap.querySelectorAll('[data-dh-question]').length<=1){alert('At least one question is required.');return;}btn.closest('[data-dh-question]')?.remove();} function collectTeacherDailyQuestions(){ return Array.from(document.querySelectorAll('#teacherDhQuestions [data-dh-question]')).map(card=>({type:card.querySelector('.teacher-dh-type')?.value||'short_answer',question:card.querySelector('.teacher-dh-question')?.value.trim()||'',answer:card.querySelector('.teacher-dh-answer')?.value.trim()||'',explanation:card.querySelector('.teacher-dh-explanation')?.value.trim()||''})); } async function saveTeacherDailyHomework(id){ const questions=collectTeacherDailyQuestions();if(!questions.length){alert('Add at least one question.');return;}if(questions.some(q=>!q.question)){alert('Every question must have question text.');return;} const d=await api('trainer_daily_homework_update',{homework_id:id,title:$('teacherDhTitle')?.value.trim()||'',topic:$('teacherDhTopic')?.value.trim()||'',instructions:$('teacherDhInstructions')?.value.trim()||'',speaking_task:$('teacherDhSpeaking')?.value.trim()||'',questions:JSON.stringify(questions)}); if(!d.ok){alert(d.error||'Could not save homework.');return;}alert('✅ AI Daily Homework updated successfully.');closeStudentProfile();await loadTrainerData();showTeacherSection('homework'); } async function deleteTeacherDailyHomework(id){ if(!confirm('Delete this AI Daily Homework?\n\nThis removes it from the student homework list.'))return; const d=await api('trainer_daily_homework_delete',{homework_id:id});if(!d.ok){alert(d.error||'Could not delete homework.');return;}alert('🗑️ Homework deleted.');closeStudentProfile();await loadTrainerData();showTeacherSection('homework'); } function renderDailyLearning(users){ const q=($('dailyLearningSearch')?.value||'').toLowerCase().trim(),level=$('dailyLearningLevelFilter')?.value||''; const today=new Intl.DateTimeFormat('en-CA',{timeZone:'Asia/Kolkata'}).format(new Date()); let date=$('dailyLearningDate')?.value||today; if(date>today){date=today;$('dailyLearningDate').value=today;} const source=(date===today||!window.dailyLearningDateData)?(users||[]):(window.dailyLearningDateData||[]); const list=source.filter(u=>{const hay=(String(u.name||'')+' '+String(u.student_id||'')).toLowerCase();if(q&&!hay.includes(q))return false;if(level&&u.level!==level)return false;return true;}); $('dailyLearningCountPill').textContent=list.length+' STUDENT'+(list.length===1?'':'S'); $('dailyLearningTable').innerHTML=list.length?list.map(u=>{ const hasPack=!!u.daily_pack_exists; const lessonDay=u.lesson_day||u.daily_lesson_day||0; const day=lessonDay?('Day '+lessonDay+'/60'):'—'; const topic=u.lesson_topic||u.daily_lesson_topic||''; const sid=String(u.student_id||'').replace(/'/g,"\\'"); const joinRaw=String(u.daily_joining_date||u.joining_date||u.course_start_date||'').trim(); const joinDisplay=/^\d{4}-\d{2}-\d{2}$/.test(joinRaw)?joinRaw.split('-').reverse().join('-'):(joinRaw||'—'); return `
👤${esc(u.name||'Student')}${esc(u.student_id||'—')}
${esc(joinDisplay)}${esc(u.level||'—')}
${esc(day)}${topic?''+esc(topic)+'':''}
${hasPack?'✓ AI Prepared':'Not prepared'}`; }).join(''):'No students match your filters.'; } function filterDailyLearning(){if(trainerDataCache)renderDailyLearning(trainerDataCache.users||[]);} async function loadDailyLearningForDate(autoPrepare=false){ const today=new Intl.DateTimeFormat('en-CA',{timeZone:'Asia/Kolkata'}).format(new Date());let date=$('dailyLearningDate')?.value||today; if(date>today){alert('Future dates are not available.');$('dailyLearningDate').value=today;date=today;} const d=await api('trainer_daily_learning',{student_id:'',date:date}); if(!d.ok){alert(d.error||'Could not load AI daily learning.');return;} window.dailyLearningDateData=d.summaries||[]; renderDailyLearning(window.dailyLearningDateData); } async function openDailyLearning(studentId,date){ const sid=String(studentId||'').trim();if(!sid){alert('Student ID is missing.');return;} const today=new Intl.DateTimeFormat('en-CA',{timeZone:'Asia/Kolkata'}).format(new Date());const selected=date||today; if(selected>today){alert('Future dates are not available.');return;} const d=await api('trainer_daily_learning',{student_id:sid,date:selected}); if(!d.ok){alert(d.error||'Could not load AI learning.');return;} const pack=d.pack||null,acts=Array.isArray(pack?.activities)?pack.activities:[]; const day=Number(d.learning_state?.day||0); const labels={word:'📖 Word of the Day',phrase:'💬 Phrase of the Day',idiom:'🌱 Idiom of the Day',proverb:'🪴 Proverb of the Day',grammar:'🔤 Grammar Focus',sentence:'✨ Sentence of the Day',speaking:'🗣️ Daily Speaking Challenge',mistake:'🎯 My Mistake of the Day',quiz:'🧩 Mini Quiz',pronunciation:'🎧 Pronunciation Challenge'}; let html='
👤
AI DAILY LEARNING

'+esc(d.student?.name||'Student')+'

'+esc(d.student?.student_id||sid)+' · '+esc(d.student?.level||'')+' · 📅 '+esc(d.date)+(day?' · Day '+esc(day)+'/60':'')+'

'; html+='

🤖 WHAT AI TAUGHT TODAY

'; if(!pack||!acts.length){html+='
No AI content was prepared for this student on '+esc(d.date)+'.
';}else{ html+='
'+acts.map(a=>{const c=a.content||{};let main='';if(a.id==='word')main=''+esc(c.word||'')+'

'+esc(c.meaning_simple||'')+' · '+esc(c.hindi_meaning||'')+'

Example: '+esc(c.example||'')+'

';else if(a.id==='phrase')main=''+esc(c.phrase||'')+'

'+esc(c.meaning||'')+' · '+esc(c.hindi_meaning||'')+'

Example: '+esc(c.example||'')+'

';else if(a.id==='idiom')main=''+esc(c.idiom||'')+'

'+esc(c.meaning||'')+' · '+esc(c.hindi_meaning||'')+'

Example: '+esc(c.example||'')+'

';else if(a.id==='proverb')main=''+esc(c.proverb||'')+'

'+esc(c.meaning||'')+' · '+esc(c.hindi_meaning||'')+'

Example: '+esc(c.example||'')+'

';else if(a.id==='grammar')main=''+esc(c.topic||'')+'

'+esc(c.rule||'')+'

Correct: '+esc(c.example_right||'')+'

';else if(a.id==='sentence')main=''+esc(c.sentence||'')+'

'+esc(c.meaning||'')+' · '+esc(c.hindi_meaning||'')+'

';else if(a.id==='speaking')main=''+esc(c.topic||'')+'

'+esc(c.instruction||'')+'

';else if(a.id==='mistake')main='

Mistake: '+esc(c.mistake||'')+'

Correction: '+esc(c.correction||'')+'

'+esc(c.explanation||'')+'

';else if(a.id==='quiz')main='

'+esc((c.questions||[]).length)+' questions

'+((c.questions||[]).map((q,i)=>'

Q'+(i+1)+'. '+esc(q.question||'')+'

').join(''));else if(a.id==='pronunciation')main=''+esc(c.word_or_sentence||'')+'

'+esc(c.pronunciation||'')+' · '+esc(c.meaning||'')+'

';else main='

'+esc(JSON.stringify(c))+'

';return '
'+esc(labels[a.id]||a.title||a.id||'Activity')+'

'+esc(a.title||'Daily Activity')+'

'+main+'
';}).join('')+'
'; } html+='
'; $('studentProfileContent').innerHTML=html;$('studentProfileModal').classList.remove('hidden'); } function filterStudents(){if(trainerDataCache)renderStudentTable(trainerDataCache.users);} function waLink(number){ let n=String(number||'').replace(/[^0-9]/g,''); if(n.length===10)n='91'+n; return n?'https://wa.me/'+n:''; } function populateFeedbackStudents(users){const el=$('feedbackStudentFilter');if(!el)return;const current=el.value;el.innerHTML=''+(users||[]).map(u=>'').join('');if(current)el.value=current;} function renderStudentFeedback(items,users){populateFeedbackStudents(users);const sid=$('feedbackStudentFilter')?.value||'',date=$('feedbackDateFilter')?.value||'';const list=(items||[]).filter(x=>{if(sid&&String(x.user_id)!==String(sid))return false;if(date&&String(x.created_at||'').slice(0,10)!==date)return false;return true;});$('feedbackCountPill').textContent=list.length+' MESSAGE'+(list.length===1?'':'S');$('studentFeedbackTable').innerHTML=list.length?list.map(x=>''+esc(x.name||'Student')+''+esc(x.student_id||'—')+''+esc(x.message||'—')+''+esc(x.created_at||'')+'').join(''):'No feedback found.';} function filterStudentFeedback(){if(trainerDataCache)renderStudentFeedback(trainerDataCache.student_feedback||[],trainerDataCache.users||[]);} function clearStudentFeedbackFilters(){if($('feedbackStudentFilter'))$('feedbackStudentFilter').value='';if($('feedbackDateFilter'))$('feedbackDateFilter').value='';filterStudentFeedback();} function filterClassEnquiries(){if(trainerDataCache)renderClassEnquiries(trainerDataCache.class_enquiries||[]);} async function updateClassEnquiryStatus(id,status){const d=await api('update_class_enquiry',{id:id,status:status});if(!d.ok){alert(d.error||'Could not update enquiry.');return;}await loadTrainerData();showTeacherSection('enquiries');} async function deleteClassEnquiry(id){if(!confirm('Delete this enquiry?'))return;const d=await api('delete_class_enquiry',{id:id});if(!d.ok){alert(d.error||'Could not delete enquiry.');return;}await loadTrainerData();showTeacherSection('enquiries');} function renderClassEnquiries(items){ const q=($('enquirySearch')?.value||'').toLowerCase().trim(),status=($('enquiryStatusFilter')?.value||''); const list=(items||[]).filter(x=>{const hay=(String(x.name||'')+' '+String(x.email||'')+' '+String(x.phone||'')+' '+String(x.whatsapp||'')+' '+String(x.goal||'')).toLowerCase();if(q&&!hay.includes(q))return false;if(status&&String(x.status||'New')!==status)return false;return true;}); $('enquiryCountPill').textContent=list.length+' ENQUIR'+(list.length===1?'Y':'IES'); $('classEnquiryTable').innerHTML=list.length?list.map(x=>{ const wa=waLink(x.whatsapp||x.phone);const contact=(wa?'📲 WhatsApp':'')+(x.email?'✉️ Email':''); const st=x.status||'New'; return ''+esc(x.name||'Learner')+''+esc(x.email||'')+''+esc(x.whatsapp||x.phone||'—')+'
'+contact+'
'+esc(x.level||'—')+''+esc(x.goal||'—')+''+esc(x.message||'—')+''+esc(x.created_at||'')+''; }).join(''):'No class enquiries match your search or filter.'; } function renderAiLearners(items,enquiries){ const q=($('aiLearnerSearch')?.value||'').toLowerCase().trim(),level=$('aiLearnerLevelFilter')?.value||''; const list=(items||[]).filter(u=>{ const hay=(String(u.name||'')+' '+String(u.public_id||'')+' '+String(u.email||'')+' '+String(u.phone||'')+' '+String(u.whatsapp||'')).toLowerCase(); if(q&&!hay.includes(q))return false;if(level&&u.level!==level)return false;return true; }); const leads=(enquiries||[]).filter(x=>String(x.status||'New')!=='Closed').slice(0,5); $('aiLearnerEnquiries').innerHTML=leads.length?'
📩 Recent class enquiries
'+leads.map(x=>'
'+esc(x.name||'Learner')+''+esc(x.level||'')+' · '+esc(x.whatsapp||x.phone||x.email||'No contact')+' · '+esc(x.created_at||'')+'
'+(waLink(x.whatsapp||x.phone)?'WhatsApp':'')+(x.email?'Email':'')+'
').join('')+'
':'
No new class enquiry yet.
'; $('aiLearnerTable').innerHTML=list.length?list.map(u=>{ const contact=waLink(u.whatsapp||u.phone)?'WhatsApp':(u.email?'Email':'No contact'); return '
🌍'+esc(u.name||'Learner')+''+esc(u.email||'')+'
'+esc(u.public_id||'—')+''+esc(u.level||'—')+''+contact+''+esc(u.chat_count||0)+' chats · '+esc(u.grammar_count||0)+' grammar · '+esc(u.mistake_count||0)+' mistakes · '+esc(u.practice_minutes||0)+' min'+esc(u.last_seen||'Never')+''; }).join(''):'No AI learners match your search or filters.'; } function filterAiLearners(){if(trainerDataCache)renderAiLearners(trainerDataCache.ai_learners||[],trainerDataCache.class_enquiries||[]);} function openAiLearnerProfile(id){ const u=(trainerDataCache?.ai_learners||[]).find(x=>+x.id===+id);if(!u)return; const wa=waLink(u.whatsapp||u.phone);const contact=wa?'📲 WhatsApp':''; $('studentProfileContent').innerHTML='
🌍
Free AI Learner

'+esc(u.name||'Learner')+'

'+esc(u.public_id||'—')+' · '+esc(u.level||'—')+' · '+esc(u.email||'')+'

FREE
'+ '

👤 Contact

WhatsApp / Phone'+esc(u.whatsapp||u.phone||'Not added')+'
Email'+esc(u.email||'Not added')+'
Goal'+esc(u.goal||'Not added')+'
Created'+esc(u.created_at||'')+'
'+contact+(u.email?'✉️ Email':'')+'
'+ '

📊 AI Learning Activity

AI Chats'+esc(u.chat_count||0)+'
Grammar Checks'+esc(u.grammar_count||0)+'
Mistakes'+esc(u.mistake_count||0)+'
Practice Time'+esc(u.practice_minutes||0)+'m
'+ '

🔐 Login Security

PasswordProtected — teacher cannot view it
RecoveryOTP by registered email
'+(u.email?'':'No email available')+'
The original password is never shown or stored in readable form.
'+ '

📅 Activity

Last active: '+esc(u.last_seen||'Never')+'

'; $('studentProfileModal').classList.remove('hidden'); } async function sendAiLearnerResetOtp(id){ if(!confirm('Send a password-reset OTP to this AI learner’s registered email?'))return; const d=await api('send_ai_learner_reset_otp',{user_id:id}); if(!d.ok){alert(d.error||'Could not send OTP.');return;} alert(d.message||'Password reset OTP sent.'); } function renderAttention(items){$('trainerAttention').innerHTML=items.length?items.map(x=>'
'+esc(x.name)+' · '+esc(x.student_id)+'
'+x.reasons.map(esc).join(' · ')+'
').join(''):'
🎉 No urgent student issues detected.
';} function renderRecommendations(items){ return items||[]; } function renderTrainerInsights(d){ const w=d.top_weaknesses||[],cs=d.class_stats||{},hard=d.hardest_questions||[],recs=d.recommendations||[]; let html='
'+ '
👥 Active today'+esc(d.active_today||0)+' / '+esc(d.users.length||0)+'
'+ '
📝 Homework completion'+esc(cs.completion_rate||0)+'%'+esc(cs.completed||0)+' of '+esc(cs.assigned||0)+' assigned slots completed
'+ '
📈 Average homework score'+esc(cs.average_score||0)+'%'+esc(cs.attempts||0)+' submission(s)
'+ '
🗂️ Drafts waiting'+esc(d.draft_count||0)+'private homework draft(s)
'+ '
🧠 Common learning gaps
'+(w.length?w.slice(0,5).map(x=>''+esc(x.source)+' · '+esc(x.count)+'').join(''):'No repeated mistake pattern yet.')+'
'+ '
'; if(hard.length) html+='

🎯 Questions Needing More Practice

'+hard.slice(0,5).map(q=>'
Q'+esc(q.number)+' · '+esc(q.accuracy)+'% accuracy'+esc(q.question||'')+'
').join('')+'
'; if(recs.length) html+='

🎯 Teaching Recommendations

'+recs.slice(0,5).map(x=>'
'+esc(x)+'
').join('')+'
'; $('trainerInsights').innerHTML=html; } function openHomeworkCreator(){ showTeacherSection('homework'); setTimeout(()=>{$('createHomeworkCard')?.scrollIntoView({behavior:'smooth',block:'start'});},60); } function renderHomeworkManagement(drafts,published){ const el=$('teacherHomeworkList'); if(!el)return; const items=[...(drafts||[]).map(h=>({...h,_status:'draft'})),...(published||[]).map(h=>({...h,_status:'published'}))]; window.trainerHomeworkManagementItems=items; if(!items.length){el.innerHTML='
📝No homework yetClick “Create New Homework” to create your first assignment.
';renderHomeworkSummary([]);return;} renderHomeworkSummary(items); el.innerHTML=items.map(h=>{ const attempts=(trainerDataCache?.attempts||[]).filter(a=>+a.homework_id===+h.id); const assigned=(trainerDataCache?.users||[]).filter(u=>{const levelOk=(h.level||'All')==='All'||h.level===u.level;const targetOk=!h.target_student_id||String(h.target_student_id).toUpperCase()===String(u.student_id||'').toUpperCase();return h.target_student_id?targetOk:(levelOk&&targetOk);}).length; const completed=new Set(attempts.map(a=>String(a.user_id))).size; const status=h._status==='draft'?'DRAFT':'PUBLISHED'; const statusClass=h._status==='draft'?'pill':'pill good'; const actions=h._status==='draft' ? '' : ''; return '
'+ '

📝 '+esc(h.title||'Homework')+'

'+esc(h.topic||'')+' · '+esc(h.level||'All')+' · '+esc(h.question_count||((h.questions||[]).length)||0)+' questions
'+status+'
'+ '

'+(h._status==='draft'?'Private draft · Saved: '+esc(h.updated_at||h.created_at||''):'Published: '+esc(h.published_at||h.approved_at||h.created_at||''))+'

'+ '
Assigned'+assigned+'
Completed'+completed+'
Pending'+Math.max(0,assigned-completed)+'
'+ '
'+actions+'
'; }).join(''); } function renderHomeworkSummary(items){ const el=$('trainerHomeworkSummary');if(!el)return; const drafts=(items||[]).filter(x=>x._status==='draft').length; const published=(items||[]).filter(x=>x._status==='published').length; const assigned=(trainerDataCache?.class_stats?.assigned)||0; const completed=(trainerDataCache?.class_stats?.completed)||0; const pending=Math.max(0,assigned-completed); el.innerHTML='
'+ '
Drafts'+drafts+'
'+ '
Published'+published+'
'+ '
Assigned'+assigned+'
'+ '
Completed'+completed+'
'+ '
Pending'+pending+'
'+ '
'; } function renderProgressSnapshot(d){ const el=$('trainerProgressSnapshot');if(!el)return; const cs=d.class_stats||{}; const totalMistakes=(d.mistakes||[]).length; let totalMinutes=0; (d.users||[]).forEach(u=>{totalMinutes+=Math.round((+u.total_seconds||0)/60);}); el.innerHTML='
'+ '
📊
Average Homework Score'+esc(cs.average_score||0)+'%
'+ '
📝
Homework Completion'+esc(cs.completion_rate||0)+'%
'+ '
🟢
Active Today'+esc(d.active_today||0)+' / '+esc((d.users||[]).length)+'
'+ '
⏱️
Total Practice Time'+esc(totalMinutes)+' min
'+ '
🧠
Recorded Mistakes'+esc(totalMistakes)+'
'+ '
'; } function filterHomeworkList(){ const q=($('homeworkSearch')?.value||'').toLowerCase().trim(),level=$('homeworkLevelFilter')?.value||'',status=$('homeworkStatusFilter')?.value||''; document.querySelectorAll('#teacherHomeworkList [data-hw-status]').forEach(el=>{const text=(el.getAttribute('data-hw-search')||'').toLowerCase(),lv=el.getAttribute('data-hw-level')||'',st=el.getAttribute('data-hw-status')||'';el.style.display=(!q||text.includes(q))&&(!level||lv===level)&&(!status||st===status)?'':'none';}); } function viewHomeworkDetails(id){ const all=[...(trainerDataCache?.drafts||[]),...(trainerDataCache?.published_homework||[])];const h=all.find(x=>+x.id===+id);if(!h)return; const attempts=(trainerDataCache?.attempts||[]).filter(a=>+a.homework_id===+id); const questions=Array.isArray(h.questions)?h.questions:[]; const assigned=(trainerDataCache?.users||[]).filter(u=>{const levelOk=(h.level||'All')==='All'||h.level===u.level;const targetOk=!h.target_student_id||String(h.target_student_id).toUpperCase()===String(u.student_id||'').toUpperCase();return h.target_student_id?targetOk:(levelOk&&targetOk);}); let html='
📝
Homework

'+esc(h.title||'Homework')+'

'+esc(h.topic||'')+' · '+esc(h.level||'All')+' · '+questions.length+' questions

'+esc(h.status||'published').toUpperCase()+'
'+ '

📋 Instructions

'+esc(h.instructions||'No instructions added.')+'

'+ '

📊 Assignment Status

Assigned'+assigned.length+'
Completed'+new Set(attempts.map(a=>String(a.user_id))).size+'
Pending'+Math.max(0,assigned.length-new Set(attempts.map(a=>String(a.user_id))).size)+'
'+ '

❓ Questions

'+(questions.length?questions.map((q,i)=>'
Q'+(i+1)+'. '+esc(q.question||'')+'
Expected answer: '+esc(q.answer||'—')+''+(q.explanation?'
'+esc(q.explanation)+'':'')+'
').join(''):'

No questions saved.

')+'
'+ '

👥 Assigned Students

'+(assigned.length?assigned.map(u=>'
'+esc(u.name)+''+esc(u.student_id||'')+' · '+esc(u.level||'')+'
'+((attempts.find(a=>+a.user_id===+u.id))?'Completed':'Pending')+'
').join(''):'

No matching students.

')+'
'+ '
'; $('studentProfileContent').innerHTML=html;$('studentProfileModal').classList.remove('hidden'); } async function removePublishedHomework(id){ const h=(trainerDataCache?.published_homework||[]).find(x=>+x.id===+id);if(!h)return; const attempts=(trainerDataCache?.attempts||[]).filter(a=>+a.homework_id===+id).length; const msg=attempts?'Remove this homework from students? Existing '+attempts+' submission(s), scores and mistakes will be preserved.':'Remove this published homework? Students will no longer see it.'; if(!confirm(msg))return; const d=await api('remove_published_homework',{homework_id:id});if(!d.ok){alert(d.error||'Could not remove homework.');return;} await loadTrainerData(); } function renderTrainerDrafts(items){ const el=$('trainerDrafts'); if(!el)return; if(!items.length){el.innerHTML='
No private drafts. Create a homework, review it, then save it as a draft.
';return;} el.innerHTML=items.map(h=>'

📝 '+esc(h.title)+'

'+esc(h.topic)+' · '+esc(h.level)+' · '+esc(h.question_count||0)+' questions
DRAFT · PRIVATE

Saved: '+esc(h.updated_at||h.created_at||'')+'

').join(''); } function renderTrainerMistakes(items){ $('trainerMistakes').innerHTML=items.length?items.slice(0,10).map(m=>'
'+esc(m.name)+' · '+esc(m.student_id||'')+''+esc(m.source)+'
'+esc(m.mistake)+' → '+esc(m.correction||'')+'
').join(''):'
No mistakes recorded yet.
'; } function renderTrainerHomework(items){ $('trainerHomework').innerHTML=items.length?items.slice(0,10).map(a=>'
'+esc(a.name)+''+esc(a.student_id||'')+' · '+esc(a.title||a.topic||'Homework')+'
'+esc(a.score||0)+'%
').join(''):'
No homework submissions yet.
'; } function openStudentProfile(id){ const d=trainerDataCache;if(!d)return;const u=d.users.find(x=>+x.id===+id);if(!u)return; const ms=d.mistakes.filter(x=>+x.user_id===+id),as=d.attempts.filter(x=>+x.user_id===+id),at=(d.attention||[]).find(x=>+x.id===+id); const photo=u.profile_photo?'Student photo':'👤'; const sid=JSON.stringify(String(u.student_id||'')); const status=u.account_status||'Active'; const feeText=u.balance_fee?('₹'+esc(u.balance_fee)+' due'):((u.total_fee||'')?'₹'+esc(u.total_fee):'Not set'); $('studentProfileContent').innerHTML='
'+photo+'
Student Profile

'+esc(u.name)+'

'+esc(u.student_id||'—')+' · '+esc(u.level||'—')+' · '+esc(u.course||'Course not set')+'

'+esc(status)+'
'+ '

👤 Personal & Contact

Phone'+esc(u.phone||'Not added')+'
WhatsApp'+esc(u.whatsapp||'Not added')+'
Email'+esc(u.email||'Not added')+'
Address'+esc(u.address||'Not added')+'
'+ '

📚 Course & Admission

Level'+esc(u.level||'—')+'
Batch'+esc(u.batch||'Not set')+'
Joining Date'+esc(u.joining_date||'Not set')+'
Goal'+esc(u.goal||'Not set')+'
'+ '

💰 Fees

Total Fee'+esc(u.total_fee?('₹'+u.total_fee):'Not set')+'
Paid'+esc(u.paid_fee?('₹'+u.paid_fee):'Not set')+'
Balance'+esc(u.balance_fee?('₹'+u.balance_fee):'Not set')+'
Due Date'+esc(u.fee_due_date||'Not set')+'
'+ '

📊 Learning Activity

Practice'+Math.round((u.total_seconds||0)/60)+'m
Mistakes'+esc(u.mistake_count||0)+'
Homework Done'+esc(u.homework_count||0)+'
Pending'+esc(u.pending_homework||0)+'
'+ (at?'
⚠️ Attention
'+at.reasons.map(esc).join(' · ')+'
':'')+ '

🧠 Recent Mistakes

'+(ms.length?ms.slice(0,8).map(m=>'
'+esc(m.source)+'
'+esc(m.mistake)+' → '+esc(m.correction||'')+'
'+esc(m.explanation||'')+'
').join(''):'

No mistakes recorded.

')+'
'+ '

📝 Homework History

'+(as.length?as.slice(0,8).map(a=>'
'+esc(a.title||a.topic||'Homework')+' · '+esc(a.score||0)+'/100
'+esc(a.feedback||'')+'
').join(''):'

No homework submissions yet.

')+'
'+ '
'; $('studentProfileModal').classList.remove('hidden'); } function closeStudentProfile(){$('studentProfileModal').classList.add('hidden');} async function deleteStudent(studentId,name){if(!studentId)return;if(!confirm('Delete '+name+' ('+studentId+')?\n\nThis permanently deletes the student and their learning history.'))return;const d=await api('delete_student',{student_id:studentId});if(!d.ok){alert(d.error||'Could not delete student.');return;}await loadTrainerData();} let homeworkQuestions=[]; let currentHomeworkDraftId=0; function renderHomeworkQuestions(){ const box=$('hwQuestions'); if(!box)return; if(!homeworkQuestions.length){box.innerHTML='
🤖Your questions will appear hereGenerate with AI or click Create Manually.
';return;} box.innerHTML=homeworkQuestions.map((q,i)=>`
Question ${i+1}
`).join(''); } function updateHomeworkQuestion(i,key,val){if(homeworkQuestions[i])homeworkQuestions[i][key]=val;} function addHomeworkQuestion(){homeworkQuestions.push({question:'',answer:'',explanation:''});renderHomeworkQuestions();setTimeout(()=>{const els=document.querySelectorAll('#hwQuestions textarea');els[els.length-3]?.focus()},20);} function removeHomeworkQuestion(i){homeworkQuestions.splice(i,1);renderHomeworkQuestions();} function moveHomeworkQuestion(i,dir){const j=i+dir;if(j<0||j>=homeworkQuestions.length)return;[homeworkQuestions[i],homeworkQuestions[j]]=[homeworkQuestions[j],homeworkQuestions[i]];renderHomeworkQuestions();} function startManualHomework(){homeworkQuestions=[];for(let i=0;i<+( $('hwCount')?.value||10);i++)homeworkQuestions.push({question:'',answer:'',explanation:''});renderHomeworkQuestions();$('hwGenerateStatus').textContent='Manual mode: add your questions and answers below.';} async function generateHomework(){ const topic=$('hwTopic').value.trim(),level=$('hwLevel').value,type=$('hwType').value,count=$('hwCount').value; if(!topic){alert('Please enter a topic first.');$('hwTopic').focus();return;} $('hwGenerateStatus').textContent='Generating questions…'; const d=await api('generate_homework',{topic,level,question_type:type,count}); if(!d.ok){$('hwGenerateStatus').textContent=d.error||'Could not generate homework.';return;} homeworkQuestions=Array.isArray(d.questions)?d.questions:[]; renderHomeworkQuestions();$('hwGenerateStatus').textContent=homeworkQuestions.length+' questions generated. Review and edit before assigning.'; } function clearHomeworkBuilder(){homeworkQuestions=[];currentHomeworkDraftId=0;if($('publishHomeworkBtn'))$('publishHomeworkBtn').disabled=true;['hwTitle','hwTopic','hwInstructions'].forEach(id=>{if($(id))$(id).value='';});$('hwGenerateStatus').textContent='';renderHomeworkQuestions();} async function loadDraftHomework(id){ const d=trainerDataCache;if(!d)return;const h=(d.drafts||[]).find(x=>+x.id===+id);if(!h)return; $('hwTitle').value=h.title||'';$('hwTopic').value=h.topic||'';$('hwLevel').value=h.level||'All';$('hwStudent').value=h.target_student_id||'';$('hwType').value=h.question_type||'Mixed';$('hwInstructions').value=h.instructions||''; homeworkQuestions=Array.isArray(h.questions)?JSON.parse(JSON.stringify(h.questions)):[];currentHomeworkDraftId=Number(h.id);renderHomeworkQuestions();if($('publishHomeworkBtn'))$('publishHomeworkBtn').disabled=false;$('hwGenerateStatus').textContent='Draft loaded. Edit anything, then Save Draft to update it or Approve & Publish when ready.';$('createHomeworkCard').scrollIntoView({behavior:'smooth',block:'start'}); } async function saveHomeworkDraft(){ if(!homeworkQuestions.length){alert('Please generate or add at least one question.');return;} if(homeworkQuestions.some(q=>!String(q.question||'').trim())){alert('Please fill every question before saving.');return;} const title=$('hwTitle').value.trim(),topic=$('hwTopic').value.trim(),instructions=$('hwInstructions').value.trim(); if(!title||!topic||!instructions){alert('Please complete Title, Topic and Teacher Instructions.');return;} const payload={title,topic,level:$('hwLevel').value,target_student_id:$('hwStudent').value,question_type:$('hwType').value,instructions,questions:JSON.stringify(homeworkQuestions)}; let d; if(currentHomeworkDraftId)d=await api('update_homework_draft',{...payload,homework_id:currentHomeworkDraftId}); else d=await api('create_homework',payload); if(!d.ok){alert('Error: '+d.error);return;} currentHomeworkDraftId=Number(d.id||currentHomeworkDraftId||0);if($('publishHomeworkBtn'))$('publishHomeworkBtn').disabled=!currentHomeworkDraftId; $('hwGenerateStatus').textContent='✅ Draft saved privately. Students cannot see it until you publish it.';await loadTrainerData(); } async function publishDraftFromList(id){ if(!confirm('Approve and publish this homework? Students will be able to see it immediately.'))return; const d=await api('publish_homework',{homework_id:id});if(!d.ok){alert(d.error||'Could not publish homework.');return;}if(currentHomeworkDraftId===Number(id)){currentHomeworkDraftId=0;if($('publishHomeworkBtn'))$('publishHomeworkBtn').disabled=true;}alert('Homework approved and published.');loadTrainerData(); } async function deleteDraftHomework(id){ if(!confirm('Delete this private draft? This cannot be undone.'))return; const d=await api('delete_homework',{homework_id:id});if(!d.ok){alert(d.error||'Could not delete draft.');return;}if(currentHomeworkDraftId===Number(id))clearHomeworkBuilder();loadTrainerData(); } async function checkTargetedPractice(homeworkId){ const el=$('targeted_'+homeworkId);if(!el)return;let qs=[];try{qs=JSON.parse(el.dataset.questions||'[]')}catch(e){} const answers=qs.map((q,i)=>($('tp_'+homeworkId+'_'+i)?.value||'').trim());if(answers.some(x=>!x)){alert('Please answer all practice questions.');return;} el.innerHTML='
🤖 AI is checking your targeted practice…
'; const d=await api('mistake_practice_check',{questions:JSON.stringify(qs),answers:JSON.stringify(answers)});if(!d.ok){el.innerHTML=''+esc(d.error||'Could not check practice.')+'';return;} el.innerHTML='
'+esc(d.score)+'/100

'+esc(d.correct)+'/'+esc(d.total)+' correct. '+esc(d.feedback||'Keep practising these weak points.')+'

'+d.results.map((x,i)=>'
'+(i+1)+'. '+(x.correct?'✓ Correct':'✗ Review')+'
'+esc(x.question)+'
Your answer: '+esc(x.answer||'—')+''+(x.correct?'':'Better answer: '+esc(x.better_answer||qs[i].answer||'—')+'')+(x.explanation?''+esc(x.explanation)+'':'')+'
').join(''); loadStats();loadMistakes(); } async function assignHomework(){return saveHomeworkDraft();} function createHomework(){saveHomeworkDraft();} function useHomeworkTemplate(title,topic,level,instructions){ $('hwTitle').value=title;$('hwTopic').value=topic;$('hwLevel').value=level;$('hwInstructions').value=instructions; $('createHomeworkCard').scrollIntoView({behavior:'smooth',block:'start'}); $('hwTitle').focus(); } function scrollToHomeworkResults(){ $('trainerHomework')?.closest('.card')?.scrollIntoView({behavior:'smooth',block:'start'}); } function useHomeworkTemplate(title,topic,level,instructions){$('hwTitle').value=title;$('hwTopic').value=topic;$('hwLevel').value=level;$('hwInstructions').value=instructions;$('hwType').value=topic.toLowerCase().includes('interview')?'Sentence making':(topic.toLowerCase().includes('past')||topic.toLowerCase().includes('was')?'Hindi to English':'Mixed');startManualHomework();$('createHomeworkCard').scrollIntoView({behavior:'smooth',block:'start'});$('hwTitle').focus();} function scrollToHomeworkResults(){$('trainerHomework')?.closest('.card')?.scrollIntoView({behavior:'smooth',block:'start'});} async function seedHomework(){const d=await api('seed_homework');alert(d.ok?'Starter homework added.':'Error: '+d.error);if(d.ok)loadTrainerData();} setInterval(()=>{if(state.user)api('log_time',{module:document.querySelector('.panel.active')?.id||'practice',seconds:60}).catch(()=>{});},60000); window.SERVER_USER = null; document.addEventListener('DOMContentLoaded',()=>{ // Ensure AI Mock Interview is visible in the main navigation and opens its existing panel. const mainNav=document.querySelector('.nav'); if(mainNav && !Array.from(mainNav.querySelectorAll('button')).some(b => (b.getAttribute('onclick')||'').includes("openPanel('mockInterview'"))){ const mockBtn=document.createElement('button'); mockBtn.type='button'; mockBtn.textContent='🎤 AI Mock Interview'; mockBtn.addEventListener('click',function(){ if(typeof window.openPanel==='function') window.openPanel('mockInterview',mockBtn); }); const worldBtn=Array.from(mainNav.querySelectorAll('button')).find(b => (b.getAttribute('onclick')||'').includes("openPanel('worldNews'")); if(worldBtn && worldBtn.nextSibling) mainNav.insertBefore(mockBtn,worldBtn.nextSibling); else mainNav.appendChild(mockBtn); } // Today's Practice cards use delegated events instead of inline onclick handlers. // This keeps the cards reliable even when a hosting/security layer blocks inline JS. document.querySelectorAll('[data-practice-panel]').forEach(function(card){ card.addEventListener('click',function(e){ e.preventDefault(); var target=this.getAttribute('data-practice-panel'); if(target && document.getElementById(target) && typeof window.openPanel==='function'){ window.openPanel(target, null); } }); }); if(window.SERVER_USER && !window.SERVER_TRAINER){ state.user=window.SERVER_USER; applyAccountVisibility(); showApp(); } if($('voiceLevelLabel')) $('voiceLevelLabel').textContent=state.user?.level||'Student'; newVoiceChallenge(); if($('robotMessages') && state.user){ selectRobot(document.querySelector('.robot-card.active')); } });