'use client' import { useEffect, useState, useMemo, useCallback, useRef } from 'react' import { useStore } from '@/lib/store' import { api } from '@/lib/api' import { CommandCenterLayout } from '@/components/CommandCenterLayout' import { Toast, useToast } from '@/components/Toast' import { Eye, Gavel, Clock, ExternalLink, Plus, Activity, Search, ArrowRight, CheckCircle2, XCircle, Loader2, Crosshair, Radar, Zap, Globe, Target, Cpu, Radio } from 'lucide-react' import clsx from 'clsx' import Link from 'next/link' // ============================================================================ // TYPES // ============================================================================ interface HotAuction { domain: string current_bid: number time_remaining: string platform: string affiliate_url?: string } interface TrendingTld { tld: string current_price: number price_change: number reason: string } interface SearchResult { domain: string status: string is_available: boolean | null registrar: string | null expiration_date: string | null loading: boolean inAuction: boolean auctionData?: HotAuction } // ============================================================================ // ANIMATED RADAR COMPONENT // ============================================================================ function RadarAnimation() { return (
{/* Outer Ring */}
{/* Crosshairs */}
{/* Sweeping Line */}
{/* Center Dot */}
{/* Blips */}
) } // ============================================================================ // LIVE TICKER // ============================================================================ function LiveTicker({ items }: { items: { label: string; value: string; highlight?: boolean }[] }) { return (
{[...items, ...items, ...items].map((item, i) => (
{item.label} {item.value}
))}
) } // ============================================================================ // MAIN PAGE // ============================================================================ export default function RadarPage() { const { isAuthenticated, user, domains, addDomain } = 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) // 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() }, [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(`Target acquired: ${searchQuery.trim()}`, 'success') setSearchQuery('') setSearchResult(null) } catch (err: any) { showToast(err.message || 'Mission 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 const tickerItems = [ { label: 'System', value: 'ONLINE', highlight: true }, { label: 'Targets', value: totalDomains.toString() }, { label: 'Opportunities', value: availableDomains.length.toString(), highlight: availableDomains.length > 0 }, { label: 'Market', value: `${marketStats.totalAuctions} Active` }, { label: 'Latency', value: '12ms' }, ] return ( {toast && }
{/* ═══════════════════════════════════════════════════════════════════════ */} {/* HERO SECTION - CINEMATIC */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Left: Typography */}
Intelligence Hub // Active

Global Recon. Zero Blind Spots.

Scanning {marketStats.totalAuctions.toLocaleString()}+ auction listings across all major platforms. Your targets. Your intel.

{/* Stats Row */}
{totalDomains}
Tracking
{availableDomains.length}
Ready
{marketStats.endingSoon}
Ending Soon
{/* Right: Search Terminal */}
{/* Tech Corners */}
{/* Header */}
Target Acquisition
{/* Input */}
{'>'}
setSearchQuery(e.target.value)} onFocus={() => setSearchFocused(true)} onBlur={() => setSearchFocused(false)} placeholder="ENTER_TARGET..." className="w-full bg-black/50 px-10 py-5 text-2xl text-white placeholder:text-white/20 font-mono uppercase tracking-tight outline-none" /> {searchQuery && ( )}
{/* Results */} {searchResult && (
{searchResult.loading ? (
Scanning registries...
) : (
{searchResult.is_available ? (
) : (
)} {searchResult.domain}
{searchResult.is_available ? 'AVAILABLE' : 'REGISTERED'}
{searchResult.is_available && (
ACQUIRE
)}
)}
)} {/* Footer */}
SECURE_CONNECTION V2.1.0
{/* Ticker */} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* LIVE FEED SECTION */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Section Header */}
Live Feed

Market
Operations.

Live Updates
Full Feed
{/* Grid */}
{/* Hot Auctions */}

Active Auctions

Real-time market data

{loadingData ? (
) : hotAuctions.length > 0 ? ( ) : (
No active auctions
)}
{/* Quick Actions */}

Quick Access

Navigation

{[ { label: 'Watchlist', desc: 'Your targets', href: '/terminal/watchlist', icon: Eye }, { label: 'Market', desc: 'All auctions', href: '/terminal/market', icon: Gavel }, { label: 'Intel', desc: 'TLD pricing', href: '/terminal/intel', icon: Globe }, ].map((item) => (
{item.label}
{item.desc}
))}
{/* System Status */}
System Status
All Systems Operational
99.9%
) }