'use client' import { useEffect, useState } from 'react' import { useStore } from '@/lib/store' import { api } from '@/lib/api' import { CommandCenterLayout } from '@/components/CommandCenterLayout' import { Toast, useToast } from '@/components/Toast' import { Plus, Trash2, RefreshCw, Loader2, Bell, BellOff, History, ExternalLink, MoreVertical, Search, Filter, ArrowUpRight, } from 'lucide-react' import clsx from 'clsx' import Link from 'next/link' interface DomainHistory { id: number status: string is_available: boolean checked_at: string } // Status indicator component with traffic light system function StatusIndicator({ domain }: { domain: any }) { // Determine status based on domain data let status: 'available' | 'watching' | 'stable' = 'stable' let label = 'Stable' let description = 'Domain is registered and active' if (domain.is_available) { status = 'available' label = 'Available' description = 'Domain is available for registration!' } else if (domain.status === 'checking' || domain.status === 'pending') { status = 'watching' label = 'Watching' description = 'Monitoring for changes' } const colors = { available: 'bg-accent text-accent', watching: 'bg-amber-400 text-amber-400', stable: 'bg-foreground-muted text-foreground-muted', } return (
{status === 'available' && ( )}

{label}

{description}

) } export default function WatchlistPage() { const { domains, addDomain, deleteDomain, refreshDomain, subscription } = useStore() const { toast, showToast, hideToast } = useToast() const [newDomain, setNewDomain] = useState('') const [adding, setAdding] = useState(false) const [refreshingId, setRefreshingId] = useState(null) const [deletingId, setDeletingId] = useState(null) const [selectedDomainId, setSelectedDomainId] = useState(null) const [domainHistory, setDomainHistory] = useState(null) const [loadingHistory, setLoadingHistory] = useState(false) const [togglingNotifyId, setTogglingNotifyId] = useState(null) const [filterStatus, setFilterStatus] = useState<'all' | 'available' | 'watching'>('all') const [searchQuery, setSearchQuery] = useState('') // Filter domains const filteredDomains = domains?.filter(domain => { // Search filter if (searchQuery && !domain.name.toLowerCase().includes(searchQuery.toLowerCase())) { return false } // Status filter if (filterStatus === 'available' && !domain.is_available) return false if (filterStatus === 'watching' && domain.is_available) return false return true }) || [] // Stats const availableCount = domains?.filter(d => d.is_available).length || 0 const watchingCount = domains?.filter(d => !d.is_available).length || 0 const handleAddDomain = async (e: React.FormEvent) => { e.preventDefault() if (!newDomain.trim()) return setAdding(true) try { await addDomain(newDomain.trim()) setNewDomain('') showToast(`Added ${newDomain.trim()} to watchlist`, 'success') } catch (err: any) { showToast(err.message || 'Failed to add domain', 'error') } finally { setAdding(false) } } const handleRefresh = async (id: number) => { setRefreshingId(id) try { await refreshDomain(id) showToast('Domain status refreshed', 'success') } catch (err: any) { showToast(err.message || 'Failed to refresh', 'error') } finally { setRefreshingId(null) } } const handleDelete = async (id: number, name: string) => { if (!confirm(`Remove ${name} from your watchlist?`)) return setDeletingId(id) try { await deleteDomain(id) showToast(`Removed ${name} from watchlist`, 'success') } catch (err: any) { showToast(err.message || 'Failed to remove', 'error') } finally { setDeletingId(null) } } const handleToggleNotify = async (id: number, currentState: boolean) => { setTogglingNotifyId(id) try { await api.updateDomainNotify(id, !currentState) showToast( !currentState ? 'Notifications enabled' : 'Notifications disabled', 'success' ) } catch (err: any) { showToast(err.message || 'Failed to update', 'error') } finally { setTogglingNotifyId(null) } } const loadHistory = async (domainId: number) => { if (selectedDomainId === domainId) { setSelectedDomainId(null) setDomainHistory(null) return } setSelectedDomainId(domainId) setLoadingHistory(true) try { const history = await api.getDomainHistory(domainId) setDomainHistory(history) } catch (err) { setDomainHistory([]) } finally { setLoadingHistory(false) } } const domainLimit = subscription?.domain_limit || 5 const domainsUsed = domains?.length || 0 const canAddMore = domainsUsed < domainLimit return ( {toast && }
{/* Stats Cards */}

Total Watched

{domainsUsed}

Available

{availableCount}

Watching

{watchingCount}

Limit

{domainLimit === -1 ? '∞' : domainLimit}

{/* Add Domain Form */}
setNewDomain(e.target.value)} placeholder="Enter domain to track (e.g., dream.com)" disabled={!canAddMore} className={clsx( "w-full h-12 px-5 bg-background-secondary/50 border border-border/50 rounded-xl", "text-foreground placeholder:text-foreground-subtle", "focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent/30", "disabled:opacity-50 disabled:cursor-not-allowed", "shadow-[0_2px_8px_-2px_rgba(0,0,0,0.1)]" )} />
{!canAddMore && (

You've reached your domain limit. Upgrade to track more.

Upgrade
)} {/* Filters */}
setSearchQuery(e.target.value)} placeholder="Search domains..." className="w-full sm:w-64 h-10 pl-9 pr-4 bg-background-secondary border border-border rounded-lg text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:border-accent" />
{/* Domain List */}
{filteredDomains.length === 0 ? (
{domainsUsed === 0 ? ( <>

Your watchlist is empty

Add a domain above to start tracking

) : ( <>

No domains match your filters

)}
) : ( filteredDomains.map((domain) => (
{/* Domain Name + Status */}

{domain.name}

{domain.is_available && ( GRAB IT! )}
{/* Actions */}
{/* Notify Toggle */} {/* History */} {/* Refresh */} {/* Delete */} {/* External Link (if available) */} {domain.is_available && ( Register )}
{/* History Panel */} {selectedDomainId === domain.id && (

Status History

{loadingHistory ? (
Acquiring targets...
) : domainHistory && domainHistory.length > 0 ? (
{domainHistory.slice(0, 5).map((entry) => (
{new Date(entry.checked_at).toLocaleDateString()} at{' '} {new Date(entry.checked_at).toLocaleTimeString()} {entry.is_available ? 'Available' : 'Registered'}
))}
) : (

No history available yet

)}
)}
)) )}
) }