/* ───────────────────────────────────────────── LEARNING HOME — general dashboard · Level test (members only) · Daily learning plan + today's checklist · Learning history: streak, totals, last 14 days Exposes: window.HomeMode, window.LEARN_PLANS, window.todayKey, window.bumpHistory, window.computeStreak ───────────────────────────────────────────── */ function todayKey(d) { const dt = d || new Date(); return dt.getFullYear() + '-' + String(dt.getMonth() + 1).padStart(2, '0') + '-' + String(dt.getDate()).padStart(2, '0'); } /* Add +n to today's counter for `kind` inside a state object (immutably). */ function bumpHistory(s, kind, n) { const k = todayKey(); const h = { ...(s.history || {}) }; const day = { ...(h[k] || {}) }; day[kind] = (day[kind] || 0) + (n || 1); h[k] = day; return { ...s, history: h }; } function dayHasActivity(history, dt) { const day = history[todayKey(dt)]; return !!day && Object.values(day).some(v => v > 0); } function computeStreak(history) { if (!history) return 0; const DAY = 86400000; let d = new Date(); if (!dayHasActivity(history, d)) d = new Date(d.getTime() - DAY); // today can still be empty let streak = 0; while (dayHasActivity(history, d)) { streak++; d = new Date(d.getTime() - DAY); } return streak; } const HOME_TASKS = [ { key:'words', emoji:'📖', en:'Learn new words', ar:'تعلّم كلمات جديدة', tr:'Yeni kelimeler öğren', mode:'vocab' }, { key:'lessons', emoji:'📚', en:'Complete a lesson', ar:'أكمل درساً', tr:'Bir ders tamamla', mode:'lessons' }, { key:'reading', emoji:'📕', en:'Read a text', ar:'اقرأ نصاً', tr:'Bir metin oku', mode:'reading' }, { key:'practice', emoji:'🎯', en:'Practice answers', ar:'إجابات تمرين', tr:'Alıştırma cevapları', mode:'practice' }, { key:'speaking', emoji:'🎤', en:'Speaking session', ar:'جلسة محادثة', tr:'Konuşma oturumu', mode:'speaking' }, ]; const LEARN_PLANS = [ { id:'spark', emoji:'🌱', minutes:10, en:'Daily Spark', ar:'الشرارة اليومية', tr:'Günlük Kıvılcım', descEn:'A light habit that survives busy weeks. Words plus one short text a day.', descAr:'عادة خفيفة تصمد في الأسابيع المزدحمة. كلمات ونص قصير واحد يومياً.', descTr:'Yoğun haftalara dayanan hafif bir alışkanlık. Her gün kelimeler ve kısa bir metin.', targets:{ words:5, reading:1 } }, { id:'builder', emoji:'🔧', minutes:20, en:'Steady Builder', ar:'البنّاء المنتظم', tr:'İstikrarlı İnşacı', descEn:'One lesson, one text and real practice — solid progress, every single day.', descAr:'درس واحد ونص واحد وتمرين حقيقي — تقدّم متين كل يوم.', descTr:'Bir ders, bir metin ve gerçek alıştırma — her gün sağlam ilerleme.', targets:{ words:5, lessons:1, reading:1, practice:8 } }, { id:'throttle', emoji:'🚀', minutes:40, en:'Full Throttle', ar:'أقصى سرعة', tr:'Tam Gaz', descEn:'The complete daily circuit — including speaking out loud. Fastest results.', descAr:'الحلقة اليومية الكاملة — بما فيها التحدث بصوت عالٍ. أسرع النتائج.', descTr:'Tam günlük devre — sesli konuşma dahil. En hızlı sonuçlar.', targets:{ words:8, lessons:1, reading:2, practice:12, speaking:1 } }, ]; const PLAN_FOR_LEVEL = { A1:'spark', A2:'builder', B1:'builder', B2:'builder', C1:'throttle', C2:'throttle' }; function HomeMode({ state, setState, lang, t, member, onMember, setMode }) { const [view, setView] = React.useState('dash'); // dash | gate | test | planpick const [gateNext, setGateNext] = React.useState('test'); // where to go after joining from the gate const isAr = lang === 'ar'; const history = state.history || {}; const today = history[todayKey()] || {}; const streak = computeStreak(history); const placement = state.placement; const plan = state.plan ? LEARN_PLANS.find(p => p.id === state.plan.id) : null; const recPlanId = placement ? (PLAN_FOR_LEVEL[placement.level] || 'builder') : 'builder'; const planName = (p) => isAr ? p.ar : lang === 'tr' ? p.tr : p.en; const lvlName = (id) => { const n = (window.LEVEL_NAMES || {})[id]; return n ? (isAr ? n.ar : lang === 'tr' ? n.tr : n.en) : id; }; const dateStr = new Date().toLocaleDateString(isAr ? 'ar' : lang === 'tr' ? 'tr' : 'en-GB', { weekday:'long', day:'numeric', month:'long' }); const startTest = () => { if (member) setView('test'); else { setGateNext('test'); setView('gate'); } }; /* ── gate: sign in before the test ── */ if (view === 'gate') return (
{ onMember(m); setView(gateNext); }} />
); /* ── the placement test ── */ if (view === 'test') return ( setState(s => bumpHistory({ ...s, placement: res }, 'test'))} onClose={() => setView('dash')} /> ); /* ── plan cards (picker) ── */ const planPicker = (
{LEARN_PLANS.map(p => { const current = plan && plan.id === p.id; return (
{p.id === recPlanId && ★ {t('Recommended','موصى بها','Önerilen')}} {p.emoji}
{planName(p)}
~{p.minutes} {t('min / day','دقيقة / يوم','dk / gün')}
{isAr ? p.descAr : lang === 'tr' ? p.descTr : p.descEn}
    {HOME_TASKS.filter(task => p.targets[task.key]).map(task => (
  • {p.targets[task.key]} × {t(task.en, task.ar, task.tr).toLowerCase()}
  • ))}
); })}
); /* ── today's checklist ── */ const checklist = plan && (() => { const tasks = HOME_TASKS.filter(task => plan.targets[task.key]); const allDone = tasks.every(task => (today[task.key] || 0) >= plan.targets[task.key]); return (
{plan.emoji} {planName(plan)}
~{plan.minutes} {t('min / day','دقيقة / يوم','dk / gün')} · {t('Today\u2019s checklist','قائمة اليوم','Bugünün listesi')}
{tasks.map(task => { const target = plan.targets[task.key]; const done = Math.min(today[task.key] || 0, target); const isDone = done >= target; return (
{task.emoji} {t(task.en, task.ar, task.tr)} {done} / {target} {!isDone && }
); })} {allDone && (
🎉 {t('Perfect day — every task complete. See you tomorrow!','يوم مثالي — أنجزت كل المهام. نراك غداً!','Mükemmel gün — tüm görevler tamam. Yarın görüşürüz!')}
)}
); })(); /* ── history numbers ── */ const totLessons = (state.lessonsCompleted || []).length; const totReading = (state.readingCompleted || []).length; const totWords = (state.learned || []).length + (state.myWords || []).length; const spkMin = Math.round(((state.speaking || {}).seconds || 0) / 60); const ps = state.practiceScore || { correct:0, total:0 }; const acc = ps.total ? Math.round(ps.correct / ps.total * 100) : null; const days = []; for (let i = 13; i >= 0; i--) { const d = new Date(Date.now() - i * 86400000); const rec = history[todayKey(d)] || {}; days.push({ d, total: Object.values(rec).reduce((a, b) => a + b, 0), rec }); } const maxDay = Math.max(4, ...days.map(x => x.total)); return (
{/* WELCOME + STREAK */}
Nour welcomes you
{member ? t('Welcome back, ','مرحباً بعودتك، ','Tekrar hoş geldin, ') + member.name : t('Welcome to your learning home','أهلاً بك في صفحة تعلّمك','Öğrenme merkezine hoş geldin')}
{dateStr}{!member && <> · }
🔥
{streak}
{t('day streak','أيام متتالية','günlük seri')}
{/* LEVEL */}
📐

{t('Your level','مستواك','Seviyen')}

{placement ? (
{placement.level}
{lvlName(placement.level)}
{t('Tested on','تاريخ الاختبار:','Test tarihi:')} {new Date(placement.at).toLocaleDateString(isAr ? 'ar' : lang === 'tr' ? 'tr' : 'en-GB')}
{[['vocab','📖',t('Vocabulary','المفردات','Kelime')],['grammar','🧩',t('Grammar','القواعد','Dil bilgisi')],['reading','📕',t('Reading','القراءة','Okuma')]].map(([k, em, nm]) => { const arr = (placement.skills || {})[k] || [0,0]; const pct = arr[1] ? Math.round(arr[0] / arr[1] * 100) : 0; return (
{em} {nm} {arr[0]}/{arr[1]}
); })}
) : (
🧭
{t('Start with the level test','ابدأ باختبار المستوى','Seviye testiyle başla')}
{t('10–15 minutes, adaptive, covers vocabulary, grammar and reading. Your result picks the right lessons and plan for you.', '10–15 دقيقة، متكيّف، يغطي المفردات والقواعد والقراءة. نتيجتك تحدد الدروس والخطة المناسبة لك.', '10–15 dakika, uyarlanabilir; kelime, dil bilgisi ve okumayı kapsar. Sonucun sana doğru dersleri ve planı seçer.')}
{!member &&
🔒 {t('Members only — joining is free','للأعضاء فقط — الانضمام مجاني','Sadece üyeler — katılmak ücretsiz')}
}
)}
{/* PLAN */}
🗓

{t('Your daily plan','خطتك اليومية','Günlük planın')}

{(!plan || view === 'planpick') ? (
{view === 'planpick' && } {planPicker}
) : checklist}
{/* REMINDER */}

{t('Reminders','التذكيرات','Hatırlatıcılar')}

{window.ReminderCard && { setGateNext('dash'); setView('gate'); }} />}
{/* HISTORY */}
📊

{t('Your learning history','سجلّ تعلّمك','Öğrenme geçmişin')}

{[[totLessons, t('Lessons done','دروس منجزة','Biten ders')], [totReading, t('Texts read','نصوص مقروءة','Okunan metin')], [totWords, t('Words learned','كلمات متعلَّمة','Öğrenilen kelime')], [spkMin + 'm', t('Speaking time','وقت المحادثة','Konuşma süresi')], ...(acc !== null ? [[acc + '%', t('Practice accuracy','دقة التمرين','Alıştırma doğruluğu')]] : []), ].map(([num, lbl], i) => (
{num}
{lbl}
))}
{days.map((x, i) => { const isToday = i === days.length - 1; const parts = []; HOME_TASKS.forEach(task => { if (x.rec[task.key]) parts.push(`${x.rec[task.key]}× ${task.en.toLowerCase()}`); }); return (
{isToday ? t('Today','اليوم','Bugün') : x.d.getDate()}
); })}
{t('Last 14 days — anything you complete anywhere on this page is counted here.', 'آخر 14 يوماً — كل ما تنجزه في أي مكان بهذه الصفحة يُحتسب هنا.', 'Son 14 gün — bu sayfada tamamladığın her şey burada sayılır.')}
); } Object.assign(window, { HomeMode, LEARN_PLANS, todayKey, bumpHistory, computeStreak });