Files
Harlekin e0b03ea336
Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
Gedankenstriche durch Bindestriche ersetzt
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die
README; an keiner Stelle Bedeutung, nur Zeichensetzung.
2026-09-04 08:54:52 +02:00

98 lines
3.6 KiB
TypeScript

import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { db } from '@/lib/db'
import { requireUser } from '@/lib/auth/current'
import { loadVisibleCase } from '@/lib/cases/service'
import { loadChangeHistory } from '@/lib/cases/entryService'
import { de } from '@/lib/i18n/de'
import { wordDiff } from '@/lib/diff'
export const metadata: Metadata = { title: de.entry.changesHeading }
export const dynamic = 'force-dynamic'
/**
* Änderungsübersicht als eigener Reiter an der Akte.
*
* Für die Abteilungsleitung ist das die Ansicht, mit der sie im Zweifel prüft,
* ob an einer Akte nachträglich gedreht wurde. Sichtbar für alle, die die Akte
* lesen dürfen - nicht nur für die Leitung. Das ist der ganze Sinn der Sache.
*/
export default async function ChangesPage({
params,
}: {
params: Promise<{ caseNumber: string }>
}) {
const user = await requireUser()
const { caseNumber } = await params
const akte = await loadVisibleCase(user.permissions, caseNumber)
if (!akte) notFound()
const versionen = await loadChangeHistory(user.permissions, akte.id)
const namen = new Map(
(
await db.user.findMany({
where: { id: { in: [...new Set(versionen.map((v) => v.editedById))] } },
select: { id: true, displayName: true },
})
).map((u) => [u.id, u.displayName]),
)
return (
<>
{/* Aktenzeichen und Titel stehen im Layout, hier nur noch die Überschrift
des Reiters. */}
<h2 className="font-condensed">{de.entry.changesHeading}</h2>
<p className="mt-2 max-w-(--container-measure) text-text-dim">{de.entry.changesIntro}</p>
{versionen.length === 0 ? (
<p className="mt-8 text-text-dim">{de.entry.changesEmpty}</p>
) : (
<ol className="mt-8 border-t border-line">
{versionen.map((version) => (
<li key={version.id} className="border-b border-line py-5">
<div className="flex flex-wrap items-baseline gap-x-3 gap-y-1 text-2xs text-text-dim">
<span className="font-condensed">
{de.entry.versionLabel(version.version)} → {version.version + 1}
</span>
<span className="font-mono">
{namen.get(version.editedById) ?? version.editedById}
</span>
<time dateTime={version.editedAt.toISOString()}>
{version.editedAt.toLocaleString('de-DE')}
</time>
</div>
{version.changeReason ? (
<p className="mt-1.5 text-sm">
<span className="font-condensed text-text-dim">{de.entry.changeReason}: </span>
{version.changeReason}
</p>
) : null}
{/* Wortdiff statt zweier Spalten: bei langen Vermerken sieht man
sonst nicht, was sich geändert hat. */}
<p className="mt-3 max-w-(--container-measure) text-sm whitespace-pre-wrap">
{wordDiff(version.body, version.entry.body).map((teil, index) =>
teil.kind === 'gleich' ? (
<span key={index}>{teil.text}</span>
) : teil.kind === 'entfernt' ? (
<del key={index} className="text-stamp-4 decoration-stamp-4">
{teil.text}
</del>
) : (
<ins key={index} className="text-stamp-2 no-underline">
{teil.text}
</ins>
),
)}
</p>
</li>
))}
</ol>
)}
</>
)
}