/** * 최상단 글로벌 메뉴바 * * 레이아웃: * [로고] | [대시보드] [실시간차트] [전략편집기] … | [테마토글] [로그인] */ import React, { memo } from 'react'; import type { Theme } from '../types'; import type { AuthSession } from '../utils/auth'; import TradeAlertPopupMenubarSelect from './TradeAlertPopupMenubarSelect'; import type { TradeAlertPopupLayout, TradeAlertPopupPosition } from '../utils/tradeAlertPopupLayout'; import { canAccessMenu } from '../utils/permissions'; export type MenuPage = 'dashboard' | 'chart' | 'paper' | 'virtual' | 'trend-search' | 'verification-board' | 'strategy' | 'strategy-editor' | 'backtest' | 'notifications' | 'settings'; interface TopMenuBarProps { activePage: MenuPage; theme: Theme; onPage: (page: MenuPage) => void; onTheme: () => void; /** 미확인 매매 시그널 알림 수 */ tradeNotifyUnread?: number; onOpenNotifications?: () => void; /** 모바일 앱 다운로드 모달 */ onOpenAppDownload?: () => void; /** 우측에 떠 있는 알림 팝업(토스트) 개수 */ tradeNotifyToastCount?: number; /** 모든 알림 팝업 닫기 */ onDismissAllNotifyPopups?: () => void; /** 알림 팝업 표시 위치·방식 */ tradeAlertPopupPosition?: string; tradeAlertPopupLayout?: string; tradeAlertPopupGridCols?: number; onTradeAlertPopupPosition?: (v: TradeAlertPopupPosition) => void; onTradeAlertPopupLayout?: (v: TradeAlertPopupLayout) => void; onTradeAlertPopupGridCols?: (v: number) => void; /** 로그인 사용자 (null = 비로그인·기기별 설정) */ authUser?: AuthSession | null; /** 게스트 모드(스플래시에서 게스트 진입) */ guestMode?: boolean; onLoginClick?: () => void; onLogout?: () => void; /** 메뉴별 접근 허용 (없으면 전체 표시) */ menuPermissions?: Record; } // ── SVG 아이콘 ──────────────────────────────────────────────────────────── const IcDashboard = () => ( ); const IcChart = () => ( ); const IcBacktest = () => ( ); const IcSettings = () => ( ); const IcAppDownload = () => ( ); const IcNotify = () => ( ); /** 알림 팝업 전체 닫기 */ const IcDismissPopups = () => ( ); const IcLogin = () => ( ); // ── 테마 아이콘 ─────────────────────────────────────────────────────────── const THEME_CONFIG: Record = { dark: { icon: '🌙', label: '다크', next: 'blue' }, blue: { icon: '🌊', label: '블루', next: 'light' }, light: { icon: '☀️', label: '라이트', next: 'dark' }, }; const IcStrategyEditor = () => ( ); const IcPaper = () => ( ); const IcVirtual = () => ( ); const IcTrendSearch = () => ( ); const IcVerificationBoard = () => ( ); const MENU_ITEMS: { page: MenuPage; label: string; icon: React.ReactNode }[] = [ { page: 'dashboard', label: '대시보드', icon: }, { page: 'chart', label: '실시간차트', icon: }, { page: 'paper', label: '모의투자', icon: }, { page: 'virtual', label: '가상매매', icon: }, { page: 'trend-search', label: '추세검색', icon: }, { page: 'strategy-editor', label: '전략편집기', icon: }, { page: 'backtest', label: '백테스팅', icon: }, { page: 'notifications', label: '알림목록', icon: }, { page: 'settings', label: '설정', icon: }, { page: 'verification-board', label: '검증게시판', icon: }, ]; export const TopMenuBar = memo(function TopMenuBar({ activePage, theme, onPage, onTheme, tradeNotifyUnread = 0, onOpenNotifications, onOpenAppDownload, tradeNotifyToastCount = 0, onDismissAllNotifyPopups, tradeAlertPopupPosition = 'right', tradeAlertPopupLayout = 'stack', tradeAlertPopupGridCols = 2, onTradeAlertPopupPosition, onTradeAlertPopupLayout, onTradeAlertPopupGridCols, authUser = null, guestMode = false, onLoginClick, onLogout, menuPermissions, }: TopMenuBarProps) { const tc = THEME_CONFIG[theme]; const visibleItems = menuPermissions ? MENU_ITEMS.filter(({ page }) => canAccessMenu(menuPermissions, page)) : MENU_ITEMS; const showNotifications = menuPermissions == null || menuPermissions.notifications === true; return (
{/* 로고 */}
GoldenChart
{/* 내비게이션 메뉴 */}
); }); export default TopMenuBar;