import { useEffect, useState } from 'react' import { Outlet, Navigate, NavLink, Link, useNavigate } from 'react-router-dom' import { LayoutDashboard, Store, Flower2, Boxes, ShoppingBag, Users, Crown, Megaphone, Repeat, CalendarClock, BarChart3, UserCog, ScrollText, Settings, LogOut, UserCircle, ArrowLeftRight, Smartphone, ClipboardList, CalendarDays, Mail, PieChart, Sparkles, Cpu, ShieldCheck, KeySquare, ListTree, Menu as MenuIcon, Building2, Briefcase, BrainCircuit, } from 'lucide-react' import { useTranslation } from 'react-i18next' import { getMe } from '../api/client' import LanguageSwitcher from '../i18n/LanguageSwitcher' const links = [ { to: '/admin/dashboard', key: 'dashboard', icon: LayoutDashboard, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/stores', key: 'stores', icon: Store, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/products', key: 'products', icon: Flower2, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/inventory', key: 'inventory', icon: Boxes, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/orders', key: 'orders', icon: ShoppingBag, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/transfers', key: 'transfers', icon: ArrowLeftRight, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/members', key: 'members', icon: Users, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/loyalty', key: 'loyalty', icon: Crown, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/events', key: 'events', icon: Megaphone, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/subscriptions', key: 'subscriptions', icon: Repeat, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/schedule', key: 'schedule', icon: CalendarClock, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/analytics', key: 'analytics', icon: BarChart3, roles: ['ADMIN', 'MANAGER'] }, ] const adminLinks = [ { to: '/admin/users', key: 'users', icon: UserCog, roles: ['ADMIN'] }, { to: '/admin/audit', key: 'audit', icon: ScrollText, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/settings', key: 'settings', icon: Settings, roles: ['ADMIN'] }, { to: '/admin/app', key: 'appInstall', icon: Smartphone, roles: ['ADMIN', 'MANAGER'] }, ] // 최신 AI 기법(중앙 guardia-rag) 토글 — 라벨 i18n 미의존(고정 표기), 변경은 MANAGER+(USER 차단) const aiLinks = [ { to: '/admin/wise-ai', label: 'WISE AI', icon: BrainCircuit, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/ai-techniques', label: 'AI Techniques', icon: Sparkles, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/ai-platform', label: 'AI 플랫폼 설정', icon: Cpu, roles: ['ADMIN'] }, ] // UIWS 이식 — 업무 모듈(관리자 영역 병합). 라벨은 i18n 미의존(고정 한/영 안전 표기). const uiwsLinks = [ { to: '/admin/uiws/worklog', label: '업무일지 Worklog', icon: ClipboardList, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/uiws/schedule', label: '일정 Schedule', icon: CalendarDays, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/uiws/message', label: '쪽지 Message', icon: Mail, roles: ['ADMIN', 'MANAGER'] }, { to: '/admin/uiws/stats', label: '업무통계 Stats', icon: PieChart, roles: ['ADMIN', 'MANAGER'] }, ] // UIWS 시스템관리(권한 RBAC) — SuperAdmin(ADMIN) 전용. 고객앱/기존 admin 보존, 백엔드 권한과 이중 가드. const sysLinks = [ { to: '/admin/uiws/system/roles', label: '권한 관리', icon: ShieldCheck, roles: ['ADMIN'] }, { to: '/admin/uiws/system/role-menus', label: '역할-메뉴 권한', icon: KeySquare, roles: ['ADMIN'] }, { to: '/admin/uiws/system/codes', label: '공통코드', icon: ListTree, roles: ['ADMIN'] }, { to: '/admin/uiws/system/menus', label: '메뉴 관리', icon: MenuIcon, roles: ['ADMIN'] }, { to: '/admin/uiws/system/depts', label: '부서 관리', icon: Building2, roles: ['ADMIN'] }, { to: '/admin/uiws/system/companies', label: '거래처 관리', icon: Briefcase, roles: ['ADMIN'] }, ] const linkClass = ({ isActive }: { isActive: boolean }) => `flex items-center gap-3 px-5 py-2.5 text-sm transition-colors ${isActive ? 'bg-card text-brand border-r-2 border-brand' : 'text-slate-300 hover:bg-card/60'}` export default function AdminLayout() { const { t } = useTranslation() const token = localStorage.getItem('mall_admin_token') const [role, setRole] = useState(() => localStorage.getItem('mall_role') || '') const [who, setWho] = useState(() => localStorage.getItem('mall_admin_user') || '') const nav = useNavigate() useEffect(() => { document.documentElement.classList.add('admin-shell') return () => document.documentElement.classList.remove('admin-shell') }, []) useEffect(() => { if (!token) return getMe().then((me: any) => { if (me?.role) { localStorage.setItem('mall_role', me.role); setRole(me.role) } if (me?.username) { localStorage.setItem('mall_admin_user', me.username); setWho(me.username) } }).catch(() => {}) }, [token]) if (!token) return // Block USER role from accessing the admin area if (role && role === 'USER') return const visible = links.filter(l => !role || l.roles.includes(role)) const visibleAdmin = adminLinks.filter(l => l.roles.includes(role)) const visibleAi = aiLinks.filter(l => !role || l.roles.includes(role)) const visibleUiws = uiwsLinks.filter(l => !role || l.roles.includes(role)) const visibleSys = sysLinks.filter(l => l.roles.includes(role)) // ADMIN 전용(role 비어있으면 비표시) const logout = () => { localStorage.removeItem('mall_admin_token'); localStorage.removeItem('mall_role'); localStorage.removeItem('mall_admin_user') nav('/admin/login') } return (
{t('admin.header')}
{who || 'admin'} {role}
) }