'use client'; import { useState, useMemo } from 'react'; import { YieldPool } from '@/types'; import { SecurityBadge } from './SecurityScore'; import { formatNumber, formatPercent, getSecurityRating, getRatingColor } from '@/utils/security'; import { ExternalLink, ChevronDown, ChevronUp, ArrowUpDown, Shield, TrendingUp, Wallet, Info } from 'lucide-react'; import { translations, Locale } from '@/utils/i18n'; interface PoolsTableProps { pools: YieldPool[]; isLoading?: boolean; locale?: Locale; } type SortField = 'apy' | 'tvl' | 'securityScore' | 'protocol'; type SortDirection = 'asc' | 'desc'; export function PoolsTable({ pools, isLoading, locale = 'en' }: PoolsTableProps) { const t = translations[locale]; const [sortField, setSortField] = useState('apy'); const [sortDirection, setSortDirection] = useState('desc'); const [expandedRow, setExpandedRow] = useState(null); const sortedPools = useMemo(() => { return [...pools].sort((a, b) => { let comparison = 0; switch (sortField) { case 'apy': comparison = a.apy - b.apy; break; case 'tvl': comparison = a.tvl - b.tvl; break; case 'securityScore': comparison = a.securityScore - b.securityScore; break; case 'protocol': comparison = a.protocol.localeCompare(b.protocol); break; } return sortDirection === 'desc' ? -comparison : comparison; }); }, [pools, sortField, sortDirection]); const handleSort = (field: SortField) => { if (field === sortField) { setSortDirection(prev => prev === 'desc' ? 'asc' : 'desc'); } else { setSortField(field); setSortDirection('desc'); } }; const SortIcon = ({ field }: { field: SortField }) => { if (field !== sortField) return ; return sortDirection === 'desc' ? : ; }; if (isLoading) return ; if (pools.length === 0) { return (
{t['table.noPool']}
{t['table.tryFilters']}
); } return (

{t['table.allPools']} ({pools.length})

{sortedPools.map((pool) => ( setExpandedRow(expandedRow === pool.id ? null : pool.id)} locale={locale} /> ))}
{t['table.asset']} {t['table.network']} {t['table.action']}
); } interface PoolRowProps { pool: YieldPool; isExpanded: boolean; onToggleExpand: () => void; locale: Locale; } function PoolRow({ pool, isExpanded, onToggleExpand, locale }: PoolRowProps) { const t = translations[locale]; const securityColor = getRatingColor(getSecurityRating(pool.securityScore)); const exploitCount = pool.exploits || 0; const years = Math.floor(pool.protocolAge / 365); return ( <>
{pool.protocolLogo ? ( {pool.protocol} { (e.target as HTMLImageElement).style.display = 'none'; (e.target as HTMLImageElement).nextElementSibling?.classList.remove('hidden'); }} /> ) : null}
{pool.protocol.charAt(0)}
{pool.protocol} {pool.protocolType && ( {pool.protocolType === 'lending' ? 'Lending' : 'Vault'} )}
{pool.stablecoinLogo ? {pool.stablecoin} { (e.target as HTMLImageElement).style.display = 'none'; }} /> : null} {pool.stablecoin} {pool.currency}
{pool.chainLogo && {pool.chain} { (e.target as HTMLImageElement).style.display = 'none'; }} />} {pool.chain}
{formatPercent(pool.apy)}
{pool.apyReward > 0 &&
Base {formatPercent(pool.apyBase)} + {formatPercent(pool.apyReward)}
}
{formatNumber(pool.tvl)}
{exploitCount >= 2 && ⚠ {exploitCount} exploits} {exploitCount === 1 && 1 exploit}
{t['table.deposit']} {isExpanded && (
Audits
{pool.audits} audit{pool.audits > 1 ? 's' : ''}
{t['table.age']}
{years > 0 ? `${years} ${t['top.years']}` : `${pool.protocolAge} ${t['top.days']}`}
{t['table.exploitHistory']}
= 2 ? 'text-red-400' : 'text-yellow-400'}`}> {exploitCount === 0 ? `✓ ${t['table.noExploit']}` : `⚠ ${exploitCount} ${exploitCount > 1 ? t['top.exploits'] : t['top.exploit']}`}
{t['table.type']}
{pool.protocolType === 'lending' ? t['table.lendingProtocol'] : t['table.vaultManager']}
)} ); } function PoolsTableSkeleton() { return (
{[...Array(5)].map((_, i) => (
))}
); }