import { prisma } from "@/lib/prisma"; import { Prisma } from "@/app/generated/prisma/client"; import { utcStartOfDay, utcDayStartFromYmd, utcDayEndFromYmd, maxUtcDate, } from "@/lib/trip-dates"; export const tripRepo = { async findAll() { return prisma.trip.findMany({ include: { organizer: { select: { id: true, name: true, image: true } }, images: { orderBy: { order: "asc" }, take: 1 }, _count: { select: { participants: { where: { status: { not: "CANCELLED" } } }, }, }, }, orderBy: { date: "asc" }, }); }, async findOpen(filters?: { q?: string; from?: string; to?: string }) { const todayStart = utcStartOfDay(new Date()); const andParts: Prisma.TripWhereInput[] = [{ status: "OPEN" }]; if (!filters?.from && !filters?.to) { andParts.push({ date: { gte: todayStart } }); } else { const userRangeStart = filters.from ? utcDayStartFromYmd(filters.from) : todayStart; const userRangeEnd = filters.to ? utcDayEndFromYmd(filters.to) : utcDayEndFromYmd("2099-12-31"); const rangeStart = maxUtcDate(todayStart, userRangeStart); const rangeEnd = userRangeEnd; andParts.push({ OR: [ { AND: [ { endDate: { not: null } }, { date: { lte: rangeEnd } }, { endDate: { gte: rangeStart } }, ], }, { AND: [ { endDate: null }, { date: { gte: rangeStart } }, { date: { lte: rangeEnd } }, ], }, ], }); } if (filters?.q) { andParts.push({ OR: [ { title: { contains: filters.q, mode: "insensitive" } }, { mountain: { contains: filters.q, mode: "insensitive" } }, { location: { contains: filters.q, mode: "insensitive" } }, ], }); } const where: Prisma.TripWhereInput = { AND: andParts }; return prisma.trip.findMany({ where, include: { organizer: { select: { id: true, name: true, image: true } }, images: { orderBy: { order: "asc" }, take: 1 }, _count: { select: { participants: { where: { status: { not: "CANCELLED" } } }, }, }, }, orderBy: { date: "asc" }, }); }, async findById(id: string) { return prisma.trip.findUnique({ where: { id }, include: { organizer: { select: { id: true, name: true, email: true, image: true, isVerified: true, }, }, images: { orderBy: { order: "asc" } }, participants: { include: { user: { select: { id: true, name: true, image: true } } }, }, reviews: { orderBy: { createdAt: "desc" }, include: { user: { select: { id: true, name: true, image: true } }, }, }, }, }); }, async countByOrganizerSince(organizerId: string, since: Date) { return prisma.trip.count({ where: { organizerId, createdAt: { gte: since } }, }); }, /** Semua trip yang dibuat user (semua status), terbaru dulu — untuk profil. */ async findByOrganizerId(organizerId: string) { return prisma.trip.findMany({ where: { organizerId }, include: { images: { orderBy: { order: "asc" }, take: 1 }, _count: { select: { participants: { where: { status: { not: "CANCELLED" } } }, }, }, }, orderBy: { date: "desc" }, }); }, async create(data: Prisma.TripCreateInput) { return prisma.trip.create({ data }); }, async updateStatus(id: string, status: "OPEN" | "FULL" | "CLOSED" | "COMPLETED") { return prisma.trip.update({ where: { id }, data: { status } }); }, };