'use client'; import { useEffect, useRef, useState } from 'react'; import { usePathname, useRouter } from 'next/navigation'; import { motion, AnimatePresence } from 'framer-motion'; import { ChevronDown, LogOut, Settings, UserCircle, CreditCard, Twitter, Linkedin, Github, X, } from 'lucide-react'; import { getAuth, signOut } from 'firebase/auth'; import { app, db } from '@/lib/firebase'; import { useAuth } from '@/contexts/AuthContext'; import toast from 'react-hot-toast'; import { doc, onSnapshot } from 'firebase/firestore'; export default function DashboardLayout({ children }: { children: React.ReactNode }) { const { user } = useAuth(); const router = useRouter(); const pathname = usePathname(); const auth = getAuth(app); const [isOpen, setIsOpen] = useState(false); const [credits, setCredits] = useState(null); const [showCreditsPulse, setShowCreditsPulse] = useState(false); const [isQuickBuyOpen, setIsQuickBuyOpen] = useState(false); const dropdownRef = useRef(null); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); useEffect(() => { if (!user) { setCredits(null); return; } const docRef = doc(db, 'users', user.uid); const unsubscribe = onSnapshot( docRef, (snapshot) => { const balance = snapshot.data()?.creditBalance ?? 0; setCredits((prev) => { if (prev !== null && prev !== balance) { setShowCreditsPulse(true); window.setTimeout(() => setShowCreditsPulse(false), 900); } return balance; }); }, (error) => { console.error('Failed to subscribe to credits', error); setCredits(0); } ); return () => unsubscribe(); }, [user]); const handleSignOut = async () => { try { await signOut(auth); toast.success('Signed out.'); router.push('/auth'); } catch (error) { console.error('Sign out failed', error); toast.error('Unable to sign out. Please try again.'); } }; const initial = user?.email?.[0]?.toUpperCase() ?? '?'; const pricingTiers = [ { label: '10 Credits', price: '€10', value: 10 }, { label: '50 Credits', price: '€45', value: 50 }, { label: '100 Credits', price: '€85', value: 100 }, ]; const handleQuickBuy = async (value: number, price: string) => { if (!user) { toast.error('Please sign in to purchase credits.'); return; } try { const response = await fetch('/api/stripe/checkout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ credits: value, amount: Number(price.replace('€', '')), userId: user.uid, }), }); if (!response.ok) { throw new Error('Checkout failed'); } const data = await response.json(); if (data.url) { window.location.href = data.url; } else { throw new Error('Missing checkout URL'); } } catch (error) { console.error('Quick buy failed', error); toast.error('Unable to start checkout.'); } }; return (
Dashboard
setIsQuickBuyOpen(true)} className="relative rounded-full bg-[#8b5cf6]/20 border border-[#8b5cf6]/40 px-3 py-1.5 text-xs font-semibold text-white hover:bg-[#8b5cf6]/30 transition" animate={showCreditsPulse ? { scale: [1, 1.08, 1] } : { scale: 1 }} transition={{ duration: 0.6 }} > 💎 {credits ?? '—'} Credits {showCreditsPulse && ( )}
{isOpen && (
{initial}

Account

{user?.email ?? 'Unknown user'}

Credits: {credits ?? '—'}
)}
{children}
{isQuickBuyOpen && ( setIsQuickBuyOpen(false)} > event.stopPropagation()} >

Quick Buy Credits

Choose a package to top up.

{pricingTiers.map((tier) => ( ))}
)}
); }