"use server"; import { revalidatePath } from "next/cache"; import { z } from "zod"; import { getServerSession } from "@/lib/auth/guards"; import { prisma } from "@/lib/db"; const brandingSchema = z.object({ brandName: z.string().max(60).optional(), primaryColor: z .string() .regex(/^#([0-9a-fA-F]{6})$/, "Use a hex colour like #7c3aed") .optional() .or(z.literal("")), logoUrl: z.string().url().optional().or(z.literal("")), removePoweredBy: z.boolean().optional(), }); export async function saveBrandingAction( organizationId: string, data: z.infer ): Promise<{ ok: boolean; error?: string }> { const session = await getServerSession(); if (!session) return { ok: false, error: "You must be signed in." }; const member = await prisma.member.findFirst({ where: { organizationId, userId: session.user.id }, select: { role: true }, }); if (!member || !["owner", "admin"].includes(member.role)) { return { ok: false, error: "Only workspace owners can edit branding." }; } const parsed = brandingSchema.safeParse(data); if (!parsed.success) return { ok: false, error: parsed.error.issues[0]?.message ?? "Invalid input." }; const payload = { brandName: parsed.data.brandName || null, primaryColor: parsed.data.primaryColor || null, logoUrl: parsed.data.logoUrl || null, removePoweredBy: parsed.data.removePoweredBy ?? false, }; await prisma.orgBranding.upsert({ where: { organizationId }, create: { organizationId, ...payload }, update: payload, }); revalidatePath("/team"); return { ok: true }; }