"use server"
import { db, type Leave, type Result } from "@/lib/sample-data"
/**
* The People dashboard's shared server actions: what more than one of its
* pages does to the same rows. The overview's leave queue and the leave page
* both decide a request, so the decision lives here, once, and both import
* it — one action name, one behaviour, everywhere the dashboard offers it.
*
* Installed as `@lib/dashboards/people/actions.ts` by the `actions-people`
* item, which every page that imports it lists in its registry dependencies,
* so installing the dashboard installs it too. Every answer is a `Result`,
* and the name in it is read off the rows the action looked up.
*/
export type LeaveDecision = Extract<Leave["status"], "approved" | "declined">
export type DecidedLeave = { id: string; status: LeaveDecision; employeeName: string; kind: Leave["kind"] }
/**
* Grants or refuses a request. Only a pending one can be decided: a request
* that was already approved or declined is refused with the decision it got,
* because a manager pressing the other button a second time — or a second
* manager on another page — is the race this guards against. The employee is
* read off the row, never the form.
*/
export async function decideLeave(id: string, decision: LeaveDecision): Promise<Result<DecidedLeave>> {
// The type is erased at the action boundary; only the two words a page offers may be written.
if (decision !== "approved" && decision !== "declined") {
return { ok: false, error: { code: "invalid", message: `"${String(decision)}" is not a decision a request can take.` } }
}
const leave = await db.leaves.get(id)
if (!leave) {
return { ok: false, error: { code: "not_found", message: `No leave request with id "${id}".` } }
}
const employee = await db.employees.get(leave.employeeId)
const name = employee?.name ?? "That colleague"
if (leave.status !== "pending") {
return {
ok: false,
error: { code: "conflict", message: `${name}'s ${leave.kind} leave was already ${leave.status}.` },
}
}
const updated = await db.leaves.update(id, { status: decision })
if (!updated.ok) return updated
return { ok: true, data: { id, status: decision, employeeName: name, kind: leave.kind } }
}