"use server"; import { revalidatePath } from "next/cache"; import { z } from "zod"; import { Permission } from "@/generated/prisma/enums"; import { hasPermission } from "@/lib/auth/permissions"; import { writeAuditLog } from "@/lib/audit/write-audit-log"; import { getActingBusinessContext } from "@/lib/business/get-acting-business-context"; import { prisma } from "@/lib/db/prisma"; import { getAppointmentById } from "@/services/scheduling/appointment.service"; import { setWhatsAppReminderSent } from "@/services/scheduling/whatsapp-reminders.service"; const inputSchema = z.object({ appointmentId: z.string().min(1), sent: z.boolean() }); export interface MarkWhatsAppReminderResult { success: boolean; error?: string; /** ISO timestamp when marked sent, null when cleared. */ sentAt?: string | null; } /** * Marks a booking's WhatsApp reminder as sent (or undoes it). A barber can do * this for their own bookings; someone who can see everyone's bookings (an * owner) can do it for any booking in the business — the same split the * reminders list itself uses, re-checked here because the browser's idea of * which rows it may touch is not a permission check. */ export async function markWhatsAppReminderAction(input: unknown): Promise { const parsed = inputSchema.safeParse(input); if (!parsed.success) return { success: false, error: "That request wasn't valid." }; const context = await getActingBusinessContext(); if (!context) return { success: false, error: "You must be signed in." }; const appointment = await getAppointmentById(prisma, parsed.data.appointmentId); if (!appointment || appointment.businessId !== context.businessId) { return { success: false, error: "Appointment not found." }; } const canSeeEveryone = await hasPermission(context.userId, Permission.VIEW_ALL_STAFF_APPOINTMENTS); if (!canSeeEveryone && appointment.staffId !== context.staffId) { return { success: false, error: "You can only do this for your own appointments." }; } const sentAt = await setWhatsAppReminderSent(prisma, parsed.data); await writeAuditLog(prisma, { actorUserId: context.userId, action: parsed.data.sent ? "WHATSAPP_REMINDER_MARKED_SENT" : "WHATSAPP_REMINDER_MARK_CLEARED", entityType: "Appointment", entityId: appointment.id, }); revalidatePath("/staff/reminders"); return { success: true, sentAt: sentAt ? sentAt.toISOString() : null }; }