'use client' import { useEffect, useState, useCallback, useRef } from 'react' import { useStore } from '@/lib/store' import { api } from '@/lib/api' import { Sidebar } from '@/components/Sidebar' import { Toast, useToast } from '@/components/Toast' import { Eye, Gavel, ArrowRight, CheckCircle2, XCircle, Loader2, Crosshair, Zap, Globe, Target, Search, X, TrendingUp, Settings, Clock, Wifi, ChevronRight, Sparkles, Radio, Activity, Menu, Tag, Coins, Shield, LogOut, Crown, ChevronDown } from 'lucide-react' import clsx from 'clsx' import Link from 'next/link' import Image from 'next/image' // ============================================================================ // TYPES // ============================================================================ interface HotAuction { domain: string current_bid: number time_remaining: string platform: string affiliate_url?: string } interface SearchResult { domain: string status: string is_available: boolean | null registrar: string | null expiration_date: string | null loading: boolean inAuction: boolean auctionData?: HotAuction } // ============================================================================ // MAIN PAGE // ============================================================================ export default function RadarPage() { const { isAuthenticated, domains, addDomain, user, subscription, logout } = useStore() const { toast, showToast, hideToast } = useToast() const [hotAuctions, setHotAuctions] = useState([]) const [marketStats, setMarketStats] = useState({ totalAuctions: 0, endingSoon: 0 }) const [loadingData, setLoadingData] = useState(true) const [searchQuery, setSearchQuery] = useState('') const [searchResult, setSearchResult] = useState(null) const [addingToWatchlist, setAddingToWatchlist] = useState(false) const [searchFocused, setSearchFocused] = useState(false) const searchInputRef = useRef(null) // Mobile Menu State const [menuOpen, setMenuOpen] = useState(false) // Load Data const loadDashboardData = useCallback(async () => { try { const summary = await api.getDashboardSummary() setHotAuctions((summary.market.ending_soon_preview || []).slice(0, 6)) setMarketStats({ totalAuctions: summary.market.total_auctions || 0, endingSoon: summary.market.ending_soon || 0, }) } catch (error) { console.error('Failed to load data:', error) } finally { setLoadingData(false) } }, []) useEffect(() => { if (isAuthenticated) loadDashboardData() else setLoadingData(false) }, [isAuthenticated, loadDashboardData]) // Search const handleSearch = useCallback(async (domainInput: string) => { if (!domainInput.trim()) { setSearchResult(null); return } const cleanDomain = domainInput.trim().toLowerCase() setSearchResult({ domain: cleanDomain, status: 'checking', is_available: null, registrar: null, expiration_date: null, loading: true, inAuction: false }) try { const [whoisResult, auctionsResult] = await Promise.all([ api.checkDomain(cleanDomain).catch(() => null), api.getAuctions(cleanDomain).catch(() => ({ auctions: [] })), ]) const auctionMatch = (auctionsResult as any).auctions?.find((a: any) => a.domain.toLowerCase() === cleanDomain) setSearchResult({ domain: whoisResult?.domain || cleanDomain, status: whoisResult?.status || 'unknown', is_available: whoisResult?.is_available ?? null, registrar: whoisResult?.registrar || null, expiration_date: whoisResult?.expiration_date || null, loading: false, inAuction: !!auctionMatch, auctionData: auctionMatch, }) } catch { setSearchResult({ domain: cleanDomain, status: 'error', is_available: null, registrar: null, expiration_date: null, loading: false, inAuction: false }) } }, []) const handleAddToWatchlist = useCallback(async () => { if (!searchQuery.trim()) return setAddingToWatchlist(true) try { await addDomain(searchQuery.trim()) showToast(`Added: ${searchQuery.trim()}`, 'success') setSearchQuery('') setSearchResult(null) } catch (err: any) { showToast(err.message || 'Failed', 'error') } finally { setAddingToWatchlist(false) } }, [searchQuery, addDomain, showToast]) useEffect(() => { const timer = setTimeout(() => { if (searchQuery.length > 3) handleSearch(searchQuery) else setSearchResult(null) }, 500) return () => clearTimeout(timer) }, [searchQuery, handleSearch]) // Computed const availableDomains = domains?.filter(d => d.is_available) || [] const totalDomains = domains?.length || 0 // Nav Items for Mobile Bottom Bar const mobileNavItems = [ { href: '/terminal/radar', label: 'Radar', icon: Target, active: true }, { 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 }, ] // Full Navigation for Drawer const tierName = subscription?.tier_name || subscription?.tier || 'Scout' const TierIcon = tierName === 'Tycoon' ? Crown : tierName === 'Trader' ? TrendingUp : Zap 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/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 */}
{/* Main Content */}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* MOBILE HEADER - Premium App Style */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Brand */}

Radar

Live Intelligence

{/* Stats Pills - Compact */}
{totalDomains}
{availableDomains.length}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* SEARCH SECTION */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Desktop Hero Text */}
Intelligence Hub

Domain Radar

Real-time monitoring across {marketStats.totalAuctions.toLocaleString()}+ auctions

{/* Search Card */}
{/* Desktop Glow */}
{/* Terminal Header - Desktop only */}
Domain Search
{/* Search Input - App Style */}
setSearchQuery(e.target.value)} onFocus={() => setSearchFocused(true)} onBlur={() => setSearchFocused(false)} placeholder="Search domain..." className="flex-1 bg-transparent px-3 py-4 text-base lg:text-lg text-white placeholder:text-white/20 outline-none font-medium" /> {searchQuery && ( )}
{/* Search Result */} {searchResult && (
{searchResult.loading ? (
Scanning network...
) : (
{/* Result Header */}
{searchResult.is_available ? (
) : (
)}
{searchResult.domain}
{!searchResult.is_available && searchResult.registrar && (
via {searchResult.registrar}
)}
{searchResult.is_available ? 'Available' : 'Taken'}
{/* Actions */}
{searchResult.is_available && ( Register Now )}
)}
)} {/* Hint */} {!searchResult && (

Type a domain to check status instantly

)}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* QUICK ACTIONS - Mobile Grid */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{[ { href: '/terminal/watchlist', icon: Eye, label: 'Watchlist', badge: availableDomains.length, color: 'text-emerald-400', bg: 'bg-emerald-400/10', border: 'border-emerald-400/20' }, { href: '/terminal/market', icon: Gavel, label: 'Market', color: 'text-blue-400', bg: 'bg-blue-400/10', border: 'border-blue-400/20' }, { href: '/terminal/intel', icon: TrendingUp, label: 'Intel', color: 'text-amber-400', bg: 'bg-amber-400/10', border: 'border-amber-400/20' }, ].map((item) => (
{item.label} {item.badge !== undefined && item.badge > 0 && ( {item.badge} )} ))}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* STATUS BAR */} {/* ═══════════════════════════════════════════════════════════════════════ */}
Live Feed
{marketStats.totalAuctions.toLocaleString()} total {marketStats.endingSoon} ending
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* WATCHLIST PREVIEW */} {/* ═══════════════════════════════════════════════════════════════════════ */} {domains && domains.length > 0 && (

Your Watchlist

Manage
{domains.slice(0, 6).map((domain) => (
{domain.is_available ? ( ) : ( )}
{domain.domain}
{domain.is_available ? 'Available!' : 'Monitoring'}
{domain.is_available && ( GET IT )} ))}
{domains.length > 6 && ( View all {domains.length} domains )}
)} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* HOT AUCTIONS - Feed Style */} {/* ═══════════════════════════════════════════════════════════════════════ */}

Live Auctions

See all
{loadingData ? (
) : hotAuctions.length > 0 ? ( ) : (

No active auctions

)} {/* Desktop Quick Links */}
{[ { href: '/terminal/watchlist', icon: Eye, label: 'Watchlist', desc: 'Track domain availability' }, { href: '/terminal/market', icon: Gavel, label: 'Market', desc: 'Browse all auctions' }, { href: '/terminal/intel', icon: Globe, label: 'Intel', desc: 'TLD price analysis' }, ].map((item) => (
{item.label}
{item.desc}
))}
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* MOBILE BOTTOM NAV - Frosted Glass */} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* MOBILE DRAWER MENU - Slide Over */} {/* ═══════════════════════════════════════════════════════════════════════ */} {menuOpen && (
{/* Backdrop */}
setMenuOpen(false)} /> {/* Drawer Panel */}
{/* Drawer Header */}
Pounce

POUNCE

Terminal

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

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

{tierName} Plan

{tierName === 'Scout' && ( setMenuOpen(false)} className="flex items-center justify-center gap-2 w-full py-3 bg-white text-black text-sm font-bold rounded-lg active:scale-[0.98] transition-all mb-3 shadow-lg" > Upgrade Now )}
)}
{/* Toast */} {toast && }
) }