"use client"; import React, { useState } from 'react'; import { doc, setDoc, getDoc, writeBatch } from "firebase/firestore"; import { useAuth } from '@/contexts/auth-context'; import { useFirebase } from '@/contexts/firebase-context'; import { useSettings } from '@/contexts/settings-context'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Logo } from './logo'; import { Sparkles, Languages, HelpCircle, ArrowRight, ArrowLeft } from 'lucide-react'; import words from 'mnemonic-words'; import { cn } from '@/lib/utils'; import type { Language } from '@/lib/types'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogTrigger } from '@/components/ui/dialog'; import { Separator } from './ui/separator'; import { Progress } from './ui/progress'; const InfoBubble = ({ text, emoji }: { text: string, emoji: string }) => (
{emoji} {text}
); const TOTAL_STEPS = 3; const StepIndicator = ({ current, total, t }: { current: number, total: number, t: (key: string) => string }) => (

{t('step')} {current} / {total}

); export const Onboarding = () => { const { setAuthStatus, auth, handleAuthenticatedUser } = useAuth(); const { db } = useFirebase(); const { addToast, t, language, setLanguage, playSound } = useSettings(); const [displayName, setDisplayName] = useState(''); const [publicId, setPublicId] = useState(''); const [recoveryId, setRecoveryId] = useState(''); const [step, setStep] = useState(1); const [isLoading, setIsLoading] = useState(false); const handleNextStep = () => { playSound('touch'); if (step === 1 && !displayName.trim()) { addToast(t('nameCannotBeEmpty')); return; } if (step === 2 && publicId.trim().length < 4) { addToast(t('publicIdMinLength')); return; } setStep(prev => prev + 1); } const handlePrevStep = () => { playSound('touch'); setStep(prev => prev - 1); } const handleCreateProfile = async () => { setIsLoading(true); playSound('touch'); const trimmedDisplayName = displayName.trim(); const trimmedPublicId = publicId.trim().toLowerCase(); const trimmedRecoveryId = recoveryId.trim(); if (!trimmedRecoveryId || trimmedRecoveryId.length < 8) { addToast("Recovery ID must be at least 8 characters."); setIsLoading(false); return; } try { const publicIdRef = doc(db, 'publicIds', trimmedPublicId); const recoveryIdRef = doc(db, 'recovery', trimmedRecoveryId); const [publicIdSnap, recoveryIdSnap] = await Promise.all([ getDoc(publicIdRef), getDoc(recoveryIdRef) ]); if (publicIdSnap.exists()) { addToast("This Public ID is already taken. Please choose another."); setStep(2); // Go back to public ID step setIsLoading(false); return; } if (recoveryIdSnap.exists()) { addToast("This Recovery ID is already in use. Please choose a more unique one."); setIsLoading(false); return; } const user = auth.currentUser; if (!user) throw new Error("User not signed in."); const androidId = localStorage.getItem('android_id'); const profile = { uid: user.uid, displayName: trimmedDisplayName, publicId: trimmedPublicId, photoURL: `https://api.dicebear.com/8.x/initials/svg?seed=${trimmedDisplayName}`, ...(androidId && { androidId }), }; const batch = writeBatch(db); batch.set(doc(db, 'users', user.uid), profile); batch.set(doc(db, 'publicIds', trimmedPublicId), { uid: user.uid }); batch.set(recoveryIdRef, { uid: user.uid }); await batch.commit(); setStep(TOTAL_STEPS + 1); // Go to confirmation step } catch (error: any) { console.error("Profile creation error:", error); addToast(`Error: ${error.message}`); } finally { setIsLoading(false); } }; const handleFinishOnboarding = () => { playSound('touch'); if (auth.currentUser) { handleAuthenticatedUser(auth.currentUser); } else { setAuthStatus('loading'); } } const generateRandomRecoveryId = () => { playSound('touch'); const randomWords = []; for (let i = 0; i < 4; i++) { const randomIndex = Math.floor(Math.random() * words.length); randomWords.push(words[randomIndex]); } setRecoveryId(randomWords.join('-')); }; const handleLanguageChange = (lang: Language) => { playSound('touch'); setLanguage(lang); }; if (step > TOTAL_STEPS) { return (
{t('recoveryTitle')} {t('recoveryDescription')} {t('yourRecoveryId')} {t('youChose')}: {recoveryId}. {t('keepItSafe')}!
); } const renderStepContent = () => { switch (step) { case 1: return (
setDisplayName(e.target.value)} placeholder={t('displayNameLabel')} autoFocus/>

{t('displayNameHint')}

); case 2: return (
setPublicId(e.target.value.replace(/[^a-z0-9-]/gi, '').toLowerCase())} placeholder={t('publicIdLabel')} autoFocus/>

{t('publicIdHint')}

); case 3: return (
setRecoveryId(e.target.value)} placeholder={t('recoveryIdPlaceholder')} className="flex-1" autoFocus/>

{t('recoveryIdHint')}

); default: return null; } } return (
{t('createProfileTitle')} {t('howLoginWorksTitle')}

{t('howLoginWorksP1')}

  • {t('howLoginWorksL1Title')} {t('howLoginWorksL1Text')}
  • {t('howLoginWorksL2Title')} {t('howLoginWorksL2Text')}

{t('howLoginWorksP2')}

{t('onboardingDescription')}
{renderStepContent()}
{step < TOTAL_STEPS ? ( ) : ( )}

{t('haveAnAccount')}{' '}

); };