import { useState } from "react"; import { cn } from "~/lib/utils"; import { Star, Bell, TrendingUp, TrendingDown, Plus, Trash2, ExternalLink, AlertCircle } from "lucide-react"; import { Button } from "@/routes/ui/button"; import { ChainIcon } from "../components/shared/ChainIcon"; export interface WatchlistToken { /** Unique identifier */ id: string; /** Token symbol */ symbol: string; /** Token name */ name?: string; /** Blockchain chain */ chain: string; /** Contract address */ contractAddress: string; /** Current price */ price: string; /** 24h price change percentage */ priceChange24h: number; /** Whether alerts are enabled for this token */ hasAlerts?: boolean; /** Number of active alerts */ alertCount?: number; } export interface WatchlistAlert { /** Alert ID */ id: string; /** Token symbol */ tokenSymbol: string; /** Alert type */ type: "price" | "volume" | "whale" | "liquidity"; /** Alert message */ message: string; /** When the alert was triggered */ timestamp: Date; /** Whether alert has been read */ isRead?: boolean; } export interface WatchlistPanelProps { /** List of watched tokens */ tokens: WatchlistToken[]; /** Recent alerts */ recentAlerts?: WatchlistAlert[]; /** Callback when token is clicked */ onTokenClick?: (token: WatchlistToken) => void; /** Callback when remove token is clicked */ onRemoveToken?: (tokenId: string) => void; /** Callback when add token is clicked */ onAddToken?: () => void; /** Callback when configure alerts is clicked */ onConfigureAlerts?: (token: WatchlistToken) => void; /** Callback when alert is clicked */ onAlertClick?: (alert: WatchlistAlert) => void; /** Additional class names */ className?: string; } /** * WatchlistPanel - Token watchlist with alerts * * Features: * - List of watched tokens with price changes * - Alert indicators per token * - Recent alerts section * - Add/remove tokens * - Quick access to alert configuration */ export function WatchlistPanel({ tokens, recentAlerts = [], onTokenClick, onRemoveToken, onAddToken, onConfigureAlerts, onAlertClick, className, }: WatchlistPanelProps) { const [activeTab, setActiveTab] = useState<"tokens" | "alerts">("tokens"); const unreadAlerts = recentAlerts.filter(a => !a.isRead).length; return (
{/* Header */}

Watchlist

{/* Tabs */}
{/* Content */}
{activeTab === "tokens" ? ( ) : ( )}
); } /** * TokenList - List of watched tokens */ function TokenList({ tokens, onTokenClick, onRemoveToken, onConfigureAlerts, }: { tokens: WatchlistToken[]; onTokenClick?: (token: WatchlistToken) => void; onRemoveToken?: (tokenId: string) => void; onConfigureAlerts?: (token: WatchlistToken) => void; }) { if (tokens.length === 0) { return (

No tokens in watchlist

Add tokens to track their price and set alerts

); } return (
{tokens.map((token) => (
onTokenClick?.(token)} > {/* Token info */}
{token.symbol} {token.hasAlerts && ( )}

{token.name || token.contractAddress.slice(0, 10) + "..."}

{/* Price and change */}

{token.price}

0 ? "text-green-500" : "text-red-500" )}> {token.priceChange24h > 0 ? ( ) : ( )} {token.priceChange24h > 0 ? "+" : ""}{token.priceChange24h.toFixed(2)}%

{/* Actions (visible on hover) */}
))}
); } /** * AlertList - List of recent alerts */ function AlertList({ alerts, onAlertClick, }: { alerts: WatchlistAlert[]; onAlertClick?: (alert: WatchlistAlert) => void; }) { if (alerts.length === 0) { return (

No alerts yet

Configure alerts on your watched tokens

); } const getAlertIcon = (type: WatchlistAlert["type"]) => { switch (type) { case "price": return TrendingUp; case "volume": return TrendingUp; case "whale": return AlertCircle; case "liquidity": return AlertCircle; default: return Bell; } }; return (
{alerts.map((alert) => { const Icon = getAlertIcon(alert.type); return (
onAlertClick?.(alert)} >
{alert.tokenSymbol} {alert.type}

{alert.message}

{alert.timestamp.toLocaleTimeString()}

{!alert.isRead && (
)}
); })}
); }