import { usePositions } from '../api/hooks'; import { DataTable, type Column } from '../components/DataTable'; import { LoadingSpinner } from '../components/ui'; import type { Position } from '../api/hooks'; function fmtUsd(v: number | null | undefined) { if (v == null) return '—'; return `$${v.toFixed(2)}`; } function pnlColor(v: number | null | undefined) { if (v == null) return 'text-gray-400'; return v >= 0 ? 'text-green-400' : 'text-red-400'; } const columns: Column[] = [ { key: 'ticker', header: 'Ticker', className: 'font-mono font-semibold text-brand-300' }, { key: 'quantity', header: 'Qty' }, { key: 'avg_entry_price', header: 'Entry', render: (r) => {fmtUsd(r.avg_entry_price)} }, { key: 'current_price', header: 'Current', render: (r) => {fmtUsd(r.current_price)} }, { key: 'unrealized_pnl', header: 'Unrealized P&L', render: (r) => {fmtUsd(r.unrealized_pnl)} }, { key: 'realized_pnl', header: 'Realized P&L', render: (r) => {fmtUsd(r.realized_pnl)} }, { key: 'updated_at', header: 'Updated', render: (r) => {new Date(r.updated_at).toLocaleString()} }, ]; export function PositionsPage() { const { data, isLoading } = usePositions(); if (isLoading) return ; const positions = data ?? []; const totals = positions.reduce( (acc, p) => ({ quantity: acc.quantity + p.quantity, unrealized_pnl: acc.unrealized_pnl + (p.unrealized_pnl ?? 0), realized_pnl: acc.realized_pnl + (p.realized_pnl ?? 0), market_value: acc.market_value + p.quantity * (p.current_price ?? 0), cost_basis: acc.cost_basis + p.quantity * p.avg_entry_price, }), { quantity: 0, unrealized_pnl: 0, realized_pnl: 0, market_value: 0, cost_basis: 0 }, ); const footer = positions.length > 0 ? ( Totals {totals.quantity} {fmtUsd(totals.cost_basis)} {fmtUsd(totals.market_value)} {fmtUsd(totals.unrealized_pnl)} {fmtUsd(totals.realized_pnl)} ) : undefined; return (

Positions

data={positions} columns={columns} keyField="id" footerRow={footer} />
); }