"use client"; import { useEffect, useRef, useState } from "react"; import { Upload } from "lucide-react"; import Shell from "@/components/Shell"; import EditableTable, { Col } from "@/components/EditableTable"; import { TableSkeleton } from "@/components/Skeleton"; import Thumb from "@/components/Thumb"; import { api, getAuth, ASSET_BASE } from "@/lib/api"; import { toastError } from "@/lib/toast"; type Catalog = Record[]>; const TABS: { key: string; label: string; cols: Col[]; tpl: Record }[] = [ { key: "coin", label: "سکه", cols: [ { key: "id", label: "شناسه" }, { key: "title", label: "عنوان" }, { key: "coins", label: "سکه", type: "number" }, { key: "vip_days", label: "VIP روز", type: "number" }, { key: "price_toman", label: "قیمت", type: "number" }, { key: "bonus_pct", label: "٪هدیه", type: "number" }, { key: "sku", label: "SKU", readonly: true }, { key: "sort", label: "ترتیب", type: "number" }, { key: "enabled", label: "فعال", type: "bool" }, ], tpl: { id: "", title: "", coins: 0, vip_days: 0, price_toman: 0, bonus_pct: 0, sort: 0, enabled: true }, }, { key: "ticket", label: "بلیط", cols: [ { key: "id", label: "شناسه" }, { key: "title", label: "عنوان" }, { key: "tickets", label: "بلیط", type: "number" }, { key: "price_toman", label: "قیمت", type: "number" }, { key: "sku", label: "SKU", readonly: true }, { key: "sort", label: "ترتیب", type: "number" }, { key: "enabled", label: "فعال", type: "bool" }, ], tpl: { id: "", title: "", tickets: 0, price_toman: 0, sort: 0, enabled: true }, }, { key: "card", label: "کارت", cols: [ { key: "id", label: "شناسه" }, { key: "title", label: "عنوان" }, { key: "price_coins", label: "قیمت (سکه)", type: "number" }, { key: "sort", label: "ترتیب", type: "number" }, { key: "enabled", label: "فعال", type: "bool" }, ], tpl: { id: "", title: "", price_coins: 0, sort: 0, enabled: true }, }, { key: "booster", label: "تجهیزات", cols: [ { key: "id", label: "شناسه" }, { key: "title", label: "عنوان" }, { key: "multiplier", label: "ضریب", type: "number" }, { key: "hours", label: "ساعت", type: "number" }, { key: "price_toman", label: "قیمت", type: "number" }, { key: "sku", label: "SKU", readonly: true }, { key: "sort", label: "ترتیب", type: "number" }, { key: "enabled", label: "فعال", type: "bool" }, ], tpl: { id: "", title: "", multiplier: 2, hours: 24, price_toman: 0, sort: 0, enabled: true }, }, { key: "vip", label: "VIP", cols: [ { key: "id", label: "شناسه" }, { key: "title", label: "عنوان" }, { key: "months", label: "ماه", type: "number" }, { key: "price_toman", label: "قیمت", type: "number" }, { key: "sku", label: "SKU", readonly: true }, { key: "sort", label: "ترتیب", type: "number" }, { key: "enabled", label: "فعال", type: "bool" }, ], tpl: { id: "", title: "", months: 1, price_toman: 0, sort: 0, enabled: true }, }, { key: "tier", label: "میزها", cols: [ { key: "id", label: "شناسه" }, { key: "title", label: "عنوان" }, { key: "hands", label: "دست", type: "number" }, { key: "entry", label: "ورودی", type: "number" }, { key: "prize", label: "جایزه", type: "number" }, { key: "xp", label: "XP", type: "number" }, { key: "trophy", label: "جام", type: "number" }, { key: "rank_reward", label: "رتبه", type: "number" }, { key: "sort", label: "ترتیب", type: "number" }, { key: "enabled", label: "فعال", type: "bool" }, ], tpl: { id: "", title: "", hands: 7, entry: 0, prize: 0, xp: 0, trophy: 0, rank_reward: 0, sort: 0, enabled: true }, }, ]; export default function ShopPage() { const [cat, setCat] = useState({}); const [tab, setTab] = useState("coin"); const [ver, setVer] = useState(1); const [loading, setLoading] = useState(true); async function load() { setLoading(true); try { setCat(await api.get("/catalog")); setVer((v) => v + 1); } finally { setLoading(false); } } useEffect(() => { load(); }, []); const active = TABS.find((t) => t.key === tab)!; const isCard = tab === "card"; return (
{TABS.map((t) => ( ))}
{loading ? ( ) : ( { await api.post(`/catalog/${tab}`, row); await load(); }} onDelete={async (id) => { if (!confirm("حذف آیتم؟")) return; await api.del(`/catalog/${tab}?id=${encodeURIComponent(id)}`); await load(); }} preview={ isCard ? (row) => String(row.id) === "simple" ? ( پیش‌فرض ) : ( ) : undefined } extra={isCard ? (row) => : undefined} /> )}

{isCard ? "برای هر اسکینِ کارت، یک فایلِ zip از تصاویرِ کارت‌ها (مثلِ AS.png، KH.png، back.jpg) آپلود کنید." : "SKU برای سکه/بلیط/تجهیزات/VIP هنگام ساخت خودکار تولید می‌شود؛ همان را در پنل مایکت/کافه‌بازار ثبت کنید."}

); } // آپلودِ zipِ اسکینِ کارت (به /catalog/card/{id}/upload، فیلد "deck"). function DeckUpload({ id, onDone }: { id: string; onDone: () => void }) { const ref = useRef(null); const [busy, setBusy] = useState(false); async function upload(file: File) { setBusy(true); try { const fd = new FormData(); fd.append("deck", file); const auth = getAuth(); const res = await fetch(`${ASSET_BASE}/admin/api/catalog/card/${encodeURIComponent(id)}/upload`, { method: "POST", headers: auth ? { Authorization: `Basic ${auth}` } : {}, body: fd, }); if (!res.ok) throw new Error("آپلودِ zip ناموفق بود"); onDone(); } catch (e) { toastError((e as Error).message); } finally { setBusy(false); } } return ( <> { const f = e.target.files?.[0]; if (f) upload(f); e.target.value = ""; }} /> ); }