import type { Prisma } from "@prisma/client"; import { blindIndex } from "../services/crypto.server"; /** Booking list filters shared by the list page and the CSV export. */ export function bookingWhere(shopId: string, sp: URLSearchParams, today: string): Prisma.BookingWhereInput { const status = sp.get("status") ?? "upcoming"; const where: Prisma.BookingWhereInput = { shopId }; if (status === "review") where.OR = [{ status: "needs_review" }, { status: "confirmed", reviewReason: { not: null } }]; else if (status === "upcoming") Object.assign(where, { status: "confirmed", date: { gte: today } }); else if (status !== "all") where.status = status; const method = sp.get("method"); if (method && method !== "all") where.method = method; const loc = sp.get("location"); if (loc && loc !== "all") where.locationId = loc; const from = sp.get("from"); const to = sp.get("to"); if (from || to) where.date = { ...(from ? { gte: from } : {}), ...(to ? { lte: to } : {}) }; const q = sp.get("q")?.trim(); // Customer details are encrypted at rest: match order numbers by text, emails and phones exactly (by keyed hash). if (q) { const or: Prisma.BookingWhereInput[] = [{ orderName: { contains: q, mode: "insensitive" } }]; if (q.includes("@")) or.push({ customerEmailHash: blindIndex(q, "email") }); else if (/^[\d\s()+.-]{7,}$/.test(q)) or.push({ customerPhoneHash: blindIndex(q, "phone") }); where.AND = [{ OR: or }]; } return where; }