// === Shared UI helpers ===
const { useState, useEffect, useMemo, useRef, useCallback } = React;
const formatKRW = (n) => "₩" + Math.round(n).toLocaleString("ko-KR");
const formatNum = (n) => Math.round(n).toLocaleString("ko-KR");
const formatDate = (s) => s.split(" ")[0].replace(/-/g, ".");
// Toast manager
let toastSetter;
function ToastHost() {
const [toasts, setToasts] = useState([]);
toastSetter = setToasts;
useEffect(() => {
if (toasts.length === 0) return;
const t = setTimeout(() => setToasts(arr => arr.slice(1)), 2800);
return () => clearTimeout(t);
}, [toasts]);
return (
{toasts.map((t, i) => (
{t}
))}
);
}
function toast(msg) { toastSetter && toastSetter(arr => [...arr, msg]); }
window.toast = toast;
// Image placeholder using gradient — pseudo product photo
function ProductThumb({ tone = 0, name = "", size = 36, radius = 6 }) {
const [a, b] = window.MOCK.TONES[tone % window.MOCK.TONES.length];
const initial = name.replace(/[^가-힣A-Za-z]/g, "").slice(0, 2);
return (
{initial}
);
}
window.ProductThumb = ProductThumb;
// Modal
function Modal({ open, onClose, title, children, footer, size = "" }) {
if (!open) return null;
return (
e.stopPropagation()}>
{children}
{footer &&
{footer}
}
);
}
window.Modal = Modal;
// Status badge for products
function StatusBadge({ status }) {
const map = {
active: { label: "판매중", cls: "badge-success" },
outofstock: { label: "품절", cls: "badge-warn" },
paused: { label: "판매중지", cls: "" },
paid: { label: "결제완료", cls: "badge-info" },
shipped: { label: "배송중", cls: "badge-warn" },
delivered: { label: "배송완료", cls: "badge-success" },
};
const c = map[status] || { label: status, cls: "" };
return {c.label};
}
window.StatusBadge = StatusBadge;
// MiniSpark — sparkline chart
function MiniSpark({ data, height = 40, color = "var(--accent)" }) {
const max = Math.max(...data);
const min = Math.min(...data);
const w = 100;
const pts = data.map((v, i) => {
const x = (i / (data.length - 1)) * w;
const y = height - ((v - min) / (max - min || 1)) * (height - 4) - 2;
return `${x},${y}`;
}).join(" ");
const areaPts = `0,${height} ${pts} ${w},${height}`;
return (
);
}
window.MiniSpark = MiniSpark;