'use client' import { useEffect, useState, useCallback } from 'react' import { useRouter } from 'next/navigation' import { Sidebar } from '@/components/Sidebar' import { useStore } from '@/lib/store' import { api, PriceAlert } from '@/lib/api' import { User, Bell, CreditCard, Shield, ChevronRight, Loader2, Check, AlertCircle, Trash2, ExternalLink, Crown, Zap, Key, TrendingUp, X, Settings, ArrowUp, ArrowDown, Sparkles, Clock, Target, BarChart3, MessageSquare, Database, Menu, Eye, Gavel, Tag, Coins, LogOut, Briefcase } from 'lucide-react' import Link from 'next/link' import Image from 'next/image' import clsx from 'clsx' type SettingsTab = 'profile' | 'notifications' | 'billing' | 'security' // Plan definitions const PLANS = [ { id: 'scout', name: 'Scout', icon: Zap, price: 0, period: 'forever', description: 'Perfect for getting started', features: [ { icon: Target, text: '5 Watchlist Domains' }, { icon: Clock, text: 'Daily Checks' }, { icon: Bell, text: '2 Sniper Alerts' }, { icon: BarChart3, text: 'Basic Market Data' }, ], }, { id: 'trader', name: 'Trader', icon: TrendingUp, price: 9, period: '/month', description: 'For serious investors', badge: 'Popular', features: [ { icon: Target, text: '50 Watchlist Domains' }, { icon: Clock, text: 'Hourly Checks' }, { icon: Bell, text: '10 Sniper Alerts' }, { icon: Sparkles, text: 'Domain Valuation' }, { icon: Database, text: '25 Portfolio' }, { icon: MessageSquare, text: '5 Listings' }, ], }, { id: 'tycoon', name: 'Tycoon', icon: Crown, price: 29, period: '/month', description: 'Maximum power', badge: 'Full Power', features: [ { icon: Target, text: '500 Domains' }, { icon: Clock, text: '10-Min Checks' }, { icon: Bell, text: '50 Sniper Alerts' }, { icon: Sparkles, text: 'Full SEO' }, { icon: Database, text: 'Unlimited Portfolio' }, { icon: MessageSquare, text: '50 Featured' }, ], }, ] export default function SettingsPage() { const router = useRouter() const { user, isAuthenticated, isLoading, checkAuth, subscription, logout } = useStore() const [activeTab, setActiveTab] = useState('profile') const [saving, setSaving] = useState(false) const [success, setSuccess] = useState(null) const [error, setError] = useState(null) const [menuOpen, setMenuOpen] = useState(false) const [changingPlan, setChangingPlan] = useState(null) const [profileForm, setProfileForm] = useState({ name: '', email: '' }) const [notificationPrefs, setNotificationPrefs] = useState({ domain_availability: true, price_alerts: true, weekly_digest: false, }) const [savingNotifications, setSavingNotifications] = useState(false) const [priceAlerts, setPriceAlerts] = useState([]) const [loadingAlerts, setLoadingAlerts] = useState(false) const [deletingAlertId, setDeletingAlertId] = useState(null) useEffect(() => { checkAuth() }, [checkAuth]) useEffect(() => { if (!isLoading && !isAuthenticated) router.push('/login') }, [isLoading, isAuthenticated, router]) useEffect(() => { if (user) setProfileForm({ name: user.name || '', email: user.email || '' }) }, [user]) useEffect(() => { if (isAuthenticated && activeTab === 'notifications') loadPriceAlerts() }, [isAuthenticated, activeTab]) useEffect(() => { const saved = localStorage.getItem('notification_prefs') if (saved) try { setNotificationPrefs(JSON.parse(saved)) } catch {} }, []) // Handle URL params for upgrade success/cancel useEffect(() => { const params = new URLSearchParams(window.location.search) const upgraded = params.get('upgraded') const cancelled = params.get('cancelled') if (upgraded) { setSuccess(`Upgrade complete: ${upgraded.charAt(0).toUpperCase() + upgraded.slice(1)}`) setActiveTab('billing') window.history.replaceState({}, '', '/terminal/settings') checkAuth() } if (cancelled) { setError('Checkout cancelled.') setActiveTab('billing') window.history.replaceState({}, '', '/terminal/settings') } }, [checkAuth]) const loadPriceAlerts = async () => { setLoadingAlerts(true) try { setPriceAlerts(await api.getPriceAlerts()) } catch {} finally { setLoadingAlerts(false) } } const handleSaveProfile = async (e: React.FormEvent) => { e.preventDefault() setSaving(true); setError(null); setSuccess(null) try { await api.updateMe({ name: profileForm.name || undefined }) await checkAuth() setSuccess('Profile updated') } catch (err) { setError(err instanceof Error ? err.message : 'Failed') } finally { setSaving(false) } } const handleSaveNotifications = async () => { setSavingNotifications(true); setError(null); setSuccess(null) try { localStorage.setItem('notification_prefs', JSON.stringify(notificationPrefs)); setSuccess('Saved') } catch (err) { setError('Failed') } finally { setSavingNotifications(false) } } const handleDeletePriceAlert = async (tld: string, alertId: number) => { setDeletingAlertId(alertId) try { await api.deletePriceAlert(tld); setPriceAlerts(prev => prev.filter(a => a.id !== alertId)) } catch (err) { setError('Failed') } finally { setDeletingAlertId(null) } } const handleOpenBillingPortal = async () => { try { const { portal_url } = await api.createPortalSession(); window.location.href = portal_url } catch (err) { setError('Failed to open portal') } } const handlePlanChange = async (planId: string) => { setChangingPlan(planId); setError(null) try { if (planId === 'scout') { await api.cancelSubscription() setSuccess('Downgraded to Scout') await checkAuth() } else { const { checkout_url } = await api.createCheckoutSession( planId, `${window.location.origin}/terminal/settings?upgraded=${planId}`, `${window.location.origin}/terminal/settings?cancelled=true` ) window.location.href = checkout_url } } catch (err) { setError(err instanceof Error ? err.message : 'Failed') } finally { setChangingPlan(null) } } if (isLoading) { return (
) } if (!isAuthenticated || !user) return null const tierName = subscription?.tier_name || subscription?.tier || 'Scout' const isProOrHigher = ['Trader', 'Tycoon'].includes(tierName) const TierIcon = tierName === 'Tycoon' ? Crown : tierName === 'Trader' ? TrendingUp : Zap const tabs = [ { id: 'profile' as const, label: 'Profile', icon: User }, { id: 'notifications' as const, label: 'Alerts', icon: Bell }, { id: 'billing' as const, label: 'Plans', icon: CreditCard }, { id: 'security' as const, label: 'Security', icon: Shield }, ] // Mobile Nav - same as Intel page const mobileNavItems = [ { href: '/terminal/radar', label: 'Radar', icon: Target, active: false }, { href: '/terminal/market', label: 'Market', icon: Gavel, active: false }, { href: '/terminal/watchlist', label: 'Watch', icon: Eye, active: false }, { href: '/terminal/intel', label: 'Intel', icon: TrendingUp, active: false }, ] const drawerNavSections = [ { title: 'Discover', items: [ { href: '/terminal/radar', label: 'Radar', icon: Target }, { href: '/terminal/market', label: 'Market', icon: Gavel }, { href: '/terminal/intel', label: 'Intel', icon: TrendingUp }, ]}, { title: 'Manage', items: [ { href: '/terminal/watchlist', label: 'Watchlist', icon: Eye }, { href: '/terminal/portfolio', label: 'Portfolio', icon: Briefcase }, { href: '/terminal/sniper', label: 'Sniper', icon: Target }, ]}, { title: 'Monetize', items: [ { href: '/terminal/yield', label: 'Yield', icon: Coins, isNew: true }, { href: '/terminal/listing', label: 'For Sale', icon: Tag }, ]}, ] return (
{/* Desktop Sidebar */}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* MOBILE HEADER */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Top Row */}
Settings
{tierName}
{/* Stats Grid */}
{subscription?.domains_used || 0}
Domains
{subscription?.check_frequency === 'realtime' ? '10m' : subscription?.check_frequency === 'hourly' ? '1h' : '24h'}
Interval
{subscription?.status || 'active'}
Status
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* DESKTOP HEADER */} {/* ═══════════════════════════════════════════════════════════════════════ */}
Account

Settings

Manage your account, subscription, alerts, and security preferences.

{/* Messages */} {(error || success) && (
{error && (

{error}

)} {success && (

{success}

)}
)} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* TABS */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{tabs.map((tab) => ( ))}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* CONTENT */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Profile Tab */} {activeTab === 'profile' && (
Profile Information
setProfileForm({ ...profileForm, name: e.target.value })} className="w-full px-4 py-3 bg-white/[0.02] border border-white/[0.08] text-white placeholder:text-white/20 outline-none focus:border-accent/50" />
)} {/* Notifications Tab */} {activeTab === 'notifications' && (
Email Preferences
{[ { key: 'domain_availability', label: 'Domain Available', desc: 'When domains become available' }, { key: 'price_alerts', label: 'Price Changes', desc: 'TLD price updates' }, { key: 'weekly_digest', label: 'Weekly Digest', desc: 'Weekly summary' }, ].map((item) => ( ))}
)} {/* Billing Tab */} {activeTab === 'billing' && (
{/* Plan Cards */}
{PLANS.map((plan) => { const isCurrent = tierName.toLowerCase() === plan.id const isUpgrade = (tierName === 'Scout' && plan.id !== 'scout') || (tierName === 'Trader' && plan.id === 'tycoon') const isDowngrade = (tierName === 'Tycoon' && plan.id !== 'tycoon') || (tierName === 'Trader' && plan.id === 'scout') return (
{plan.badge && (
{plan.badge}
)} {isCurrent && (
Current
)}
{plan.name}
{plan.price === 0 ? ( Free ) : ( <> ${plan.price} {plan.period} )}
    {plan.features.slice(0, 4).map((f, i) => (
  • {f.text}
  • ))}
{isCurrent ? (
Active
) : isUpgrade ? ( ) : isDowngrade ? ( ) : null}
) })}
{/* Billing Portal Link */} {isProOrHigher && ( )}
)} {/* Security Tab */} {activeTab === 'security' && (
Password

Change or reset your password

Change Password
Account Status

Email Verified

Your email is verified

2FA

Coming soon

Soon

Danger Zone

Permanently delete your account

)}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* MOBILE BOTTOM NAV */} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* MOBILE DRAWER */} {/* ═══════════════════════════════════════════════════════════════════════ */} {menuOpen && (
setMenuOpen(false)} />
Pounce

Pounce

Terminal v1.0

{drawerNavSections.map((section) => (
{section.title}
{section.items.map((item: any) => ( setMenuOpen(false)} className="flex items-center gap-3 px-4 py-2.5 text-white/60 active:text-white active:bg-white/[0.03] transition-colors border-l-2 border-transparent active:border-accent" > {item.label} {item.isNew && ( NEW )} ))}
))}
setMenuOpen(false)} className="flex items-center gap-3 py-2.5 text-accent transition-colors" > Settings {user?.is_admin && ( setMenuOpen(false)} className="flex items-center gap-3 py-2.5 text-amber-500/70 active:text-amber-400 transition-colors" > Admin )}

{user?.name || user?.email?.split('@')[0] || 'User'}

{tierName}

{tierName === 'Scout' && ( setMenuOpen(false)} className="flex items-center justify-center gap-2 w-full py-2.5 bg-accent text-black text-xs font-bold uppercase tracking-wider active:scale-[0.98] transition-all mb-2" > Upgrade )}
)}
) }