import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom' import { AppstoreOutlined, CalendarOutlined, ShoppingCartOutlined, } from '@ant-design/icons' import SchedulePanel from './SchedulePanel' import BizCareLogo from './BizCareLogo' import AccountPopover from './AccountPopover' import { careMenuSections, filterMenuSections, resolveSelectedKey, sectionContainsPath, shopMenuSections } from '../menu' import { fetchMyMenus } from '../api/auth' import { THEMES } from '../theme' import { useTheme } from '../themeContext' const PANEL_MIN = 170 const PANEL_MAX = 420 type Props = { shop?: boolean } export default function AgentShell({ shop = false }: Props) { const navigate = useNavigate() const location = useLocation() const { theme, changeTheme } = useTheme() const [scheduleOpen, setScheduleOpen] = useState(false) const userName = localStorage.getItem('userName') || (shop ? '판매점' : '관리자') const [allowedMenus, setAllowedMenus] = useState(() => { if (shop) return null try { const cached = localStorage.getItem('allowedMenus') return cached ? (JSON.parse(cached) as string[]) : [] } catch { return [] } }) const [panelWidth, setPanelWidth] = useState(() => { const v = Number(localStorage.getItem('lp.width')) return v >= PANEL_MIN && v <= PANEL_MAX ? v : 220 }) const [collapsed, setCollapsed] = useState(() => localStorage.getItem('lp.collapsed') === '1') const draggingRef = useRef(false) const [dragging, setDragging] = useState(false) useEffect(() => { if (shop) { setAllowedMenus(null) return } let cancelled = false fetchMyMenus() .then((res) => { if (cancelled) return if (res.staffPermission) localStorage.setItem('staffPermission', res.staffPermission) setAllowedMenus(res.menus || []) try { localStorage.setItem('allowedMenus', JSON.stringify(res.menus || [])) } catch { /* ignore */ } }) .catch(() => { if (cancelled) return try { const cached = localStorage.getItem('allowedMenus') if (cached) setAllowedMenus(JSON.parse(cached) as string[]) else setAllowedMenus(['home']) } catch { setAllowedMenus(['home']) } }) return () => { cancelled = true } }, [shop]) const allSections = useMemo(() => (shop ? shopMenuSections() : careMenuSections()), [shop]) const sections = useMemo( () => (shop ? allSections : filterMenuSections(allSections, allowedMenus)), [shop, allSections, allowedMenus], ) const selectedKey = resolveSelectedKey(location.pathname, location.search) const [openCards, setOpenCards] = useState>({}) useEffect(() => { setOpenCards((prev) => { const next = { ...prev } sections.forEach((sec) => { // 기본은 접힘. 현재 경로가 속한 섹션만 펼침 if (next[sec.id] === undefined) { next[sec.id] = sectionContainsPath(sec, location.pathname) } if (sectionContainsPath(sec, location.pathname)) next[sec.id] = true }) return next }) }, [location.pathname, location.search, sections]) useEffect(() => { localStorage.setItem('lp.width', String(panelWidth)) }, [panelWidth]) useEffect(() => { localStorage.setItem('lp.collapsed', collapsed ? '1' : '0') }, [collapsed]) const startResize = useCallback((e: React.MouseEvent) => { e.preventDefault() draggingRef.current = true setDragging(true) document.body.style.userSelect = 'none' document.body.style.cursor = 'col-resize' }, []) useEffect(() => { const onMove = (e: MouseEvent) => { if (!draggingRef.current) return setPanelWidth(Math.min(PANEL_MAX, Math.max(PANEL_MIN, e.clientX))) } const onUp = () => { if (!draggingRef.current) return draggingRef.current = false setDragging(false) document.body.style.userSelect = '' document.body.style.cursor = '' } window.addEventListener('mousemove', onMove) window.addEventListener('mouseup', onUp) return () => { window.removeEventListener('mousemove', onMove) window.removeEventListener('mouseup', onUp) } }, []) const logout = () => { const theme = localStorage.getItem('bizcare_ui_theme') localStorage.clear() if (theme) localStorage.setItem('bizcare_ui_theme', theme) navigate('/login') } const toggleCard = (id: string) => { setOpenCards((prev) => ({ ...prev, [id]: !prev[id] })) } return (
{!collapsed && (
)}
{shop ? ( 에이전트 데모 / {userName} ) : (
문자발송(장바구니) 잔여SMS 996건
)}
{!shop && ( <> )}
{!collapsed && ( )} {!collapsed && (
)}
{!shop && setScheduleOpen(false)} />}
) }