"use client"; import { useCallback, useEffect, useState } from "react"; import { RefreshCcw, Search, Coins } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { opsApi } from "@/lib/ops-api"; import type { OpsUser, LeaderboardEntry } from "@/types/ops"; function leaderboardName(entry: LeaderboardEntry) { const username = String(entry.username || "").trim(); if (username) return username; if (entry.telegram_id != null) return `TG${entry.telegram_id}`; return "未知用户"; } export function UsersPageClient() { const [query, setQuery] = useState(""); const [searching, setSearching] = useState(false); const [users, setUsers] = useState([]); const [leaderboard, setLeaderboard] = useState([]); const [grantEmail, setGrantEmail] = useState(""); const [grantPoints, setGrantPoints] = useState(100); const [grantResult, setGrantResult] = useState(""); const [grantBusy, setGrantBusy] = useState(false); const search = useCallback(async () => { if (!query.trim()) return; setSearching(true); try { const data = await opsApi.users(query.trim()); setUsers((data as unknown as { users?: OpsUser[] }).users ?? []); } catch { /* */ } setSearching(false); }, [query]); const loadLeaderboard = async () => { try { const data = await opsApi.leaderboard(); setLeaderboard((data as unknown as { leaderboard?: LeaderboardEntry[] }).leaderboard ?? []); } catch { /* */ } }; const handleGrant = async () => { if (!grantEmail.trim() || grantPoints <= 0) return; setGrantBusy(true); setGrantResult(""); try { const data = await opsApi.grantPoints(grantEmail.trim(), grantPoints); const result = data as unknown as { ok?: boolean; points_added?: number; points_after?: number; reason?: string }; if (result.ok) { setGrantResult(`成功: +${result.points_added} 分, 当前 ${result.points_after} 分`); } else { setGrantResult(`失败: ${result.reason ?? "unknown"}`); } } catch (e) { setGrantResult(`错误: ${String(e).slice(0, 100)}`); } setGrantBusy(false); }; useEffect(() => { void loadLeaderboard(); }, []); return (

用户积分

{/* Search */} 用户搜索
setQuery(e.target.value)} onKeyDown={(e) => e.key === "Enter" && search()} placeholder="Telegram ID / 用户名 / 邮箱" className="flex-1 rounded-lg border border-white/10 bg-black/30 px-3 py-2 text-sm text-white placeholder:text-slate-600 outline-none focus:border-cyan-400/50" />
{users.length > 0 && (
{users.map((u, i) => (
{u.username || `TG${u.telegram_id}`} {u.supabase_email || ""}
{u.points ?? 0} 积分 {u.message_count ?? 0} 发言 周 {u.weekly_points ?? 0}
))}
)}
{/* Grant Points */} 积分运营
setGrantEmail(e.target.value)} placeholder="用户 Supabase 邮箱" className="flex-1 min-w-[200px] rounded-lg border border-white/10 bg-black/30 px-3 py-2 text-sm text-white placeholder:text-slate-600 outline-none focus:border-cyan-400/50" /> setGrantPoints(Math.max(1, Math.min(100000, Number(e.target.value) || 0)))} className="w-24 rounded-lg border border-white/10 bg-black/30 px-3 py-2 text-sm text-white outline-none focus:border-cyan-400/50" />
{grantResult && (

{grantResult}

)}
{/* Leaderboard */} 本周排行榜 Top {leaderboard.length} {leaderboard.length === 0 ? ( 本周暂无积分记录 ) : (
    {leaderboard.map((entry, i) => (
  1. #{entry.rank ?? i + 1} {leaderboardName(entry)} 本周积分 {entry.weekly_points ?? 0} 分
  2. ))}
)}
); }