Files
goldenChart/frontend/src/components/paper/PaperCompactOrderbook.tsx
T
2026-05-23 21:08:46 +09:00

77 lines
2.5 KiB
TypeScript

import React, { memo } from 'react';
import { useUpbitOrderbook } from '../../hooks/useUpbitOrderbook';
interface Props {
market: string;
onPick?: (price: number, rowType: 'ask' | 'bid') => void;
fillHeight?: boolean;
hideHeader?: boolean;
depth?: number;
}
function fmtPrice(p: number): string {
if (!Number.isFinite(p)) return '-';
return p >= 1000 ? p.toLocaleString('ko-KR', { maximumFractionDigits: 0 }) : p.toFixed(4);
}
function fmtSize(s: number): string {
if (!Number.isFinite(s)) return '-';
if (s >= 1000) return s.toLocaleString('ko-KR', { maximumFractionDigits: 2 });
return s.toFixed(4);
}
const PaperCompactOrderbook: React.FC<Props> = memo(({
market,
onPick,
fillHeight = false,
hideHeader = false,
depth = 8,
}) => {
const { orderbook } = useUpbitOrderbook(market);
const rowCount = fillHeight ? Math.max(depth, 12) : depth;
const asks = orderbook.asks.slice(0, rowCount).reverse();
const bids = orderbook.bids.slice(0, rowCount);
const maxSize = Math.max(
...asks.map(a => a.size),
...bids.map(b => b.size),
1,
);
const mid = bids[0]?.price ?? asks[asks.length - 1]?.price ?? 0;
return (
<div className={`ptd-ob${fillHeight ? ' ptd-ob--fill' : ''}`}>
{!hideHeader && <div className="ptd-ob-head">호가 (Depth)</div>}
<div className="ptd-ob-body">
{asks.map(a => (
<button
key={`a-${a.price}`}
type="button"
className="ptd-ob-row ptd-ob-row--ask"
onClick={() => onPick?.(a.price, 'ask')}
>
<span className="ptd-ob-bar" style={{ width: `${(a.size / maxSize) * 100}%` }} />
<span className="ptd-ob-price">{fmtPrice(a.price)}</span>
<span className="ptd-ob-size">{fmtSize(a.size)}</span>
</button>
))}
<div className="ptd-ob-mid">{mid ? fmtPrice(mid) : '—'}</div>
{bids.map(b => (
<button
key={`b-${b.price}`}
type="button"
className="ptd-ob-row ptd-ob-row--bid"
onClick={() => onPick?.(b.price, 'bid')}
>
<span className="ptd-ob-bar" style={{ width: `${(b.size / maxSize) * 100}%` }} />
<span className="ptd-ob-price">{fmtPrice(b.price)}</span>
<span className="ptd-ob-size">{fmtSize(b.size)}</span>
</button>
))}
</div>
</div>
);
});
PaperCompactOrderbook.displayName = 'PaperCompactOrderbook';
export default PaperCompactOrderbook;