89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useState } from "react";
|
||
import Shell from "@/components/Shell";
|
||
import EditableTable, { Col } from "@/components/EditableTable";
|
||
import { api } from "@/lib/api";
|
||
|
||
type Row = Record<string, unknown>;
|
||
|
||
const COLS: Col[] = [
|
||
{ key: "id", label: "شناسه" },
|
||
{ key: "title", label: "عنوان" },
|
||
{ key: "price_coins", label: "قیمت (سکه)", type: "number" },
|
||
{ key: "vip", label: "VIP رایگان", type: "bool" },
|
||
{ key: "c1", label: "رنگ ۱ (hex)" },
|
||
{ key: "c2", label: "رنگ ۲ (hex)" },
|
||
{ key: "sort", label: "ترتیب", type: "number" },
|
||
{ key: "enabled", label: "فعال", type: "bool" },
|
||
];
|
||
|
||
const hex = (s: unknown) => {
|
||
const v = String(s || "").replace("#", "").trim();
|
||
return /^[0-9a-fA-F]{6}$/.test(v) ? `#${v}` : null;
|
||
};
|
||
|
||
function FramePreview({ row }: { row: Record<string, unknown> }) {
|
||
const a = hex(row.c1);
|
||
const b = hex(row.c2);
|
||
if (!a || !b) {
|
||
return <span className="text-[#8aa] text-xs">رتبه</span>;
|
||
}
|
||
return (
|
||
<div
|
||
style={{
|
||
width: 34,
|
||
height: 34,
|
||
borderRadius: "50%",
|
||
background: `linear-gradient(160deg, ${a}, ${b})`,
|
||
border: "1px solid #1e3a63",
|
||
}}
|
||
/>
|
||
);
|
||
}
|
||
|
||
export default function FramesPage() {
|
||
const [rows, setRows] = useState<Row[]>([]);
|
||
|
||
async function load() {
|
||
const r = await api.get<{ frames: Row[] }>("/frames");
|
||
setRows(r.frames || []);
|
||
}
|
||
useEffect(() => {
|
||
load();
|
||
}, []);
|
||
|
||
return (
|
||
<Shell title="قابها">
|
||
<p className="text-sm text-[#8aa] mb-4">
|
||
قابِ آواتار (کازمتیک). رنگِ گرادیان را با دو کدِ hex (مثلِ <code>F3D27A</code>) تعیین
|
||
کنید؛ قابِ جدید بدونِ بهروزرسانیِ اپ در بازی دیده میشود. شناسهٔ <code>none</code> = قابِ رتبه.
|
||
</p>
|
||
<EditableTable
|
||
cols={COLS}
|
||
rows={rows}
|
||
newTemplate={{
|
||
id: "",
|
||
title: "",
|
||
price_coins: 0,
|
||
vip: false,
|
||
c1: "",
|
||
c2: "",
|
||
sort: 0,
|
||
enabled: true,
|
||
}}
|
||
onSave={async (row) => {
|
||
await api.post("/frames", row);
|
||
await load();
|
||
}}
|
||
onDelete={async (id) => {
|
||
if (!confirm("حذف قاب؟")) return;
|
||
await api.del(`/frames?id=${encodeURIComponent(id)}`);
|
||
await load();
|
||
}}
|
||
preview={(row) => <FramePreview row={row} />}
|
||
/>
|
||
</Shell>
|
||
);
|
||
}
|