import { requireSession } from "@/server/auth"; import { dbForTenant } from "@/server/db"; import { hasPermission } from "@/server/rbac"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Pill } from "@/components/mockup-ui"; import { eligibleValidators, latestReviewTask } from "@/server/object-review"; import { REVIEW_LABEL, REVIEW_TONE, reviewState } from "@/lib/object-review"; import { approveTask, rejectTask } from "@/server/actions/tasks"; const inputCls = "h-9 w-full rounded-md border border-input bg-transparent px-3 text-sm"; /** * Generisches Objekt-Review (Story A3-1). Zeigt den aus der jüngsten Review-Aufgabe * abgeleiteten Status eines beliebigen Objekts und bietet — je nach Rolle — * Einreichen zur Validierung (Vier-Augen) bzw. Validieren/Zurückweisen an. * * `submit` ist die objekt-modulspezifische Einreich-Action (z. B. `submitRiskForReview` * gebunden an die Objekt-ID); sie erwartet `approverId` und optional `note` im FormData. */ export async function ObjectReview({ entityType, entityId, title, submit, canSubmit, }: { entityType: string; entityId: string; entityRef?: string | null; title: string; submit: (formData: FormData) => Promise; canSubmit: boolean; }) { const session = await requireSession(); const db = dbForTenant(session.user.tenantId); const task = await latestReviewTask(db, entityType, entityId); const state = reviewState(task); const isOpen = task?.status === "OPEN"; const isAssignee = task?.assigneeId === session.user.id; const canValidate = hasPermission(session, "validate_objects"); const validators = !isOpen && canSubmit ? await eligibleValidators(db, session.user.id) : []; const names = new Map(); const ids = [task?.assigneeId, task?.createdById, task?.resolvedById].filter(Boolean) as string[]; if (ids.length) { (await db.user.findMany({ where: { id: { in: ids } }, select: { id: true, name: true } })).forEach((u) => names.set(u.id, u.name)); } const lastReviewComment = [...(task?.comments ?? [])].reverse().find((c) => c.kind === "reject" || c.kind === "approve"); return (
Validierung {REVIEW_LABEL[state]}
{task && nur „Bestätigt“ zählt als abgesichert}
{/* Laufende Validierung */} {isOpen && (

Zur Validierung bei {names.get(task!.assigneeId ?? "") ?? "—"}{task!.createdById ? <> · eingereicht von {names.get(task!.createdById) ?? "—"} : null}.

{isAssignee && canValidate ? (
Zurückweisen