Files
2026-08-07 09:40:16 +03:30

117 lines
3.7 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { Trash2, Plus } from "lucide-react";
import Shell from "@/components/Shell";
import EditableTable, { Col } from "@/components/EditableTable";
import { api } from "@/lib/api";
type Row = Record<string, unknown>;
const PACK_COLS: Col[] = [
{ key: "id", label: "شناسه" },
{ key: "title", label: "عنوان" },
{ key: "kind", label: "نوع (text/emoji)" },
{ key: "price_coins", label: "قیمت (سکه)", type: "number" },
{ key: "vip", label: "VIP رایگان", type: "bool" },
{ key: "sort", label: "ترتیب", type: "number" },
];
export default function ChatPage() {
const [packs, setPacks] = useState<Row[]>([]);
const [messages, setMessages] = useState<Row[]>([]);
const [sel, setSel] = useState<string>("");
const [newMsg, setNewMsg] = useState("");
async function load() {
const r = await api.get<{ packs: Row[]; messages: Row[] }>("/chat");
setPacks(r.packs || []);
setMessages(r.messages || []);
if (!sel && r.packs?.length) setSel(String(r.packs[0].id));
}
useEffect(() => {
load();
}, []); // eslint-disable-line react-hooks/exhaustive-deps
const packMsgs = messages.filter((m) => String(m.pack_id) === sel);
async function addMsg() {
if (!sel || !newMsg.trim()) return;
await api.post("/chat/message", { pack_id: sel, body: newMsg.trim(), sort: packMsgs.length });
setNewMsg("");
await load();
}
return (
<Shell title="چت">
<h2 className="font-bold mb-3">بسته‌ها</h2>
<EditableTable
cols={PACK_COLS}
rows={packs}
newTemplate={{ id: "", title: "", kind: "text", price_coins: 0, vip: false, sort: 0 }}
onSave={async (row) => {
await api.post("/chat/pack", row);
await load();
}}
onDelete={async (id) => {
if (!confirm("حذف بسته و پیام‌هایش؟")) return;
await api.del(`/chat/pack?id=${encodeURIComponent(id)}`);
await load();
}}
/>
<div className="flex items-center gap-2 mt-6 mb-3">
<h2 className="font-bold">پیام‌ها</h2>
<select
className="inp w-auto"
value={sel}
onChange={(e) => setSel(e.target.value)}
>
{packs.map((p) => (
<option key={String(p.id)} value={String(p.id)}>
{String(p.title)}
</option>
))}
</select>
</div>
<div className="card p-4">
<div className="flex gap-2 mb-4">
<input
className="inp"
placeholder="پیام یا شکلکِ جدید…"
value={newMsg}
onChange={(e) => setNewMsg(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && addMsg()}
/>
<button className="btn btn-gold flex items-center gap-1" onClick={addMsg}>
<Plus size={16} /> افزودن
</button>
</div>
<div className="flex flex-wrap gap-2">
{packMsgs.map((m) => (
<span
key={String(m.id)}
className="inline-flex items-center gap-2 px-3 py-1.5 rounded-lg bg-[var(--panel-2)] border border-[#16305a]"
>
{String(m.body)}
<button
onClick={async () => {
await api.del(`/chat/message?id=${m.id}`);
await load();
}}
className="text-red-400"
>
<Trash2 size={13} />
</button>
</span>
))}
{packMsgs.length === 0 && (
<span className="text-[#8aa] text-sm">پیامی نیست</span>
)}
</div>
</div>
</Shell>
);
}