diff --git a/src/app/actions/reschedule.ts b/src/app/actions/reschedule.ts new file mode 100644 index 0000000..856702f --- /dev/null +++ b/src/app/actions/reschedule.ts @@ -0,0 +1,59 @@ +"use server"; + +import { revalidatePath } from "next/cache"; + +import { getServerPb } from "@/lib/pb/server"; +import { requireSession } from "@/lib/auth/session"; +import { logActivity } from "@/app/actions/activity"; +import type { CardRecord } from "@/lib/pb/types"; + +const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/; + +/** + * Move a card's target date from the timeline. Owner only. + * + * `target_date` is a CLIENT-OWNED field. The owner may write it — PocketBase + * permits it — but doing so silently would mean a developer moving a date the + * client chose with no record of it. The activity row below is what makes the + * client's card history read "Dave moved the target date from 1 Oct to 15 Nov", + * in their own view, without anyone having to tell them. + * + * Do not remove that call to make this faster. + */ +export async function rescheduleCardAction(input: { + cardId: string; + date: string; +}): Promise<{ ok: boolean; message?: string }> { + const session = await requireSession(); + if (session.role !== "owner") return { ok: false, message: "Not found" }; + + if (!ISO_DATE.test(input.date)) { + return { ok: false, message: "Invalid date" }; + } + + const pb = await getServerPb(); + + const card = await pb + .collection("cards") + .getOne(input.cardId) + .catch(() => null); + if (!card) return { ok: false, message: "Card not found" }; + + const previous = (card.target_date ?? "").slice(0, 10); + if (previous === input.date) return { ok: true }; + + await pb.collection("cards").update(input.cardId, { target_date: input.date }); + + await logActivity({ + project: card.project, + card: card.id, + actor: session.userId, + action: "date_changed", + field: "target_date", + oldValue: card.target_date ?? "", + newValue: input.date, + }); + + revalidatePath("/plan"); + return { ok: true }; +}