import Link from 'next/link';
import type { AssetCard as AssetCardData, SaleRow } from '@/lib/queries/assets';
import type { RadarRow, LotRow } from '@/lib/queries/market-lists';
import type { LatestSale } from '@/lib/queries/site';
import type { MarketRow } from '@/lib/queries/markets';
import { fmtMoney, fmtRelative, fmtNum, cn, fmtDate } from '@/lib/format';
import { catName, humanize } from '@/lib/taxonomy';
import { Card, CardHeader, Delta, EmptyState } from '@/components/ui/primitives';
import { GradeBadge, SourceLink, Thumb } from '@/components/market/bits';
import { heatStyle } from '@/components/charts/heat';
function Row({ href, image, title, sub, right, rightSub }: { href: string; image?: string | null; title: string; sub?: string | null; right: React.ReactNode; rightSub?: React.ReactNode }) {
return (
{title}
{sub ? {sub} : null}
{right}
{rightSub ? {rightSub} : null}
);
}
const EMPTY = 'Populates as the pipeline ingests data.';
export function AssetRail({ title, subtitle, href, items, metric, empty = EMPTY }: { title: string; subtitle?: string; href: string; items: AssetCardData[]; metric: 'change7d' | 'change1d' | 'change30d' | 'trending' | 'watchers' | 'riv' | 'opportunity' | 'new'; empty?: string }) {
return (
View all →} />
{items.length ? (
{items.map((a) => (
— : fmtMoney(a.rivUsd)}
rightSub={
metric === 'trending' ? score {a.trendingScore?.toFixed(1) ?? '—'}
: metric === 'watchers' ? {fmtNum(a.watchers)} watching
: metric === 'new' ? added {fmtRelative(a.updatedAt)}
: metric === 'riv' ? {a.rivSampleSize} sales
: metric === 'opportunity' ?
:
}
/>
))}
) : (
)}
);
}
export function SalesRail({ title, subtitle, href, items }: { title: string; subtitle?: string; href: string; items: SaleRow[] }) {
return (
View all →} />
{items.length ? (
{items.map((s) => (
} />
))}
) : (
)}
);
}
export function RadarRail({ items }: { items: RadarRow[] }) {
return (
Open radar →} />
{items.length ? (
{items.map((r) => (
— : fmtMoney(r.rivUsd)} rightSub={signal {r.score.toFixed(0)}} />
))}
) : (
)}
);
}
export function LotsRail({ items }: { items: LotRow[] }) {
return (
All auctions →} />
{items.length ? (
) : (
)}
);
}
export function MarketInsights({ rows }: { rows: MarketRow[] }) {
const withData = rows.filter((r) => r.counts.assets > 0);
return (
Markets →} />
{withData.length ? (
{withData.slice(0, 10).map((r) => (
-
{r.node.name}
{fmtNum(r.counts.assets)} assets · {fmtNum(r.counts.sales)} sales
))}
) : (
)}
);
}
export function LatestTransactions({ items }: { items: LatestSale[] }) {
return (
All sales →} />
{items.length ? (
{items.map((s) => (
-
{s.assetTitle}
{fmtDate(s.saleDate)} ·
{fmtMoney(s.priceUsd)}
))}
) : (
)}
);
}
export function cls(...c: Array): string {
return cn(...c);
}