// Onboarding.jsx — setup: language → goal → (due date | cycle) → baby info (function () { const { useState } = React; const { t, calculateDueFromLMP, GOALS } = window.AliaData; const localISO = window.AliaData.localISO || (d => d.toISOString().split('T')[0]); const todayISO = window.AliaData.todayISO || (() => localISO(new Date())); function Onboarding({ onComplete, initialLang }) { const [step, setStep] = useState(0); const [lang, setLang] = useState(initialLang || localStorage.getItem('alia_lang') || 'ru'); const [goal, setGoal] = useState('pregnancy'); const [mode, setMode] = useState('pdr'); const [dateVal, setDateVal] = useState(''); const [lastPeriod, setLastPeriod] = useState(''); const [cycleLen, setCycleLen] = useState(28); const [periodLen, setPeriodLen] = useState(5); const [error, setError] = useState(''); const [babyName, setBabyName] = useState(''); const [babyGender, setBabyGender] = useState('unknown'); const [savedDue, setSavedDue] = useState(''); const ru = lang === 'ru'; const isPreg = goal === 'pregnancy'; const today = todayISO(); const maxPDR = localISO(new Date(Date.now() + 300 * 86400000)); const minPDR = localISO(new Date(Date.now() - 20 * 86400000)); const minLMP = localISO(new Date(Date.now() - 300 * 86400000)); // динамический список шагов в зависимости от цели const steps = isPreg ? ['lang','goal','date','baby'] : ['lang','goal','cycle']; const cur = steps[step]; function finish(skipBaby) { const goalDef = GOALS.find(g => g.id === goal) || GOALS[0]; onComplete({ lang, goal, mode: goalDef.mode, due_date: isPreg ? savedDue : '', baby_name: skipBaby ? '' : babyName.trim(), baby_gender: skipBaby ? 'unknown' : babyGender, last_period: isPreg ? '' : lastPeriod, cycle_length: cycleLen, period_length: periodLen, }); } function handleNext() { setError(''); if (cur === 'lang' || cur === 'goal') { setStep(step + 1); return; } if (cur === 'date') { if (!dateVal) { setError(ru ? 'Укажите дату' : 'Please enter a date'); return; } setSavedDue(mode === 'lmp' ? calculateDueFromLMP(dateVal) : dateVal); setStep(step + 1); return; } if (cur === 'cycle') { if (!lastPeriod) { setError(ru ? 'Укажите дату' : 'Please enter a date'); return; } finish(true); return; } if (cur === 'baby') { finish(false); } } const GENDERS = [ { id:'unknown', ru:'Пока не знаем', en:"Don't know", emoji:'👶' }, { id:'boy', ru:'Мальчик', en:'Boy', emoji:'💙' }, { id:'girl', ru:'Девочка', en:'Girl', emoji:'💗' }, ]; const s = { wrap: { display:'flex', flexDirection:'column', minHeight:'100dvh', background:'var(--bg)', overflowY:'auto' }, top: { flex:1, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', padding:'32px 22px', paddingTop:'calc(32px + env(safe-area-inset-top))', paddingBottom:'32px' }, logo: { fontSize:52, marginBottom:10 }, appName: { fontSize:34, fontWeight:900, color:'var(--primary)', letterSpacing:'-0.5px', marginBottom:6 }, tagline: { fontSize:15, color:'var(--text-2)', textAlign:'center', lineHeight:1.55, marginBottom:36, maxWidth:280 }, card: { background:'var(--bg-card)', borderRadius:24, padding:'26px 22px', width:'100%', maxWidth:380, boxShadow:'0 4px 24px var(--shadow)' }, cardTitle: { fontSize:20, fontWeight:800, color:'var(--text)', marginBottom:18 }, langRow: { display:'flex', gap:12 }, langBtn: (a) => ({ flex:1, padding:'14px 0', borderRadius:16, border:'2px solid', borderColor: a ? 'var(--primary)' : 'var(--border)', background: a ? 'var(--primary-light)' : 'var(--bg)', color: a ? 'var(--primary)' : 'var(--text-2)', fontSize:18, fontWeight:700, cursor:'pointer', fontFamily:'Nunito,sans-serif', transition:'all .2s' }), goalBtn: (a) => ({ display:'flex', alignItems:'center', gap:12, width:'100%', padding:'15px 16px', borderRadius:16, border:'2px solid', marginBottom:10, borderColor: a ? 'var(--primary)' : 'var(--border)', background: a ? 'var(--primary-light)' : 'var(--bg)', color: a ? 'var(--primary)' : 'var(--text)', fontSize:16, fontWeight:700, cursor:'pointer', fontFamily:'Nunito,sans-serif', textAlign:'left', transition:'all .2s' }), modeRow: { display:'flex', gap:8, marginBottom:18 }, modeBtn: (a) => ({ flex:1, padding:'11px 8px', borderRadius:13, border:'2px solid', borderColor: a ? 'var(--primary)' : 'var(--border)', background: a ? 'var(--primary-light)' : 'var(--bg)', color: a ? 'var(--primary)' : 'var(--text-2)', fontSize:13, fontWeight:700, cursor:'pointer', fontFamily:'Nunito,sans-serif', transition:'all .2s' }), label: { fontSize:12, fontWeight:700, color:'var(--text-2)', letterSpacing:'0.4px', textTransform:'uppercase', marginBottom:8, display:'block' }, input: { width:'100%', padding:'14px 15px', borderRadius:13, border:'2px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:16, fontFamily:'Nunito,sans-serif', outline:'none', boxSizing:'border-box' }, row2: { display:'flex', gap:10 }, nameHint: { fontSize:12, color:'var(--text-2)', marginTop:6, fontStyle:'italic' }, errTxt: { fontSize:13, color:'#E05070', marginTop:8, fontWeight:700 }, genderRow: { display:'flex', gap:10, marginTop:6 }, genderBtn: (a) => ({ flex:1, padding:'13px 6px', borderRadius:15, border:'2px solid', borderColor: a ? 'var(--primary)' : 'var(--border)', background: a ? 'var(--primary-light)' : 'var(--bg)', color: a ? 'var(--primary)' : 'var(--text-2)', fontSize:11, fontWeight:700, cursor:'pointer', fontFamily:'Nunito,sans-serif', display:'flex', flexDirection:'column', alignItems:'center', gap:6, transition:'all .2s' }), actions: { display:'flex', gap:10, marginTop:22 }, btnPrimary: { flex:1, padding:'15px 0', borderRadius:15, border:'none', background:'var(--primary)', color:'#fff', fontSize:16, fontWeight:800, cursor:'pointer', fontFamily:'Nunito,sans-serif', boxShadow:'0 4px 16px var(--shadow)' }, btnBack: { padding:'15px 18px', borderRadius:15, border:'2px solid var(--border)', background:'transparent', color:'var(--text-2)', fontSize:15, fontWeight:700, cursor:'pointer', fontFamily:'Nunito,sans-serif' }, btnSkip: { flex:1, padding:'15px 0', borderRadius:15, border:'none', background:'var(--bg)', color:'var(--text-2)', fontSize:14, fontWeight:700, cursor:'pointer', fontFamily:'Nunito,sans-serif' }, dots: { display:'flex', gap:8, justifyContent:'center', marginTop:22 }, dot: (a) => ({ width:8, height:8, borderRadius:4, background: a ? 'var(--primary)' : 'var(--border)', transition:'all .3s' }), }; return (