// === Dashboard screen === function Dashboard({ goto, products, orders, productsSource, ordersSource, ordersLoading, ordersDays, productsMeta }) { const { PRODUCTS, ORDERS, SALES_TREND } = window.MOCK; const isLive = productsSource === "live" || ordersSource === "live"; // 사용할 데이터 소스 const usedProducts = productsSource === "live" ? products : PRODUCTS; const usedOrders = ordersSource === "live" ? orders : ORDERS; // 라이브 통계 계산 (orders 기반) const liveStats = useMemo(() => { if (ordersSource !== "live") return null; // 매출 인정 상태: paid/shipped/delivered (취소/반품 제외) const validOrders = usedOrders.filter(o => ["paid", "shipped", "delivered"].includes(o.status)); // 일별 매출/주문수 const byDate = new Map(); validOrders.forEach(o => { const date = (o.date || "").slice(0, 10); if (!date) return; if (!byDate.has(date)) byDate.set(date, { revenue: 0, orders: 0 }); const e = byDate.get(date); e.revenue += o.totalPaymentAmount || 0; e.orders++; }); // 트렌드 라인 (ordersDays 기간만큼) const trendDays = ordersDays || 7; const trend = []; for (let i = trendDays - 1; i >= 0; i--) { const d = new Date(Date.now() - i * 24 * 3600 * 1000); const isoDate = d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0"); const label = String(d.getMonth() + 1).padStart(2, "0") + "/" + String(d.getDate()).padStart(2, "0"); const entry = byDate.get(isoDate) || { revenue: 0, orders: 0 }; trend.push({ d: label, isToday: i === 0, revenue: entry.revenue, orders: entry.orders }); } // 베스트 상품 (orders item 합산) const productSales = new Map(); validOrders.forEach(o => { o.items.forEach(it => { const pid = it.pid; if (!pid) return; if (!productSales.has(pid)) productSales.set(pid, { pid, name: it.name || "", qty: 0, revenue: 0 }); const e = productSales.get(pid); e.qty += it.qty; e.revenue += (it.price || 0) * it.qty; }); }); const topProducts = Array.from(productSales.values()).sort((a, b) => b.qty - a.qty).slice(0, 5); return { trend, todayRevenue: trend[trend.length - 1]?.revenue || 0, yesterdayRevenue: trend[trend.length - 2]?.revenue || 0, totalRevenue: trend.reduce((s, e) => s + e.revenue, 0), totalOrders: trend.reduce((s, e) => s + e.orders, 0), newOrders: usedOrders.filter(o => o.status === "paid").length, canceledOrders: usedOrders.filter(o => o.status === "canceled").length, topProducts, recentOrders: usedOrders.slice(0, 5), validCount: validOrders.length, }; }, [ordersSource, usedOrders, ordersDays]); // 표시할 값 (라이브 vs mock) const todayRevenue = liveStats ? liveStats.todayRevenue : SALES_TREND[SALES_TREND.length - 1].revenue; const yesterdayRevenue = liveStats ? liveStats.yesterdayRevenue : SALES_TREND[SALES_TREND.length - 2].revenue; const revenueChange = yesterdayRevenue > 0 ? ((todayRevenue - yesterdayRevenue) / yesterdayRevenue) * 100 : 0; const totalRevenue = liveStats ? liveStats.totalRevenue : SALES_TREND.reduce((s, d) => s + d.revenue, 0); const totalOrders = liveStats ? liveStats.totalOrders : SALES_TREND.reduce((s, d) => s + d.orders, 0); const newOrders = liveStats ? liveStats.newOrders : usedOrders.filter(o => o.status === "paid").length; const outOfStock = usedProducts.filter(p => p.status === "outofstock").length; const activeProducts = usedProducts.filter(p => p.status === "active").length; const totalProducts = productsSource === "live" ? (productsMeta?.totalElements || usedProducts.length) : usedProducts.length; const topProducts = liveStats ? liveStats.topProducts : [...usedProducts].sort((a, b) => b.sales30d - a.sales30d).slice(0, 5); const recentOrders = liveStats ? liveStats.recentOrders : usedOrders.slice(0, 5); const trendData = liveStats ? liveStats.trend : SALES_TREND.map(d => ({ ...d, isToday: d.d === "05/10" })); const chartMax = Math.max(1, ...trendData.map(d => d.revenue)); const trendLabel = liveStats ? `최근 ${ordersDays || 7}일` : "최근 14일"; const today = new Date(); const todayLabel = `${today.getFullYear()}년 ${today.getMonth() + 1}월 ${today.getDate()}일`; return (
{todayLabel} · {isLive ? "네이버 라이브" : "샘플 데이터"} {isLive && liveStats && ` · 실 매출 인정 주문 ${liveStats.validCount}건${liveStats.canceledOrders > 0 ? ` · 취소 ${liveStats.canceledOrders}` : ""}`}