Files
craftvia/src/server/actions/reports/_state.ts
T
msolarczekandClaude Opus 5 8f53df6208 L5 Berichte & Unterschrift: Server Actions und API v1
Actions mit moduleGuard("reports"); POST daily-report/completion-report, POST approve,
GET pdf sowie Dateiauslieferung für im Bericht referenzierte Dokumente.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 12:22:40 +02:00

33 lines
1.4 KiB
TypeScript

import { ZodError } from "zod";
import type { ReportActionState } from "@/lib/reports/action-state";
import type { CompletionBlocker } from "@/lib/work-orders/status";
import { ServiceError } from "@/server/services/context";
import { ForbiddenError } from "@/server/rbac";
import { ModuleDisabledError } from "@/server/modules";
/** Map thrown errors of report actions to a displayable state (no internals leak to the client). */
export function errorState(err: unknown): ReportActionState {
const at = Date.now();
if (err instanceof ServiceError) {
const details = err.details as { field?: string } | CompletionBlocker[] | undefined;
return {
status: "error",
code: err.code,
field: details && !Array.isArray(details) ? details.field : undefined,
blockers: Array.isArray(details) ? details : undefined,
at,
};
}
if (err instanceof ZodError) return { status: "error", code: "invalid", field: String(err.issues[0]?.path[0] ?? ""), at };
if (err instanceof ForbiddenError || err instanceof ModuleDisabledError) return { status: "error", code: "forbidden", at };
console.error("[actions/reports]", err);
return { status: "error", code: "generic", at };
}
export const okState = (reportId?: string): ReportActionState => ({ status: "ok", reportId, at: Date.now() });
export const str = (fd: FormData, key: string): string | undefined => {
const v = fd.get(key);
return typeof v === "string" ? v : undefined;
};