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, Table, th, td, tdNum, Badge, VsRiv } from '@/components/ui/primitives'; import { GradeBadge, SourceLink, Thumb } from '@/components/market/bits'; import { AssetTile, Rail, RailHeader, type TileMetric } from '@/components/market/asset-tile'; import { heatStyle } from '@/components/charts/heat'; const EMPTY = 'Populates as the pipeline ingests data.'; /** Editorial rail of poster tiles (snap-scroll on mobile, grid from lg). */ export function AssetRail({ title, subtitle, href, items, metric, empty = EMPTY, priority = false }: { title: string; subtitle?: string; href: string; items: AssetCardData[]; metric: TileMetric; empty?: string; priority?: boolean }) { return (
{items.length ? ( {items.slice(0, 8).map((a, i) => ( ))} ) : ( )}
); } function SaleTile({ s }: { s: SaleRow }) { return ( {s.assetTitle ?? s.rawTitle} {catName(s.categorySlug)} {fmtMoney(s.priceUsd)} {fmtDate(s.saleDate)} · {s.sourceName} ); } export function SalesRail({ title, subtitle, href, items, hideWhenEmpty = false }: { title: string; subtitle?: string; href: string; items: SaleRow[]; hideWhenEmpty?: boolean }) { if (hideWhenEmpty && !items.length) return null; return (
{items.length ? ( {items.slice(0, 8).map((s) => ( ))} ) : ( )}
); } export function RadarRail({ items, hideWhenEmpty = false }: { items: RadarRow[]; hideWhenEmpty?: boolean }) { if (hideWhenEmpty && !items.length) return null; return (
{items.length ? ( {items.slice(0, 8).map((r) => ( {humanize(r.kind)} {r.assetTitle} {r.rivUsd === null ? 'RIV —' : `RIV ${fmtMoney(r.rivUsd)}`} · signal {r.score.toFixed(0)} · {fmtRelative(r.detectedAt)} ))} ) : ( )}
); } export function LotsRail({ items, hideWhenEmpty = false }: { items: LotRow[]; hideWhenEmpty?: boolean }) { if (hideWhenEmpty && !items.length) return null; return (
{items.length ? ( {items.slice(0, 8).map((l) => ( {l.title} {l.auctionHouse} · ends {fmtRelative(l.endsAt)} {l.allInBidUsd !== null || l.allInEstimateLowUsd !== null ? `${l.feeBasis === 'added_approximate' || l.feeBasis === 'added_default' ? '≈ ' : ''}${fmtMoney(l.allInBidUsd ?? l.allInEstimateLowUsd)}` : l.currentBid !== null ? fmtMoney(l.currentBid, l.currency ?? 'USD') : l.estimateHigh !== null ? `est. ${fmtMoney(l.estimateHigh, l.currency ?? 'USD')}` : '—'} {l.bidVsRiv !== null || l.estimateVsRiv !== null ? : {l.allInBidUsd !== null || l.allInEstimateLowUsd !== null ? 'all-in' : ''}} ))} ) : ( )}
); } export function MarketInsights({ rows }: { rows: MarketRow[] }) { const withData = rows.filter((r) => r.counts.assets > 0).sort((a, b) => b.counts.sales - a.counts.sales || b.counts.assets - a.counts.assets); return ( Markets →} /> {withData.length ? ( {withData.slice(0, 10).map((r) => ( ))}
Category Assets Sales Listings 30D
{r.node.name} {fmtNum(r.counts.assets)} {fmtNum(r.counts.sales)} {fmtNum(r.counts.listings)}
) : ( )}
); } export interface LatestObservation { id: string; assetSlug: string; assetTitle: string; categorySlug: string; heroImageUrl: string | null; priceUsd: number; priceKind: string; observationDate: string; sourceName: string; } /** Latest transactions as a dense, attributed table; falls back to guide-price observations when no sale exists yet. */ export function LatestTransactions({ items, observations = [] }: { items: LatestSale[]; observations?: LatestObservation[] }) { if (!items.length && observations.length) { return ( Browse →} /> {observations.map((o) => ( ))}
Asset Kind Source Date Price
{o.assetTitle} {catName(o.categorySlug)} {humanize(o.priceKind)} {o.sourceName} {fmtDate(o.observationDate)} {fmtMoney(o.priceUsd)}
); } return ( All sales →} /> {items.length ? ( {items.map((s) => ( ))}
Asset Grade Type Source Date Price
{s.assetTitle} {catName(s.categorySlug)} {humanize(s.saleType)} {fmtDate(s.saleDate)} {fmtMoney(s.priceUsd)} {s.currency !== 'USD' ? {fmtMoney(s.price, s.currency)} : null}
) : ( )}
); } export function cls(...c: Array): string { return cn(...c); }