import { useState } from 'react'; import { BookOpen, Flame, Link2, Star, Trophy, UserPlus } from 'lucide-react'; import { api, ApiError, type FamilyLink } from '@/api'; import { useAsync } from '@/lib/useAsync'; import { useToast } from '@/components/Toast'; import { InlineError, LoadingState, PrimaryButton, Screen, ScreenBody, ScreenHeader } from '@/components/ui'; import { friendlyError } from '@/lib/errors'; import { digitsOnly, formatJalaliDate, toFa } from '@/lib/format'; /** * بخشِ والدین. والد با شماره‌ی فرزند دعوت می‌سازد و یک کد می‌گیرد؛ فرزند * (با همان شماره وارد شده) کد را اینجا وارد می‌کند. بعد از اتصال، والد * گزارشِ هفتگی را می‌بیند. */ export function FamilyScreen() { const link = useAsync( () => api.family.link().catch((err) => { if (err instanceof ApiError && err.status === 404) return null; throw err; }), [], ); return ( {link.loading ? ( ) : ( <> {link.data && } {link.data?.status === 'accepted' && } )} ); } function LinkStatus({ link }: { link: FamilyLink }) { const accepted = link.status === 'accepted'; return (

{accepted ? <>به {link.childName || 'فرزندت'} وصلی. : 'دعوت فرستاده شده و منتظرِ تأییدِ فرزندته.'}

); } function WeeklyReport() { const report = useAsync(() => api.family.weeklyReport(), []); if (report.loading) return
; if (!report.data) return null; const r = report.data; return (

گزارشِ این هفته (از {formatJalaliDate(r.weekStart)})

{[ { icon: Star, label: 'امتیاز', value: r.xpEarned }, { icon: BookOpen, label: 'درسِ تمام‌شده', value: r.lessonsCompleted }, { icon: Trophy, label: 'جزیره‌ی تمام‌شده', value: r.islandsCompleted }, { icon: Flame, label: 'زنجیره (روز)', value: r.currentStreak }, ].map(({ icon: Icon, label, value }) => (
{label} {toFa(value)}
))}
); } function InviteChild({ onDone }: { onDone: () => void }) { const [phone, setPhone] = useState(''); const [code, setCode] = useState(null); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); async function invite() { setBusy(true); setError(''); try { const r = await api.family.invite(phone); setCode(r.inviteCode); onDone(); } catch (err) { setError(friendlyError(err)); } finally { setBusy(false); } } return (

من والدم

شماره‌ای که فرزندت باهاش وارد تدریسینو شده رو بنویس.

{code ? (

این کد رو به فرزندت بده تا تو بخشِ والدینِ حسابِ خودش وارد کنه:

{code}

) : ( <> setPhone(digitsOnly(e.target.value, 11))} placeholder="۰۹۱۲۳۴۵۶۷۸۹" dir="ltr" inputMode="numeric" className="mb-3 w-full rounded-2xl border-2 border-line px-4 py-3 text-left outline-none focus:border-orange" /> {error &&
{error}
} void invite()}> ساختِ کدِ دعوت )}
); } function AcceptInvite({ onDone }: { onDone: () => void }) { const toast = useToast(); const [code, setCode] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(''); async function accept() { setBusy(true); setError(''); try { await api.family.accept(code.trim()); toast('به والدت وصل شدی', 'success'); setCode(''); onDone(); } catch (err) { setError(friendlyError(err)); } finally { setBusy(false); } } return (

من دانش‌آموزم

اگه پدر یا مادرت کدِ دعوت بهت داده، اینجا واردش کن.

setCode(e.target.value.slice(0, 32))} placeholder="کدِ دعوت" dir="ltr" className="mb-3 w-full rounded-2xl border-2 border-line px-4 py-3 text-center font-bold tracking-widest outline-none focus:border-orange" /> {error &&
{error}
} void accept()}> وصل شو
); }