import type { Metadata } from 'next' import Link from 'next/link' import { db } from '@/lib/db' import { requireUser } from '@/lib/auth/current' import { visibleCaseWhere } from '@/lib/access/caseFilter' import { de } from '@/lib/i18n/de' import { CASE_STATUSES } from '@/lib/cases/terms' import { StampMark, classificationEdgeStyle } from '@/components/StampMark' export const metadata: Metadata = { title: de.case.listHeading } export const dynamic = 'force-dynamic' const PAGE_SIZE = 25 /** * Fallliste. * * Sichtbarkeit und Trefferzahl laufen über **dieselbe** Abfrage. Würde man * nachfiltern, stimmten Zählung und Seitenlänge nicht mehr, und aus den Lücken * liesse sich auf verborgene Akten schliessen. Siehe docs/03-auth-und-rechte.md. * * Blättern über einen Cursor auf `(updatedAt, id)`, kein OFFSET: die Liste * bleibt stabil, auch wenn währenddessen Akten dazukommen. */ export default async function CaseListPage({ searchParams, }: { searchParams: Promise<{ status?: string; cursor?: string }> }) { const user = await requireUser() const { status, cursor } = await searchParams const sichtbar = visibleCaseWhere(user.permissions) const statusFilter = status && status !== 'alle' ? { status: status as never } : {} const cursorFilter = cursor ? (() => { const [at, id] = cursor.split('_') if (!at || !id) return {} const date = new Date(Number(at)) return { OR: [{ updatedAt: { lt: date } }, { updatedAt: date, id: { lt: id } }], } })() : {} const where = { AND: [sichtbar, statusFilter, cursorFilter] } const [cases, total, levels] = await Promise.all([ db.case.findMany({ where, orderBy: [{ updatedAt: 'desc' }, { id: 'desc' }], take: PAGE_SIZE + 1, select: { id: true, caseNumber: true, title: true, status: true, classification: true, updatedAt: true, }, }), db.case.count({ where: { AND: [sichtbar, statusFilter] } }), db.clearanceLevelConfig.findMany({ orderBy: { level: 'asc' } }), ]) const hasMore = cases.length > PAGE_SIZE const page = hasMore ? cases.slice(0, PAGE_SIZE) : cases const last = page.at(-1) const levelName = new Map(levels.map((l) => [l.level, l.name])) return (

{de.case.listHeading}

{de.case.countLabel(total)}
{page.length === 0 ? (

{de.case.empty}

) : ( )} {hasMore && last ? (

{de.case.more}

) : null}
) }