import { requireOwner, withCors, preflight } from "@/lib/admin"; import { sql } from "@/lib/db"; import { isApprovalStatus } from "@/lib/driver"; export async function OPTIONS(request: Request) { return preflight(request); } type DriverBody = { first_name?: string; last_name?: string; profile_image_url?: string; car_image_url?: string; car_seats?: number; rating?: number; /** Vetting decision: 'approved' | 'rejected' | 'suspended' | 'pending'. */ approval_status?: string; /** Shown to the driver when the decision is 'rejected'. */ rejection_reason?: string; }; export async function PATCH(request: Request, { id }: { id: string }) { const auth = await requireOwner(request); if ("error" in auth) return withCors(request, auth.error); try { const body = (await request.json()) as DriverBody; // Vetting decision. Anything other than 'approved' also forces the driver // offline in the same statement: a driver who is suspended mid-shift must // stop receiving offers immediately, not at their next toggle. let approval: string | null = null; if (body.approval_status !== undefined) { if (!isApprovalStatus(body.approval_status)) { return withCors( request, Response.json( { error: "approval_status must be pending, approved, rejected or suspended.", }, { status: 400 }, ), ); } if (body.approval_status === "rejected" && !body.rejection_reason?.trim()) { return withCors( request, Response.json( { error: "A rejection needs a reason the driver can act on." }, { status: 400 }, ), ); } approval = body.approval_status; } const rejectionReason = approval === "approved" ? null : (body.rejection_reason?.trim() ?? null); const rows = await sql` UPDATE drivers SET first_name = COALESCE(${body.first_name ?? null}, first_name), last_name = COALESCE(${body.last_name ?? null}, last_name), profile_image_url = COALESCE(${body.profile_image_url ?? null}, profile_image_url), car_image_url = COALESCE(${body.car_image_url ?? null}, car_image_url), car_seats = COALESCE(${body.car_seats ?? null}, car_seats), rating = COALESCE(${body.rating ?? null}, rating), approval_status = COALESCE(${approval}, approval_status), rejection_reason = CASE WHEN ${approval}::text IS NULL THEN rejection_reason ELSE ${rejectionReason} END, reviewed_at = CASE WHEN ${approval}::text IS NULL THEN reviewed_at ELSE CURRENT_TIMESTAMP END, reviewed_by = CASE WHEN ${approval}::text IS NULL THEN reviewed_by ELSE ${auth.userId}::uuid END, online = CASE WHEN ${approval}::text IS NOT NULL AND ${approval}::text <> 'approved' THEN FALSE ELSE online END WHERE id = ${id} RETURNING * `; if (!rows[0]) { return withCors(request, Response.json({ error: "Driver not found." }, { status: 404 }), ); } return withCors(request, Response.json({ data: rows[0] })); } catch (error) { console.error("[ADMIN_DRIVER_PATCH]: ", error); return withCors(request, Response.json({ error: "Internal Server Error" }, { status: 500 }), ); } } export async function DELETE(request: Request, { id }: { id: string }) { const auth = await requireOwner(request); if ("error" in auth) return withCors(request, auth.error); try { const used = await sql<{ n: number }>` SELECT COUNT(*)::int AS n FROM rides WHERE driver_id = ${id} `; if (used[0].n > 0) { return withCors(request, Response.json( { error: "Driver has recorded rides and cannot be deleted." }, { status: 409 }, ), ); } const rows = await sql` DELETE FROM drivers WHERE id = ${id} RETURNING id `; if (!rows[0]) { return withCors(request, Response.json({ error: "Driver not found." }, { status: 404 }), ); } return withCors(request, Response.json({ data: rows[0] })); } catch (error) { console.error("[ADMIN_DRIVER_DELETE]: ", error); return withCors(request, Response.json({ error: "Internal Server Error" }, { status: 500 }), ); } }