// === Main app shell === const { useState: useStateApp, useEffect: useEffectApp } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "theme": "light" }/*EDITMODE-END*/; function App() { const [route, setRoute] = useStateApp("dashboard"); const [products, setProducts] = useStateApp(window.MOCK.PRODUCTS); const [orders, setOrders] = useStateApp(window.MOCK.ORDERS); const [detailId, setDetailId] = useStateApp(null); const [sidebarOpen, setSidebarOpen] = useStateApp(false); const [tweaksOpen, setTweaksOpen] = useStateApp(false); // 데이터 소스: mock(샘플) vs live(네이버 실제). loading/error는 별도. const [productsSource, setProductsSource] = useStateApp("mock"); const [productsLoading, setProductsLoading] = useStateApp(false); const [productsError, setProductsError] = useStateApp(null); const [productsMeta, setProductsMeta] = useStateApp(null); const loadNaverProducts = (opts) => { setProductsLoading(true); setProductsError(null); return window.API.naverFetchProducts({ page: 1, size: 100, ...(opts || {}) }) .then(({ products: live, ...meta }) => { setProducts(live); setProductsSource("live"); setProductsMeta(meta); window.toast && window.toast(`네이버 상품 ${live.length}개 불러옴 (전체 ${meta.totalElements}개)`); }) .catch(err => { console.error("[naverFetchProducts]", err); setProductsError(err.message); window.toast && window.toast("네이버 상품 조회 실패: " + err.message); }) .finally(() => setProductsLoading(false)); }; // 마운트 시 자격증명 있으면 자동 로드 useEffectApp(() => { if (window.API.naverConfigured()) { loadNaverProducts(); } }, []); // Theme tweak const [tweaks, setTweak] = window.useTweaks ? window.useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}]; useEffectApp(() => { document.documentElement.setAttribute("data-theme", tweaks.theme); }, [tweaks.theme]); // Tweaks panel host registration useEffectApp(() => { const handler = (e) => { if (!e.data || typeof e.data !== "object") return; if (e.data.type === "__activate_edit_mode") setTweaksOpen(true); if (e.data.type === "__deactivate_edit_mode") setTweaksOpen(false); }; window.addEventListener("message", handler); window.parent.postMessage({ type: "__edit_mode_available" }, "*"); return () => window.removeEventListener("message", handler); }, []); const navItems = [ { key: "dashboard", label: "대시보드", icon: window.I.Dashboard }, { key: "products", label: "상품 관리", icon: window.I.Box, badge: products.filter(p => p.status === "outofstock").length || null }, { key: "bulk", label: "일괄 가격 수정", icon: window.I.Tag }, { key: "orders", label: "주문/판매 내역", icon: window.I.ShoppingCart, badge: orders.filter(o => o.status === "paid").length || null }, { key: "shipping", label: "로젠 송장 출력", icon: window.I.Truck }, { key: "isvm", label: "ISVM 상품 연동", icon: window.I.Plug }, { key: "settings", label: "API 설정", icon: window.I.Settings }, ]; const goto = (k) => { setRoute(k); setSidebarOpen(false); window.scrollTo(0, 0); }; const openDetail = (pid) => setDetailId(pid); const closeDetail = () => setDetailId(null); const titleMap = { dashboard: "대시보드", products: "상품 관리", bulk: "일괄 가격 수정", orders: "주문/판매 내역", shipping: "로젠 송장 출력", isvm: "ISVM 상품 연동", settings: "API 설정" }; return (