'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, ExternalLink, Plus, Activity, ArrowRight, CheckCircle2, XCircle, Loader2, Crosshair, Zap, Globe, Target } 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 SearchResult { domain: string status: string is_available: boolean | null registrar: string | null expiration_date: string | null loading: boolean inAuction: boolean auctionData?: HotAuction } // ============================================================================ // 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, 5)) 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: 'Status', value: 'ONLINE', highlight: true }, { label: 'Tracking', value: totalDomains.toString() }, { label: 'Available', value: availableDomains.length.toString(), highlight: availableDomains.length > 0 }, { label: 'Auctions', value: marketStats.totalAuctions.toString() }, ] return ( {toast && } {/* ═══════════════════════════════════════════════════════════════════════ */} {/* HERO - Compact for Laptops */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Left: Typography */}
Intelligence Hub

Domain Radar Find your next acquisition.

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

{/* Stats Row */}
{totalDomains}
Tracking
{availableDomains.length}
Available
{marketStats.endingSoon}
Ending Soon
{/* Right: Search Terminal */}
{/* Header Bar */}
Domain Search
{/* Input */}
setSearchQuery(e.target.value)} onFocus={() => setSearchFocused(true)} onBlur={() => setSearchFocused(false)} placeholder="example.com" className="w-full bg-transparent px-4 py-4 text-lg text-white placeholder:text-white/20 outline-none" /> {searchQuery && ( )}
{/* Results */} {searchResult && (
{searchResult.loading ? (
Checking availability...
) : (
{/* Status Header */}
{searchResult.is_available ? ( ) : ( )} {searchResult.domain}
{searchResult.is_available ? 'Available' : 'Taken'}
{/* Registrar Info */} {!searchResult.is_available && searchResult.registrar && (

Registered with {searchResult.registrar}

)} {/* Actions - Always show */}
{searchResult.is_available && ( Register Now )}
)}
)} {/* Hint */} {!searchResult && (

Enter a domain name to check availability

)}
{/* Ticker */} {/* ═══════════════════════════════════════════════════════════════════════ */} {/* CONTENT GRID */} {/* ═══════════════════════════════════════════════════════════════════════ */}
{/* Hot Auctions - 2 cols */}
Live Auctions
View all →
{loadingData ? (
) : hotAuctions.length > 0 ? ( ) : (
No active auctions
)}
{/* Quick Links */}
Quick Access
{[ { label: 'Watchlist', href: '/terminal/watchlist', icon: Eye }, { label: 'Market', href: '/terminal/market', icon: Gavel }, { label: 'Intel', href: '/terminal/intel', icon: Globe }, ].map((item) => ( {item.label} ))}
{/* Status */}
System online
) }