diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 984cf38..1719253 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -8,6 +8,7 @@ import ControlCenter from "@/components/admin/control-center"; import RegenerateImagesButton from "@/components/admin/regenerate-images"; import UserManagement from "@/components/admin/user-management"; import Reports from "@/components/admin/reports"; +import MiiList from "@/components/mii/list"; export const metadata: Metadata = { title: "Admin - TomodachiShare", @@ -18,7 +19,11 @@ export const metadata: Metadata = { }, }; -export default async function AdminPage() { +interface Props { + searchParams: Promise<{ [key: string]: string | string[] | undefined }>; +} + +export default async function AdminPage({ searchParams }: Props) { const session = await auth(); if (!session || Number(session.user?.id) !== Number(process.env.NEXT_PUBLIC_ADMIN_USER_ID)) redirect("/404"); @@ -66,6 +71,14 @@ export default async function AdminPage() { + + {/* Queue */} +
+
+ Reports +
+
+ ); } diff --git a/src/app/api/admin/accept-mii/route.ts b/src/app/api/admin/accept-mii/route.ts new file mode 100644 index 0000000..4c9ad4e --- /dev/null +++ b/src/app/api/admin/accept-mii/route.ts @@ -0,0 +1,29 @@ +import { NextRequest, NextResponse } from "next/server"; + +import { auth } from "@/lib/auth"; +import { prisma } from "@/lib/prisma"; +import { idSchema } from "@/lib/schemas"; + +export async function PATCH(request: NextRequest) { + const session = await auth(); + if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + + if (Number(session.user?.id) !== Number(process.env.NEXT_PUBLIC_ADMIN_USER_ID)) return NextResponse.json({ error: "Forbidden" }, { status: 403 }); + + const searchParams = request.nextUrl.searchParams; + const parsedMiiId = idSchema.safeParse(searchParams.get("id")); + + if (!parsedMiiId.success) return NextResponse.json({ error: parsedMiiId.error.issues[0].message }, { status: 400 }); + const miiId = parsedMiiId.data; + + await prisma.mii.update({ + where: { + id: miiId, + }, + data: { + in_queue: false, + }, + }); + + return NextResponse.json({ success: true }); +} diff --git a/src/app/profile/likes/page.tsx b/src/app/profile/likes/page.tsx index 4d84cf6..e6684a5 100644 --- a/src/app/profile/likes/page.tsx +++ b/src/app/profile/likes/page.tsx @@ -37,7 +37,7 @@ export default async function ProfileSettingsPage({ searchParams }: Props) { }> - + ); diff --git a/src/components/mii/list/index.tsx b/src/components/mii/list/index.tsx index 210d278..5c1c4d0 100644 --- a/src/components/mii/list/index.tsx +++ b/src/components/mii/list/index.tsx @@ -15,10 +15,10 @@ import MiiGrid from "./mii-grid"; interface Props { searchParams: { [key: string]: string | string[] | undefined }; userId?: number; // Profiles - inLikesPage?: boolean; // Self-explanatory + parentPage?: "likes" | "admin"; } -export default async function MiiList({ searchParams, userId, inLikesPage }: Props) { +export default async function MiiList({ searchParams, userId, parentPage }: Props) { const session = await auth(); const parsed = searchSchema.safeParse(searchParams); if (!parsed.success) return

{parsed.error.issues[0].message}

; @@ -28,7 +28,7 @@ export default async function MiiList({ searchParams, userId, inLikesPage }: Pro // My Likes page let miiIdsLiked: number[] | undefined = undefined; - if (inLikesPage && session?.user?.id) { + if (parentPage === "likes" && session?.user?.id) { const likedMiis = await prisma.like.findMany({ where: { userId: Number(session.user.id) }, select: { miiId: true }, @@ -36,10 +36,10 @@ export default async function MiiList({ searchParams, userId, inLikesPage }: Pro miiIdsLiked = likedMiis.map((like) => like.miiId); } - const where: Prisma.MiiWhereInput = { - in_queue: false, + const where: Prisma.MiiWhereInput = { + in_queue: parentPage === "admin", // Only show liked miis on likes page - ...(inLikesPage && miiIdsLiked && { id: { in: miiIdsLiked } }), + ...(parentPage === "likes" && miiIdsLiked && { id: { in: miiIdsLiked } }), // Searching ...(query && { OR: [{ name: { contains: query, mode: "insensitive" } }, { tags: { has: query } }, { description: { contains: query, mode: "insensitive" } }], @@ -184,7 +184,7 @@ export default async function MiiList({ searchParams, userId, inLikesPage }: Pro - + ); diff --git a/src/components/mii/list/mii-grid.tsx b/src/components/mii/list/mii-grid.tsx index fd346de..10652e2 100644 --- a/src/components/mii/list/mii-grid.tsx +++ b/src/components/mii/list/mii-grid.tsx @@ -13,11 +13,12 @@ import Carousel from "@/components/carousel"; interface Props { miis: Prisma.MiiGetPayload<{ include: { user: { select: { id: true; name: true } }; _count: { select: { likedBy: true } } } }>[]; userId?: number; + parentPage?: string; } const fetcher = (url: string) => fetch(url).then((res) => res.json()); -export default function MiiGrid({ miis, userId }: Props) { +export default function MiiGrid({ miis, userId, parentPage }: Props) { const session = useSession(); const ids = miis.map((m) => m.id).join(","); const { data } = useSWR(session.data?.user && miis.length > 0 ? `/api/mii/has-liked?ids=${ids}` : null, fetcher, { @@ -79,6 +80,13 @@ export default function MiiGrid({ miis, userId }: Props) { )} + {parentPage === "admin" && ( +
+ +
+ )}