"use client"; import { useEffect, useState } from "react"; import { Search, Coins, Gift, Loader2 } from "lucide-react"; import Shell from "@/components/Shell"; import NumberInput, { fmtNum } from "@/components/NumberInput"; import Badge from "@/components/Badge"; import Empty from "@/components/Empty"; import { TableSkeleton } from "@/components/Skeleton"; import { api } from "@/lib/api"; import { toastError } from "@/lib/toast"; type User = { id: number; mobile: string; first_name: string | null; coins: number; rank_points: number; is_admin: number; }; export default function UsersPage() { const [q, setQ] = useState(""); const [users, setUsers] = useState([]); const [sel, setSel] = useState(null); const [loading, setLoading] = useState(true); async function load(query = "") { setLoading(true); try { const r = await api.get<{ users: User[] }>( `/users${query ? `?q=${encodeURIComponent(query)}` : ""}`, ); setUsers(r.users || []); } finally { setLoading(false); } } useEffect(() => { load(); }, []); return (
{ e.preventDefault(); load(q); }} className="flex gap-2 mb-4" > setQ(e.target.value)} />
{loading ? ( ) : users.length === 0 ? ( ) : (
{users.map((u) => ( ))}
# موبایل نام سکه امتیاز رتبه ادمین
{u.id} {u.mobile} {u.first_name || "—"} {fmtNum(u.coins)} {fmtNum(u.rank_points)} {u.is_admin ? مدیر : ""}
)} {sel && setSel(null)} onDone={() => load(q)} />}
); } function ManageUser({ user, onClose, onDone, }: { user: User; onClose: () => void; onDone: () => void; }) { const [coins, setCoins] = useState(0); const [tickets, setTickets] = useState(0); const [vipDays, setVipDays] = useState(30); const [busy, setBusy] = useState(false); async function run(fn: () => Promise) { setBusy(true); try { await fn(); onDone(); } catch (e) { toastError((e as Error).message); } finally { setBusy(false); } } return (
e.stopPropagation()}>

{user.first_name || user.mobile}

{user.mobile} · سکه: {fmtNum(user.coins)}

); }