Files
goldenChart/frontend/src/utils/tradeAlertPopupLayout.ts
T
2026-05-23 15:11:48 +09:00

125 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** 매매 알림 팝업 표시 위치 */
export type TradeAlertPopupPosition = 'right' | 'left' | 'bottom';
/** 매매 알림 팝업 배치 방식 */
export type TradeAlertPopupLayout = 'stack' | 'grid' | 'strip' | 'single';
export const TRADE_ALERT_POPUP_POSITIONS: { id: TradeAlertPopupPosition; label: string; desc: string }[] = [
{ id: 'right', label: '화면 우측', desc: '우측 상단부터 아래로 쌓입니다 (기본)' },
{ id: 'left', label: '화면 좌측', desc: '좌측 상단부터 아래로 쌓입니다' },
{ id: 'bottom', label: '화면 하단', desc: '화면 하단 중앙에 표시됩니다' },
];
export const TRADE_ALERT_POPUP_LAYOUTS: { id: TradeAlertPopupLayout; label: string; desc: string }[] = [
{ id: 'stack', label: '세로 스택', desc: '알림을 위·아래로 순서대로 쌓아 표시' },
{ id: 'grid', label: '그리드 (N×N)', desc: '알림을 격자 형태로 배치' },
{ id: 'strip', label: '가로 나열', desc: '알림을 가로로 나열 (스크롤)' },
{ id: 'single', label: '최신 1건', desc: '가장 최근 알림 1건만 표시' },
];
export const TRADE_ALERT_GRID_COL_OPTIONS = [2, 3, 4] as const;
export function normalizeTradeAlertPopupPosition(raw?: string | null): TradeAlertPopupPosition {
if (raw === 'left' || raw === 'bottom') return raw;
return 'right';
}
export function normalizeTradeAlertPopupLayout(raw?: string | null): TradeAlertPopupLayout {
if (raw === 'grid' || raw === 'strip' || raw === 'single') return raw;
return 'stack';
}
export function normalizeTradeAlertGridCols(raw?: number | null): number {
const n = raw ?? 2;
return Math.min(4, Math.max(2, Math.round(n)));
}
/** CSS 클래스 조합 */
export function tradeAlertPopupClassNames(
position: TradeAlertPopupPosition,
layout: TradeAlertPopupLayout,
): { stack: string; cards: string } {
return {
stack: `tsn-stack tsn-stack--${position} tsn-layout--${layout}`,
cards: `tsn-cards tsn-cards--${layout}`,
};
}
const POSITION_SHORT: Record<TradeAlertPopupPosition, string> = {
right: '우측',
left: '좌측',
bottom: '하단',
};
const LAYOUT_SHORT: Record<TradeAlertPopupLayout, string> = {
stack: '스택',
grid: '그리드',
strip: '가로',
single: '1건',
};
export function tradeAlertPopupModeKey(
position: TradeAlertPopupPosition,
layout: TradeAlertPopupLayout,
): string {
return `${position}:${layout}`;
}
export function parseTradeAlertPopupModeKey(key: string): {
position: TradeAlertPopupPosition;
layout: TradeAlertPopupLayout;
} {
const [pos, lay] = key.split(':');
return {
position: normalizeTradeAlertPopupPosition(pos),
layout: normalizeTradeAlertPopupLayout(lay),
};
}
export function formatTradeAlertPopupMode(
position: TradeAlertPopupPosition,
layout: TradeAlertPopupLayout,
): string {
return `${POSITION_SHORT[position]} · ${LAYOUT_SHORT[layout]}`;
}
/** 메뉴바 드롭다운용 — 위치별 배치 옵션 */
export function buildTradeAlertPopupModeOptions(): {
position: TradeAlertPopupPosition;
layout: TradeAlertPopupLayout;
key: string;
label: string;
}[] {
const options: {
position: TradeAlertPopupPosition;
layout: TradeAlertPopupLayout;
key: string;
label: string;
}[] = [];
for (const pos of TRADE_ALERT_POPUP_POSITIONS) {
for (const lay of TRADE_ALERT_POPUP_LAYOUTS) {
options.push({
position: pos.id,
layout: lay.id,
key: tradeAlertPopupModeKey(pos.id, lay.id),
label: `${pos.label} · ${lay.label}`,
});
}
}
return options;
}
/** @deprecated useToastPageCapacity 훅 사용 */
export function getToastPageSize(
layout: TradeAlertPopupLayout,
gridCols: number,
): number {
switch (layout) {
case 'single': return 1;
case 'strip': return 4;
case 'grid': return normalizeTradeAlertGridCols(gridCols) * 4;
case 'stack':
default: return 5;
}
}