diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index 1719253..679ec87 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -70,7 +70,7 @@ export default async function AdminPage({ searchParams }: Props) {
diff --git a/src/components/admin/report-tabs.tsx b/src/components/admin/report-tabs.tsx
new file mode 100644
index 0000000..d29339e
--- /dev/null
+++ b/src/components/admin/report-tabs.tsx
@@ -0,0 +1,32 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { useTransition } from "react";
+import { ReportStatus } from "@prisma/client";
+
+export default function ReportTabs({ status }: { status?: ReportStatus }) {
+ const router = useRouter();
+ const [isPending, startTransition] = useTransition();
+
+ return (
+
+ {["ALL", "OPEN", "RESOLVED", "DISMISSED"].map((s) => (
+
+ ))}
+
+ );
+}
diff --git a/src/components/admin/reports.tsx b/src/components/admin/reports.tsx
index c920eb1..8a7b12b 100644
--- a/src/components/admin/reports.tsx
+++ b/src/components/admin/reports.tsx
@@ -5,10 +5,27 @@ import { Icon } from "@iconify/react";
import { ReportStatus } from "@prisma/client";
import { prisma } from "@/lib/prisma";
+import ReportTabs from "./report-tabs";
-export default async function Reports() {
- const reports = await prisma.report.findMany({ orderBy: { createdAt: "desc" } });
- // TODO: add pagination
+const PAGE_SIZE = 20;
+
+export default async function Reports({ searchParams }: { searchParams: { status?: string; page?: string } }) {
+ const status = searchParams.status as ReportStatus | undefined;
+ const page = Number(searchParams.page ?? 1);
+
+ const [reports, total] = await Promise.all([
+ prisma.report.findMany({
+ where: status ? { status } : undefined,
+ orderBy: { createdAt: "desc" },
+ skip: (page - 1) * PAGE_SIZE,
+ take: PAGE_SIZE,
+ }),
+ prisma.report.count({
+ where: status ? { status } : undefined,
+ }),
+ ]);
+
+ const totalPages = Math.ceil(total / PAGE_SIZE);
const updateStatus = async (formData: FormData) => {
"use server";
@@ -25,6 +42,9 @@ export default async function Reports() {
return (
+
+
+ {/* Grid */}
{reports.map((report) => (
@@ -150,6 +170,34 @@ export default async function Reports() {
Reports will appear here when users submit them
)}
+
+ {/* Pagination */}
+ {totalPages > 1 && (
+
+
{total} total
+
+ {page > 1 && (
+
+ Previous
+
+ )}
+
+ Page {page} of {totalPages}
+
+ {page < totalPages && (
+
+ Next
+
+ )}
+
+
+ )}
);
}
diff --git a/src/lib/auth.ts b/src/lib/auth.ts
index dbefdb9..b0edd81 100644
--- a/src/lib/auth.ts
+++ b/src/lib/auth.ts
@@ -13,6 +13,14 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
signIn: "/login",
},
callbacks: {
+ async signIn({ user }) {
+ const blacklist = process.env.BLACKLISTED_EMAILS ? process.env.BLACKLISTED_EMAILS.split(",").map((item) => item.trim().toLowerCase()) : [];
+ const email = user?.email?.toLowerCase();
+ if (!email) return false;
+ if (blacklist?.some((blocked) => email.endsWith(blocked))) return false;
+ return true;
+ },
+
async session({ session, user }) {
if (user) {
session.user.id = user.id;