'use client'; import Styles from '../styles/layout.module.scss'; import { useCallback, useEffect, useRef } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import useAuth from '@/hooks/useAuth'; import useDragScroll from '@/hooks/useDragScroll'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faBars, faXmark, faCartShopping, faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons'; import NotificationBell from '@/app/component/NotificationBell'; import Profile from '@/app/component/Profile'; import Logo from '@/app/component/Logo'; import PointChargeIcon from '@/public/icons/layout/point.svg'; import useCart from '@/hooks/useCart'; import { FEATURE_CHANNEL } from '@/constants/features'; // 채널/방송 메뉴(생방송·크리에이터)는 채널 기능 ON 일 때만 노출 const channelNavItems = [ { href: '/live', label: '생방송' }, { href: '/creators', label: '크리에이터' } ]; const baseNavItems = [ { href: '/games', label: '게임' }, { href: '/feed/all', label: '피드' }, { href: '/store', label: '상점' }, { href: '/attendance', label: '출석부' }, { href: '/board/notice', label: '고객지원' } ]; const navItems = FEATURE_CHANNEL ? [...channelNavItems, ...baseNavItems] : baseNavItems; const SCROLL_AMOUNT = 120; type Props = { sidebarOpen: boolean; onToggle: () => void; }; export default function Header({ sidebarOpen, onToggle }: Props) { const { isAuthenticated } = useAuth(); const { totalCount: cartCount } = useCart(); const pathname = usePathname(); const dragScroll = useDragScroll(); const searchRef = useRef(null); // 통합 검색 포커스 단축키: Ctrl+K(⌘+K) / '/' (finviz 관례) — 검색 동작 자체는 후속 useEffect(() => { const handler = (e: KeyboardEvent) => { if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); searchRef.current?.focus(); return; } if (e.key === '/' && !e.ctrlKey && !e.metaKey && !e.altKey) { const target = e.target as HTMLElement|null; const tag = target?.tagName; if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target?.isContentEditable) { return; } e.preventDefault(); searchRef.current?.focus(); } }; window.addEventListener('keydown', handler); return () => { window.removeEventListener('keydown', handler); }; }, []); const scrollTabs = useCallback((dir: 'left' | 'right') => { const el = dragScroll.ref.current; if (!el) { return; } el.scrollBy({ left: dir === 'left' ? -SCROLL_AMOUNT : SCROLL_AMOUNT, behavior: 'smooth' }); }, [dragScroll.ref]); const handlePopupCharge = useCallback(() => { const w = 450, h = 635; const left = window.screenX + (window.outerWidth - w) / 2; const top = window.screenY + (window.outerHeight - h) / 2; window.open('/charge', 'charge', `width=${w},height=${h},left=${left},top=${top},scrollbars=no,resizable=no`); }, []); return ( ); }