import { ArrowLeftRight } from "lucide-react"; import Link from "next/link"; import { getTranslations } from "next-intl/server"; import { StatusCard } from "@/components/admin/dashboard"; import { requireStaff } from "@/lib/admin/guard"; import { prisma } from "@/lib/prisma"; export const dynamic = "force-dynamic"; const PER_PAGE = 25; type Txn = Awaited>[number]; const PAID_STATUS = new Set(["completed", "paid", "success", "approved"]); const FAILED_STATUS = new Set(["failed", "denied", "refunded", "cancelled", "canceled"]); function statusState(status: string | null | undefined): "ok" | "danger" | undefined { if (!status) return undefined; const s = status.toLowerCase(); if (PAID_STATUS.has(s)) return "ok"; if (FAILED_STATUS.has(s)) return "danger"; return undefined; } function fromDate(d: Date | null | undefined): string { return d ? d.toISOString().slice(0, 16).replace("T", " ") : "—"; } function formatAmount(amount: number, currency: string): string { const n = Number(amount); const value = Number.isFinite(n) ? n.toFixed(2) : "0.00"; return `${value} ${currency}`; } export default async function AdminTransactions({ searchParams, }: { searchParams: Promise<{ page?: string }>; }) { await requireStaff(); const t = await getTranslations("pages.admin.transactions"); const sp = await searchParams; const page = Math.max(1, Number(sp.page ?? "1") || 1); let transactions: Txn[] = []; let total = 0; let names = new Map(); try { [transactions, total] = await Promise.all([ prisma.websitePaypalTransactions.findMany({ orderBy: { id: "desc" }, skip: (page - 1) * PER_PAGE, take: PER_PAGE, }), prisma.websitePaypalTransactions.count(), ]); const userIds = [...new Set(transactions.map((t) => t.userId))]; if (userIds.length > 0) { const users = await prisma.user.findMany({ where: { id: { in: userIds } }, select: { id: true, username: true }, }); names = new Map(users.map((u) => [u.id, u.username])); } } catch { transactions = []; total = 0; names = new Map(); } const pages = Math.max(1, Math.ceil(total / PER_PAGE)); const pagePaid = transactions.filter((t) => statusState(t.status) === "ok").length; const pageFailed = transactions.filter((t) => statusState(t.status) === "danger").length; return (

{t("title")}

{t("subtitle")}

0 ? "ok" : "neutral"} icon="💳" /> 0 ? "danger" : "neutral"} icon="⚠️" />

{t("title")} ({total})

{transactions.length === 0 ? (
{t("noTransactions")}
) : (
{transactions.map((x) => { const state = statusState(x.status); return ( ); })}
{t("colId")} {t("colPayer")} {t("colAmount")} {t("colPackage")} {t("colStatus")} {t("colTransaction")} {t("colDate")}
{String(x.id)} {names.get(x.userId) ?? `#${x.userId}`} {formatAmount(x.amount, x.currency)} {x.description ?? "—"} {x.status ? ( {x.status} ) : ( — )} {x.transactionId} {fromDate(x.createdAt)}
)}

{t("pagination", { page, pages, total })} {page > 1 ? ( <> {" · "} ← {t("prev")} ) : null} {page < pages ? ( <> {" · "} {t("next")} → ) : null}

); }