/* ── LIGHT MEMBERSHIP GATE ── Free preview → simple signup (name + email + offers opt-in). No password — this is a lead-capture gate, not the full auth layer. window.MemberGate — wrap a mode; locks after the free allowance Storage: tfe_member_v1 (current member), tfe_leads_v1 (all signups on this device) */ const MEMBER_KEY = 'tfe_member_v1'; const LEADS_KEY = 'tfe_leads_v1'; const FREE_PRACTICE_ANSWERS = 12; // free scored answers (practice + lessons) /* Speaking is ALWAYS free — never gated. */ function loadMember() { try { const m = JSON.parse(localStorage.getItem(MEMBER_KEY)); if (m && m.email) return m; } catch {} return null; } function saveMember(m) { localStorage.setItem(MEMBER_KEY, JSON.stringify(m)); try { const leads = JSON.parse(localStorage.getItem(LEADS_KEY)) || []; if (!leads.some(l => l.email === m.email)) { leads.push(m); localStorage.setItem(LEADS_KEY, JSON.stringify(leads)); } } catch {} } function SignupCard({ t, onDone, context }) { const [name, setName] = React.useState(''); const [email, setEmail] = React.useState(''); const [offers, setOffers] = React.useState(true); const [err, setErr] = React.useState(null); const [joined, setJoined] = React.useState(null); const submit = () => { if (!name.trim()) { setErr(t('Please enter your name.','يرجى إدخال اسمك.','Lütfen adınızı girin.')); return; } const em = email.trim().toLowerCase(); if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(em)) { setErr(t('Please enter a valid email.','يرجى إدخال بريد إلكتروني صحيح.','Lütfen geçerli bir e-posta girin.')); return; } const m = { name: name.trim(), email: em, offers, at: Date.now() }; saveMember(m); setJoined(m); }; if (joined) return (
🎁
{t('Welcome, ','أهلاً بك، ','Hoş geldin, ')}{joined.name}!
{t( 'Your welcome gift is ready: our complete guide to the English tenses — all 8 tenses explained with examples and a cheat sheet. We’ll also send it to your email.', 'هدية ترحيبية جاهزة لك: دليلنا الكامل لأزمنة الإنجليزية — الأزمنة الثمانية مشروحة بأمثلة وورقة مرجعية. وسنرسله أيضاً إلى بريدك.', 'Hoş geldin hediyen hazır: İngilizce zamanların tam rehberi — 8 zaman, örnekler ve kopya kâğıdıyla. E-postana da göndereceğiz.' )}
📘 {t('Open my welcome gift','افتح هديتي','Hediyemi aç')}
); return (
{(context && context.emoji) || '🔓'}
{(context && context.title) || t('You\u2019ve finished your free preview!','لقد أنهيت الجولة المجانية!','Ücretsiz denemeyi tamamladın!')}
{(context && context.sub) || t( 'Join free to keep practicing — unlimited exercises, your progress saved, and a welcome gift: our complete English Tenses Guide. No password needed.', 'انضم مجاناً لمواصلة التمرين — تمارين بلا حدود، حفظ تقدمك، وهدية ترحيبية: دليل الأزمنة الإنجليزية الكامل. لا حاجة لكلمة مرور.', 'Ücretsiz katıl — sınırsız alıştırma, kayıtlı ilerleme ve hoş geldin hediyesi: İngilizce Zamanlar Rehberi. Şifre gerekmez.' )}
setName(e.target.value)} placeholder="Ahmed / Ayşe / Sara" autoComplete="name" />
setEmail(e.target.value)} placeholder="you@example.com" autoComplete="email" onKeyDown={e => { if (e.key === 'Enter') submit(); }} />
{err &&
⚠ {err}
}
{t('Free forever. No spam — unsubscribe anytime.','مجاني للأبد. لا رسائل مزعجة — يمكنك إلغاء الاشتراك متى شئت.','Sonsuza dek ücretsiz. Spam yok — istediğin zaman ayrılabilirsin.')}
); } /* Wraps a practice-type mode. Pass member/onMember from the app to keep sign-in state in sync across all sections. */ function MemberGate({ state, t, kind, member: memberProp, onMember, children }) { const [memberLocal, setMemberLocal] = React.useState(loadMember); const member = memberProp !== undefined ? memberProp : memberLocal; const setMember = onMember || setMemberLocal; const answers = (state.practiceScore && state.practiceScore.total) || 0; const over = answers >= FREE_PRACTICE_ANSWERS; // Lock is decided when the mode opens — never mid-exercise const [locked] = React.useState(over); if (!member && locked) return ; const leftTxt = `${Math.max(0, FREE_PRACTICE_ANSWERS - answers)} ${t('free answers left','إجابات مجانية متبقية','ücretsiz cevap kaldı')}`; return ( {!member && (
🎁 {t('Free preview','جولة مجانية','Ücretsiz deneme')} — {leftTxt} {t('Join free for unlimited practice','انضم مجاناً لتمرين بلا حدود','Sınırsız alıştırma için ücretsiz katıl')}
)} {member &&
👋 {t('Welcome back,','مرحباً بعودتك،','Tekrar hoş geldin,')} {member.name}
} {children}
); } Object.assign(window, { MemberGate, SignupCard, loadMember, saveMember });