{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "opponent-profile",
  "title": "Opponent profile",
  "description": "Scout an opponent from your uploaded hands: their HUD and the leaks Poker Study AI noted. Needs your API key.",
  "registryDependencies": [
    "https://www.pokerstudy.ai/r/poker-core.json",
    "https://www.pokerstudy.ai/r/player-stats.json",
    "https://www.pokerstudy.ai/r/pokerstudy-api.json"
  ],
  "files": [
    {
      "path": "src/components/pokerstudy/opponent-profile.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { PlayerStatsGrid } from \"@/components/pokerstudy/player-stats\";\nimport { PokerStudyStatus, usePokerStudy } from \"@/components/pokerstudy/use-pokerstudy\";\nimport { STAT_LABELS, type OpponentDetail, type OpponentListItem, type StatKey } from \"@/lib/pokerstudy/poker\";\n\nfunction noteText(n: OpponentDetail[\"notes\"][number]): string {\n  if (n.manualText) return n.manualText;\n  const spot = STAT_LABELS[n.spotLabel as StatKey] ?? n.spotLabel;\n  return `${spot}: ${n.leakType}`;\n}\n\n/** One opponent: hand count, HUD, and the notes Poker Study AI wrote about them. */\nexport function OpponentProfileView({ data }: { data: OpponentDetail }) {\n  return (\n    <div className=\"flex w-full max-w-[560px] flex-col gap-4\">\n      <div className=\"flex flex-wrap items-baseline justify-between gap-2\">\n        <span className=\"text-base font-semibold text-foreground\">{data.opponent.displayName}</span>\n        <span className=\"font-mono text-xs text-muted-foreground\">{data.opponent.handCount} hands</span>\n      </div>\n      <PlayerStatsGrid stats={data.stats} />\n      <div className=\"flex flex-col gap-2\">\n        <span className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">Notes</span>\n        {data.notes.length === 0 ? (\n          <span className=\"text-sm text-muted-foreground\">No pattern has enough hands for a note yet.</span>\n        ) : (\n          <ul className=\"flex flex-col gap-1.5\">\n            {data.notes.map((n) => (\n              <li key={n.id} className=\"flex items-baseline justify-between gap-3 text-sm\">\n                <span className=\"text-foreground\">\n                  <span className=\"mr-2 rounded bg-amber-400/15 px-1.5 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-amber-300\">\n                    {n.street}\n                  </span>\n                  {noteText(n)}\n                </span>\n                <span className=\"shrink-0 font-mono text-xs tabular-nums text-muted-foreground\">{n.sampleSize} hands</span>\n              </li>\n            ))}\n          </ul>\n        )}\n      </div>\n    </div>\n  );\n}\n\n/**\n * Scout an opponent from the hands you uploaded to Poker Study AI: their HUD\n * and the leaks it noted. With no `opponentId` it shows a picker of your most\n * recent opponents. Private data: see `authorizePrivate`.\n */\nexport function OpponentProfile({\n  opponentId,\n  endpoint = \"/api/pokerstudy\",\n  initialData,\n}: {\n  opponentId?: string;\n  endpoint?: string;\n  initialData?: OpponentDetail;\n}) {\n  const [picked, setPicked] = useState<string | null>(null);\n  const list = usePokerStudy<{ opponents: OpponentListItem[] }>(\n    opponentId || initialData ? null : `${endpoint}/opponents`,\n  );\n  const options = list.status === \"ready\" ? list.data.opponents.slice(0, 50) : [];\n  const id = opponentId ?? picked ?? options[0]?.id;\n  const detail = usePokerStudy<OpponentDetail>(id ? `${endpoint}/opponents/${id}` : null, { initialData });\n\n  if (!opponentId && !initialData && list.status !== \"ready\") return <PokerStudyStatus state={list} />;\n  if (!id && !initialData) {\n    return <p className=\"text-sm text-muted-foreground\">No opponents yet. Upload a hand history at pokerstudy.ai.</p>;\n  }\n  return (\n    <div className=\"flex w-full max-w-[560px] flex-col gap-4\">\n      {options.length > 1 ? (\n        <select\n          aria-label=\"Opponent\"\n          value={id}\n          onChange={(e) => setPicked(e.target.value)}\n          className=\"self-start rounded-md border border-white/15 bg-neutral-950 px-2 py-1.5 text-sm text-foreground\"\n        >\n          {options.map((o) => (\n            <option key={o.id} value={o.id}>\n              {o.displayName} ({o.handCount} hands)\n            </option>\n          ))}\n        </select>\n      ) : null}\n      {detail.status === \"ready\" ? <OpponentProfileView data={detail.data} /> : <PokerStudyStatus state={detail} />}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/pokerstudy/opponent-profile.tsx"
    }
  ],
  "type": "registry:block"
}