'use client' import { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' import { Header } from '@/components/Header' import { Footer } from '@/components/Footer' 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, } from 'lucide-react' import Link from 'next/link' import clsx from 'clsx' type SettingsTab = 'profile' | 'notifications' | 'billing' | 'security' export default function SettingsPage() { const router = useRouter() const { user, isAuthenticated, isLoading, checkAuth, subscription } = useStore() const [activeTab, setActiveTab] = useState('profile') const [saving, setSaving] = useState(false) const [success, setSuccess] = useState(null) const [error, setError] = useState(null) // Profile form const [profileForm, setProfileForm] = useState({ name: '', email: '', }) // Notification preferences (local state - would be persisted via API in production) const [notificationPrefs, setNotificationPrefs] = useState({ domain_availability: true, price_alerts: true, weekly_digest: false, }) const [savingNotifications, setSavingNotifications] = useState(false) // Price alerts 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]) const loadPriceAlerts = async () => { setLoadingAlerts(true) try { const alerts = await api.getPriceAlerts() setPriceAlerts(alerts) } catch (err) { console.error('Failed to load alerts:', err) } 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 }) // Update store with new user info const { checkAuth } = useStore.getState() await checkAuth() setSuccess('Profile updated successfully') } catch (err) { setError(err instanceof Error ? err.message : 'Failed to update profile') } finally { setSaving(false) } } const handleSaveNotifications = async () => { setSavingNotifications(true) setError(null) setSuccess(null) try { // Store in localStorage for now (would be API in production) localStorage.setItem('notification_prefs', JSON.stringify(notificationPrefs)) setSuccess('Notification preferences saved') } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save preferences') } finally { setSavingNotifications(false) } } // Load notification preferences from localStorage useEffect(() => { const saved = localStorage.getItem('notification_prefs') if (saved) { try { setNotificationPrefs(JSON.parse(saved)) } catch {} } }, []) 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(err instanceof Error ? err.message : 'Failed to delete alert') } finally { setDeletingAlertId(null) } } const handleOpenBillingPortal = async () => { try { const { portal_url } = await api.createPortalSession() window.location.href = portal_url } catch (err) { setError(err instanceof Error ? err.message : 'Failed to open billing portal') } } if (isLoading) { return (
) } if (!isAuthenticated || !user) { return null } const tierName = subscription?.tier_name || subscription?.tier || 'Scout' const isProOrHigher = ['Trader', 'Tycoon', 'Professional', 'Enterprise'].includes(tierName) const tabs = [ { id: 'profile' as const, label: 'Profile', icon: User }, { id: 'notifications' as const, label: 'Notifications', icon: Bell }, { id: 'billing' as const, label: 'Billing', icon: CreditCard }, { id: 'security' as const, label: 'Security', icon: Shield }, ] return (
{/* Background Effects - matching landing page */}
{/* Header */}
Settings

Your account.

Your rules. Configure everything in one place.

{/* Messages */} {error && (

{error}

)} {success && (

{success}

)}
{/* Sidebar - Horizontal scroll on mobile, vertical on desktop */}
{/* Mobile: Horizontal scroll tabs */} {/* Desktop: Vertical tabs */} {/* Plan info - hidden on mobile, shown in content area instead */}
{isProOrHigher ? : } {tierName} Plan

{subscription?.domains_used || 0} / {subscription?.domain_limit || 5} domains tracked

{!isProOrHigher && ( Upgrade )}
{/* Content */}
{/* Profile Tab */} {activeTab === 'profile' && (

Profile Information

setProfileForm({ ...profileForm, name: e.target.value })} placeholder="Your name" className="w-full px-4 py-3.5 bg-background border border-border rounded-xl text-body text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-accent/50 focus:border-accent/50 transition-all" />

Email cannot be changed

)} {/* Notifications Tab */} {activeTab === 'notifications' && (

Email Preferences

{/* Active Price Alerts */}

Active Price Alerts

{loadingAlerts ? (
) : priceAlerts.length === 0 ? (

No price alerts set

Browse TLD prices →
) : (
{priceAlerts.map((alert) => (
{alert.is_active && ( )}
.{alert.tld}

Alert on {alert.threshold_percent}% change {alert.target_price && ` or below $${alert.target_price}`}

))}
)}
)} {/* Billing Tab */} {activeTab === 'billing' && (
{/* Current Plan */}

Your Current Plan

{tierName === 'Tycoon' ? ( ) : tierName === 'Trader' ? ( ) : ( )}

{tierName}

{tierName === 'Scout' ? 'Free forever' : tierName === 'Trader' ? '$19/month' : '$49/month'}

{isProOrHigher ? 'Active' : 'Free'}
{/* Plan Stats */}

{subscription?.domain_limit || 5}

Domains

{subscription?.check_frequency === 'realtime' ? '10m' : subscription?.check_frequency === 'hourly' ? '1h' : '24h'}

Check Interval

{subscription?.portfolio_limit === -1 ? '∞' : subscription?.portfolio_limit || 0}

Portfolio

{isProOrHigher ? ( ) : ( Upgrade Plan )}
{/* Plan Features */}

Your Plan Includes

  • {subscription?.domain_limit || 5} Watchlist Domains
  • {subscription?.check_frequency === 'realtime' ? '10-minute' : subscription?.check_frequency === 'hourly' ? 'Hourly' : 'Daily'} Scans
  • Email Alerts
  • TLD Price Data
  • {subscription?.features?.domain_valuation && (
  • Domain Valuation
  • )} {(subscription?.portfolio_limit ?? 0) !== 0 && (
  • {subscription?.portfolio_limit === -1 ? 'Unlimited' : subscription?.portfolio_limit} Portfolio
  • )} {subscription?.features?.expiration_tracking && (
  • Expiry Tracking
  • )} {(subscription?.history_days ?? 0) !== 0 && (
  • {subscription?.history_days === -1 ? 'Full' : `${subscription?.history_days}-day`} History
  • )}
{/* Compare All Plans */}

Compare All Plans

Feature Scout Trader Tycoon
Price Free $19/mo $49/mo
Watchlist Domains 5 50 500
Scan Frequency Daily Hourly 10 min
Portfolio 25 Unlimited
Domain Valuation
Price History 90 days Unlimited
Expiry Tracking
{!isProOrHigher && (
Upgrade Now
)}
)} {/* Security Tab */} {activeTab === 'security' && (

Password

Change your password or reset it if you've forgotten it.

Change Password

Account Security

Email Verified

Your email address has been verified

Two-Factor Authentication

Coming soon

Soon

Danger Zone

Permanently delete your account and all associated data.

)}
) }