import type {ComponentType, ReactNode} from 'react'; import {Link, NavLink, useLocation} from 'react-router'; import {LayoutGrid, LogOut, Search, Wand2} from 'lucide-react'; import {cn} from '@/lib/utils'; import {userLabel, useAuthStore} from '@/stores/auth'; export type NavItem = { to: string; /** 활성 표시용 경로. 쿼리스트링이 붙은 `to` 로는 pathname 을 비교할 수 없다. */ match: string; label: string; icon: ComponentType<{className?: string}>; }; /** * ★ 메뉴를 이 파일에 하드코딩하지 않는다 — 앱마다 다르고, **섞이면 새어 나간다.** * 내부 메뉴(`/places`, `/local-content`)를 여기 두면 그 경로 이름이 사장님 번들에 * 문자열로 남는다(실측: 앱을 가른 뒤에도 dist 에서 `local-content` 가 나왔다). * 앱을 가른 이유가 그거라 메뉴도 앱이 들고 온다. 내부 메뉴는 `admin/src/app/router.tsx`. * * ★ 빌더는 `?new=1` 로 간다. 그냥 `/builder` 로 보내면 저장된 위저드 상태가 복원돼 * 지난번에 편집하던 가게의 에디터가 뜬다(BuilderPage 주석) — 새로 만들러 누른 사람에게는 * 남의 화면이다. */ const OWNER_NAV: NavItem[] = [ {to: '/builder?new=1', match: '/builder', label: '새 사이트', icon: Wand2}, ]; export function AppShell({children, nav = OWNER_NAV}: {children: ReactNode; nav?: NavItem[]}) { const user = useAuthStore((s) => s.user); const signOut = useAuthStore((s) => s.signOut); const location = useLocation(); return (
{description}
}{title}
{description &&{description}
} {action &&