import type { Metadata } from 'next' import { Suspense } from 'react' import Link from 'next/link' import { notFound } from 'next/navigation' import { db } from '@/lib/db' import { requireUser } from '@/lib/auth/current' import { recordRead, READ_AUDIT_FROM_LEVEL } from '@/lib/audit' import { loadDocumentSections, loadVisibleDocument } from '@/lib/documents/service' import { canEditDocument, canFinalizeDocument, canRetractDocument, } from '@/lib/access/documentWrite' import { de } from '@/lib/i18n/de' import { StampMark, classificationEdgeStyle } from '@/components/StampMark' import { SkeletonLine } from '@/components/Skeleton' import { Sections } from '@/components/sections/Sections' import { Sheet } from '@/components/documents/Sheet' import { SheetSwitch } from '@/components/documents/SheetSwitch' import { saveDocumentSectionAction } from '../actions' import { DocumentActions } from './DocumentActions' import { Attachments } from '@/components/files/Attachments' import { listAttachments, resolvePhotoUrls } from '@/lib/files/service' import { toAttachmentViews } from '@/lib/files/view' import type { EffectivePermissions } from '@/lib/auth/permissions' export const dynamic = 'force-dynamic' export async function generateMetadata({ params, }: { params: Promise<{ documentNumber: string }> }): Promise { const { documentNumber } = await params return { title: documentNumber } } async function Body({ document, permissions, canEdit, }: { document: { id: string templateId: string documentNumber: string title: string layout: string createdAt: Date caseId: string | null } permissions: EffectivePermissions canEdit: boolean }) { const sections = await loadDocumentSections(permissions, document) const photoUrls = await resolvePhotoUrls( permissions, sections.map((section) => ({ fieldKey: section.fieldKey, visible: section.visible, value: section.visible ? section.value : null, type: section.field.type, })), ) const editor = ( ) if (document.layout !== 'DOSSIER') return editor // Das Aktenblatt braucht die Kopfzeilen der Vorlage und die // Foundation-Stufen für den Balken. Beide steuern keinen Zugriff. const [template, foundationLevels] = await Promise.all([ db.documentTemplate.findUnique({ where: { id: document.templateId }, select: { sheetTitle: true, sheetSubtitle: true, name: true }, }), db.foundationClearance.findMany({ orderBy: { sortOrder: 'asc' } }), ]) return ( } /> ) } async function AttachmentBlock({ documentId, documentNumber, topic, permissions, canUpload, }: { documentId: string documentNumber: string topic: string permissions: EffectivePermissions canUpload: boolean }) { const anhaenge = await listAttachments(permissions, { documentId }) return ( ) } /** * Ein Dokument. * * Dieselbe Darstellung trägt einen Vorfallsbericht und einen mehrseitigen * Vertrag: was sie unterscheidet, steht in der Vorlage, nicht hier. * Siehe docs/13-entscheidungen.md. */ export default async function DocumentPage({ params, }: { params: Promise<{ documentNumber: string }> }) { const user = await requireUser() const { documentNumber } = await params const doc = await loadVisibleDocument(user.permissions, documentNumber) // Kein Zugriff heisst 404, nicht 403. if (!doc) notFound() if (doc.classification >= READ_AUDIT_FROM_LEVEL) { recordRead({ actorId: user.id, action: 'document.read', targetType: 'Document', targetId: doc.id, clearanceAtTime: user.permissions.clearanceLevel, meta: { documentNumber: doc.documentNumber, classification: doc.classification }, }) } const [levels, besitzer, verfasser] = await Promise.all([ db.clearanceLevelConfig.findMany({ orderBy: { level: 'asc' } }), doc.caseId ? db.case.findUnique({ where: { id: doc.caseId }, select: { caseNumber: true, title: true } }) : doc.personnelFileId ? db.personnelFile.findUnique({ where: { id: doc.personnelFileId }, select: { id: true, displayName: true }, }) : Promise.resolve(null), db.user.findMany({ where: { id: { in: [doc.createdById, doc.finalizedById, doc.retractedById].filter( (id): id is string => id !== null, ), }, }, select: { id: true, displayName: true }, }), ]) const level = levels.find((l) => l.level === doc.classification) const nameOf = new Map(verfasser.map((v) => [v.id, v.displayName])) const canEdit = canEditDocument(user.permissions, doc).ok return (
{doc.documentNumber}

{doc.title}

{de.case.status}
{de.document.statusNames[doc.status] ?? doc.status}
{de.document.kind}
{doc.templateKey}
{de.case.createdBy}
{nameOf.get(doc.createdById) ?? doc.createdById}

{de.export.asPdf}

{besitzer ? (

{'caseNumber' in besitzer ? ( {de.document.ownerCase} · {besitzer.title} ) : ( {de.document.ownerPersonnel} · {besitzer.displayName} )}

) : (

{de.document.ownerNone}

)} {doc.retractedAt ? (

{de.document.retracted( doc.retractedAt.toLocaleDateString('de-DE'), nameOf.get(doc.retractedById ?? '') ?? doc.retractedById ?? de.common.unknown, doc.retractionReason ?? '', )}

) : doc.finalizedAt ? (

{de.document.finalized( doc.finalizedAt.toLocaleDateString('de-DE'), nameOf.get(doc.finalizedById ?? '') ?? doc.finalizedById ?? de.common.unknown, )}

) : null} l.level <= user.permissions.clearanceLevel) .map((l) => ({ level: l.level, name: l.name }))} />
} >

{de.attachment.heading}

}>
) }