import { useMemo, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { useWatchlist } from '../hooks/useWatchlist'; import { useRankings } from '../hooks/useScores'; import { WatchlistTable } from '../components/watchlist/WatchlistTable'; import { AddTickerForm } from '../components/watchlist/AddTickerForm'; import { RankingsTable } from '../components/rankings/RankingsTable'; import { WeightsForm } from '../components/rankings/WeightsForm'; import { Callout } from '../components/ui/Callout'; import { Disclosure } from '../components/ui/Disclosure'; import { Dropdown } from '../components/ui/Dropdown'; import { PageHeader } from '../components/ui/PageHeader'; import { SkeletonTable } from '../components/ui/Skeleton'; import { Tabs } from '../components/ui/Tabs'; import type { WatchlistEntry } from '../lib/types'; const tabs = ['Watchlist', 'Rankings'] as const; type Tab = (typeof tabs)[number]; type SortMode = 'name_asc' | 'name_desc' | 'score_desc' | 'score_asc'; function sortEntries(entries: WatchlistEntry[], mode: SortMode): WatchlistEntry[] { const sorted = [...entries]; if (mode === 'name_asc') { sorted.sort((a, b) => a.symbol.localeCompare(b.symbol)); return sorted; } if (mode === 'name_desc') { sorted.sort((a, b) => b.symbol.localeCompare(a.symbol)); return sorted; } if (mode === 'score_desc') { sorted.sort((a, b) => { const aScore = a.composite_score ?? Number.NEGATIVE_INFINITY; const bScore = b.composite_score ?? Number.NEGATIVE_INFINITY; if (aScore === bScore) return a.symbol.localeCompare(b.symbol); return bScore - aScore; }); return sorted; } sorted.sort((a, b) => { const aScore = a.composite_score ?? Number.POSITIVE_INFINITY; const bScore = b.composite_score ?? Number.POSITIVE_INFINITY; if (aScore === bScore) return a.symbol.localeCompare(b.symbol); return aScore - bScore; }); return sorted; } function WatchlistPanel() { const { data, isLoading, isError, error } = useWatchlist(); const [sortMode, setSortMode] = useState('score_desc'); const sortedEntries = useMemo( () => (data ? sortEntries(data, sortMode) : []), [data, sortMode], ); return (
{isLoading && } {isError && {error?.message || 'Failed to load watchlist'}} {data && ( <>
)}
); } function RankingsPanel() { const { data, isLoading, isError, error } = useRankings(); return (
{isLoading && } {isError && ( Failed to load rankings: {(error as Error).message} )} {data && ( <> )}
); } export default function MarketPage() { const [searchParams, setSearchParams] = useSearchParams(); const activeTab: Tab = searchParams.get('tab') === 'rankings' ? 'Rankings' : 'Watchlist'; const setTab = (tab: Tab) => { setSearchParams(tab === 'Rankings' ? { tab: 'rankings' } : {}, { replace: true }); }; return (
{activeTab === 'Watchlist' ? : }
); }