56 lines
2.1 KiB
TypeScript
56 lines
2.1 KiB
TypeScript
import type { TickerData } from '../hooks/useMarketTicker';
|
|
import { getKoreanName } from '../utils/marketNameCache';
|
|
import { safePercentFromRate } from '../utils/safeFormat';
|
|
|
|
export type MoverSortKey = 'gainers' | 'losers' | 'volume';
|
|
|
|
export function tickerListFromMap(tickers: Map<string, TickerData>): TickerData[] {
|
|
return [...tickers.values()].filter(t => t.market.startsWith('KRW-') && t.tradePrice != null);
|
|
}
|
|
|
|
export function sortTickers(items: TickerData[], key: MoverSortKey, limit = 15): TickerData[] {
|
|
const copy = [...items];
|
|
if (key === 'gainers') {
|
|
return copy
|
|
.filter(t => (t.changeRate ?? 0) > 0)
|
|
.sort((a, b) => (b.changeRate ?? 0) - (a.changeRate ?? 0))
|
|
.slice(0, limit);
|
|
}
|
|
if (key === 'losers') {
|
|
return copy
|
|
.filter(t => (t.changeRate ?? 0) < 0)
|
|
.sort((a, b) => (a.changeRate ?? 0) - (b.changeRate ?? 0))
|
|
.slice(0, limit);
|
|
}
|
|
return copy
|
|
.sort((a, b) => (b.accTradePrice24 ?? 0) - (a.accTradePrice24 ?? 0))
|
|
.slice(0, limit);
|
|
}
|
|
|
|
export function changeColorClass(rate: number | null | undefined): string {
|
|
if (rate == null || rate === 0) return 'wd-muted';
|
|
return rate > 0 ? 'wd-up' : 'wd-down';
|
|
}
|
|
|
|
export function fmtPct(rate: number | null | undefined): string {
|
|
return safePercentFromRate(rate, 2).replace('—', '-');
|
|
}
|
|
|
|
export function fmtKrwShort(n: number | null | undefined): string {
|
|
if (n == null || !Number.isFinite(n)) return '-';
|
|
if (n >= 1_0000_0000) return `${(n / 1_0000_0000).toFixed(1)}억`;
|
|
if (n >= 1_0000) return `${Math.round(n / 1_0000).toLocaleString('ko-KR')}만`;
|
|
return n.toLocaleString('ko-KR', { maximumFractionDigits: 0 });
|
|
}
|
|
|
|
export function resolveName(market: string, ticker?: TickerData): string {
|
|
return ticker?.koreanName || getKoreanName(market) || market.replace('KRW-', '');
|
|
}
|
|
|
|
export function heatmapColor(rate: number | null | undefined): string {
|
|
if (rate == null || rate === 0) return 'rgba(120, 130, 150, 0.35)';
|
|
const intensity = Math.min(1, Math.abs(rate) * 8);
|
|
if (rate > 0) return `rgba(231, 76, 60, ${0.25 + intensity * 0.55})`;
|
|
return `rgba(52, 152, 219, ${0.25 + intensity * 0.55})`;
|
|
}
|