feat(market): 거래대금 상위 + 52주 위치 게이지

- /api/markets/movers: by_trading_value (close*volume DESC) 카테고리 추가
- MarketsOverview: 4 컬럼 그리드 (등락 상위/하위/거래대금/거래량), 거래대금은 억·조 표기
- SymbolSidebar: 52주 범위 내 현재가 위치 게이지 (그라데이션 바 + 화이트 점)
This commit is contained in:
claude-owner
2026-05-28 15:21:27 +09:00
parent aa58761176
commit 645e93e7bf
4 changed files with 114 additions and 39 deletions

View File

@@ -45,13 +45,22 @@ export function SymbolSidebar({ code }: { code: string }) {
if (p.high != null && p.high > yearHigh) yearHigh = p.high;
if (p.low != null && p.low < yearLow) yearLow = p.low;
}
const yh = yearHigh === -Infinity ? null : yearHigh;
const yl = yearLow === Infinity ? null : yearLow;
// 52주 위치 (0~1). 종가 기준, 분모 0 방어.
let pos: number | null = null;
if (yh != null && yl != null && yh > yl && last.close != null) {
pos = Math.min(1, Math.max(0, (last.close - yl) / (yh - yl)));
}
return {
open: last.open,
high: last.high,
low: last.low,
close: last.close,
volume: last.volume,
yearHigh: yearHigh === -Infinity ? null : yearHigh,
yearLow: yearLow === Infinity ? null : yearLow,
yearHigh: yh,
yearLow: yl,
yearPos: pos,
};
}, [chart]);
@@ -81,6 +90,48 @@ export function SymbolSidebar({ code }: { code: string }) {
<Row label="52주 최고" value={fmt(stats.yearHigh)} tone="up" />
<Row label="52주 최저" value={fmt(stats.yearLow)} tone="down" />
</dl>
{stats.yearPos != null && (
<YearRangeBar
low={stats.yearLow}
high={stats.yearHigh}
pos={stats.yearPos}
/>
)}
</div>
);
}
// 52주 범위 내 현재가 위치 — 토스 종목 상세에 있는 가로 게이지를 흉내냄.
function YearRangeBar({
low,
high,
pos,
}: {
low: number | null;
high: number | null;
pos: number;
}) {
const pct = pos * 100;
return (
<div className="mt-4 border-t border-zinc-800 pt-3">
<div className="mb-1.5 flex items-center justify-between text-[10px] text-zinc-500">
<span>52 </span>
<span className="tabular-nums text-zinc-300">{pct.toFixed(0)}%</span>
</div>
<div className="relative h-1.5 w-full rounded-full bg-zinc-800">
<div
className="absolute left-0 top-0 h-full rounded-full bg-gradient-to-r from-sky-500/70 via-amber-400/70 to-rose-500/70"
style={{ width: "100%" }}
/>
<div
className="absolute top-1/2 h-3 w-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-zinc-950 bg-zinc-100 shadow"
style={{ left: `${pct}%` }}
/>
</div>
<div className="mt-1 flex justify-between text-[10px] tabular-nums text-zinc-500">
<span>{fmt(low)}</span>
<span>{fmt(high)}</span>
</div>
</div>
);
}