feat: bang edit and delete

This commit is contained in:
ginnoir
2026-07-04 18:20:38 -05:00
parent 1a03763e1b
commit 753f653b89
4 changed files with 281 additions and 15 deletions
+73 -4
View File
@@ -1,5 +1,6 @@
"use server";
import { and, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { db } from "@/lib/db";
@@ -7,11 +8,19 @@ import { getCurrentSession } from "@/lib/session";
import { logActivity } from "@/modules/_core/activity";
import { bangEvents } from "../schema";
const dateString = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Must be YYYY-MM-DD");
const addBangInput = z.object({
occurredOn: z
.string()
.regex(/^\d{4}-\d{2}-\d{2}$/, "Must be YYYY-MM-DD")
.optional(),
occurredOn: dateString.optional(),
});
const updateBangInput = z.object({
id: z.string().uuid(),
occurredOn: dateString,
});
const deleteBangInput = z.object({
id: z.string().uuid(),
});
function todayString(): string {
@@ -48,3 +57,63 @@ export async function addBang(input: z.input<typeof addBangInput> = {}) {
return bang;
}
export async function updateBang(input: z.input<typeof updateBangInput>) {
const parsed = updateBangInput.parse(input);
const { household } = await getCurrentSession();
await assertCanAccessBang(parsed.id, household.id);
const [bang] = await db
.update(bangEvents)
.set({ occurredOn: parsed.occurredOn })
.where(eq(bangEvents.id, parsed.id))
.returning();
if (!bang) throw new Error("Bang was not updated");
await logActivity({
entityType: "bangs.event",
entityId: bang.id,
action: "update",
payload: { occurredOn: parsed.occurredOn },
});
revalidatePath("/");
revalidatePath("/d/[slug]", "page");
return bang;
}
export async function deleteBang(input: z.input<typeof deleteBangInput>) {
const parsed = deleteBangInput.parse(input);
const { household } = await getCurrentSession();
await assertCanAccessBang(parsed.id, household.id);
const [existing] = await db
.select({ occurredOn: bangEvents.occurredOn })
.from(bangEvents)
.where(eq(bangEvents.id, parsed.id))
.limit(1);
await logActivity({
entityType: "bangs.event",
entityId: parsed.id,
action: "delete",
payload: existing ? { occurredOn: existing.occurredOn } : undefined,
});
await db.delete(bangEvents).where(eq(bangEvents.id, parsed.id));
revalidatePath("/");
revalidatePath("/d/[slug]", "page");
}
async function assertCanAccessBang(bangId: string, householdId: string) {
const [bang] = await db
.select({ id: bangEvents.id })
.from(bangEvents)
.where(and(eq(bangEvents.id, bangId), eq(bangEvents.householdId, householdId)))
.limit(1);
if (!bang) throw new Error("Forbidden");
}