feat(roadmap): reschedule from the timeline, always audited

This commit is contained in:
Dave 2026-09-17 07:18:20 +02:00
parent bed7af848e
commit ecf5f0c173

View file

@ -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<CardRecord>(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 };
}