SPB Git
2.3 KB · 14 lines tsx
1"use client";2import { useState } from "react";3import Link from "next/link";4import { api } from "./api";5export function FlagList({ flags }: { flags: { key: string; value: any; updatedAt: string }[] }) {6  const [list, setList] = useState(flags);7  return <ul className="mt-2 space-y-2">{list.map((f) => { const slug = f.key.split(":")[1]; return <li key={f.key} className="card flex flex-wrap items-start gap-3 p-3 text-sm"><span className={`chip ${f.key.startsWith("stale") ? "" : "chip-accent"}`}>{f.value.kind}</span><div className="min-w-0 flex-1"><Link href={`/admin/tools/${slug}`} className="font-medium hover:text-accent">{slug}</Link><p className="text-xs text-fg-2">{f.value.reasons?.join("; ") ?? (f.value.kind === "canonical_moved" ? `canonical now ${f.value.to}` : `page changed (${f.value.title ?? "no title"})`)}</p></div><button onClick={async () => { await api("/api/admin/flags", { method: "DELETE", body: JSON.stringify({ key: f.key }) }); setList((l) => l.filter((x) => x.key !== f.key)); }} className="btn-ghost h-8 px-2 text-xs">Dismiss</button></li>; })}{!list.length && <li className="text-sm text-fg-3">No flags.</li>}</ul>;8}9export function ReportList({ reports }: { reports: any[] }) {10  const [list, setList] = useState(reports);11  const setStatus = async (id: string, status: string) => { await api("/api/admin/reports", { method: "PATCH", body: JSON.stringify({ id, status }) }); setList((l) => l.map((r) => (r.id === id ? { ...r, status } : r))); };12  return <ul className="mt-2 space-y-2">{list.map((r) => <li key={r.id} className={`card p-3 text-sm ${r.status !== "open" ? "opacity-60" : ""}`}><div className="flex flex-wrap items-center gap-2"><Link href={`/admin/tools/${r.toolSlug}`} className="font-medium hover:text-accent">{r.toolSlug}</Link><span className="chip">{r.status}</span><span className="text-xs text-fg-3">{new Date(r.createdAt).toLocaleString("en-CA")}{r.contact ? ` · ${r.contact}` : ""}</span>{r.status === "open" && <span className="ml-auto flex gap-1"><button onClick={() => setStatus(r.id, "resolved")} className="btn-ghost h-8 px-2 text-xs">Resolved</button><button onClick={() => setStatus(r.id, "dismissed")} className="btn-ghost h-8 px-2 text-xs">Dismiss</button></span>}</div><p className="mt-1 whitespace-pre-wrap text-fg-2">{r.message}</p></li>)}{!list.length && <li className="text-sm text-fg-3">No reports.</li>}</ul>;13}14
Files · main
Menu

Theme