"use client"; // 같은 시장 내 거래량/유동성 기준 관련 종목 8개. // /api/markets/related/{code} 응답을 좁은 list 카드로 렌더. // Collapsible 로 감싸 — 모바일에서 사이드바 길이가 부담되면 사용자가 접어 둠. import Link from "next/link"; import { useEffect, useState } from "react"; import { api, type RelatedResponse } from "../lib/api"; import { Collapsible } from "./Collapsible"; export function RelatedStocks({ code }: { code: string }) { const [data, setData] = useState(null); const [err, setErr] = useState(null); useEffect(() => { let alive = true; setErr(null); setData(null); api .related(code, 8) .then((r) => { if (alive) setData(r); }) .catch((e) => { if (alive) setErr(e instanceof Error ? e.message : String(e)); }); return () => { alive = false; }; }, [code]); const subtitle = data?.market ? `${data.market} · 거래량 기준` : undefined; return ( {err && (
관련 종목 로딩 실패: {err}
)} {!err && !data && (
관련 종목 로딩 중…
)} {!err && data && !data.items.length && (
같은 시장({data.market}) 데이터가 아직 부족합니다.
)} {!err && data && data.items.length > 0 && (
    {data.items.map((m) => { const pct = m.pct_change; const tone = pct == null || pct === 0 ? "text-zinc-400" : pct > 0 ? "text-rose-400" : "text-sky-400"; return (
  • {m.name} {m.close != null ? m.close.toLocaleString(undefined, { maximumFractionDigits: 0, }) : "—"} {pct != null ? `${pct >= 0 ? "+" : ""}${pct.toFixed(2)}%` : ""}
  • ); })}
)}
); }