import { NextRequest, NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; import { auth } from "@/lib/auth"; import { searchSchema } from "@tomodachi-share/shared/schemas"; import { Prisma } from "@prisma/client"; export async function GET(request: NextRequest) { const session = await auth(); const parsed = searchSchema.safeParse(Object.fromEntries(request.nextUrl.searchParams)); if (!parsed.success) return NextResponse.json({ error: parsed.error.issues[0].message }, { status: 400 }); const { q: query, sort, tags, exclude, platform, gender, makeup, allowCopying, quarantined, page = 1, limit = 24, parentPage, userId } = parsed.data; // My Likes page let miiIdsLiked: number[] | undefined = undefined; if (parentPage === "likes" && session?.user?.id) { const likedMiis = await prisma.like.findMany({ where: { userId: Number(session.user.id) }, select: { miiId: true }, }); miiIdsLiked = likedMiis.map((like) => like.miiId); } const where: Prisma.MiiWhereInput = { // In queue logic ...(parentPage === "admin" ? { in_queue: true } // Only show queued Miis : userId ? { // Include queued Miis if user is on their profile ...(Number(session?.user?.id) === userId ? {} : { in_queue: false }), userId, } : { // Don't show queued Miis on main page in_queue: false, }), // Only show liked miis on likes page ...(parentPage === "likes" && miiIdsLiked && { id: { in: miiIdsLiked } }), // Searching ...(query && { OR: [{ name: { contains: query, mode: "insensitive" } }, { tags: { has: query } }, { description: { contains: query, mode: "insensitive" } }], }), // Tag filtering ...(tags && tags.length > 0 && { tags: { hasEvery: tags } }), ...(exclude && exclude.length > 0 && { NOT: { tags: { hasSome: exclude } } }), // Platform ...(platform && { platform: { equals: platform } }), // Gender ...(gender && { gender: { equals: gender } }), // Allow Copying ...(allowCopying && { allowedCopying: true }), // Makeup ...(makeup && { makeup: { equals: makeup } }), // Quarantined ...(!quarantined && !userId && { quarantined: false }), }; const select: Prisma.MiiSelect = { id: true, // Don't show when userId is specified ...(!userId && { user: { select: { id: true, name: true, }, }, }), platform: true, name: true, imageCount: true, tags: true, createdAt: true, gender: true, makeup: true, allowedCopying: true, quarantined: true, in_queue: true, // Mii liked check ...(session?.user?.id && { likedBy: { where: { userId: Number(session.user.id) }, select: { userId: true }, }, }), // Like count _count: { select: { likedBy: true }, }, }; let totalCount: number; let miis: Prisma.MiiGetPayload<{ select: typeof select }>[]; // Sorting by likes, newest, or oldest let orderBy: Prisma.MiiOrderByWithRelationInput[]; if (sort === "likes") { orderBy = [{ likedBy: { _count: "desc" } }, { name: "asc" }]; } else if (sort === "oldest") { orderBy = [{ createdAt: "asc" }, { name: "asc" }]; } else { // default to newest orderBy = [{ createdAt: "desc" }, { name: "asc" }]; } [totalCount, miis] = await Promise.all([ prisma.mii.count({ where: { ...where, userId } }), prisma.mii.findMany({ where, orderBy, select, skip: (page - 1) * limit, take: limit, }), ]); const lastPage = Math.ceil(totalCount / limit); return NextResponse.json({ miis, totalCount, lastPage, }); }