import type { Metadata } from 'next' import Link from 'next/link' import { db } from '@/lib/db' import { requireUser } from '@/lib/auth/current' import { loadDashboard } from '@/lib/dashboard/load' import { pendingApprovals } from '@/lib/export/service' import { de } from '@/lib/i18n/de' import { StampMark, classificationEdgeStyle } from '@/components/StampMark' import { Approvals } from '../export/Approvals' export const metadata: Metadata = { title: de.dashboard.heading } export const dynamic = 'force-dynamic' /** * Die Übersicht: vier Fragen, die man morgens hat. * * Woran arbeite ich, was ist fällig, wo hat jemand geschrieben, was hat sich * getan. Jede Liste läuft durch dieselbe Sichtbarkeitsprüfung wie die * Fallliste — das ist der Ort, an dem eine unachtsame Abfrage am ehesten eine * Akte verrät, die man nicht sehen darf. */ export default async function DashboardPage() { const user = await requireUser() const [daten, levels, offen] = await Promise.all([ loadDashboard(user.permissions), db.clearanceLevelConfig.findMany({ orderBy: { level: 'asc' } }), pendingApprovals(user.permissions), ]) const levelName = new Map(levels.map((l) => [l.level, l.name])) const beschriftet = await beschrifte(offen) const heute = new Date() return (

{de.dashboard.heading}

{de.dashboard.access}
{beschriftet.length > 0 ? (

{de.export.approvals}

) : null}
{(akte) => } {(akte) => ( )}

{de.dashboard.unread}

{daten.ungelesen.length === 0 ? (

{de.dashboard.unreadEmpty}

) : (
    {daten.ungelesen.map((eintrag) => (
  • {eintrag.label} {de.dashboard.unreadCount(eintrag.count)}
  • ))}
)}
{(akte) => }

{de.dashboard.recent}

{daten.zuletzt.length === 0 ? (

{de.dashboard.recentEmpty}

) : (
    {daten.zuletzt.map((akte) => (
  • ))}
)}
) } type Fall = { id: string caseNumber: string title: string status: string classification: number updatedAt: Date dueAt?: Date | null } function Block({ titel, leer, eintraege, children, }: { titel: string leer: string eintraege: Fall[] children: (akte: Fall) => React.ReactNode }) { return (

{titel}

{eintraege.length === 0 ? (

{leer}

) : ( )}
) } function Akte({ akte, levelName, zusatz, dringend, }: { akte: Fall levelName: Map zusatz?: string dringend?: boolean }) { return ( {akte.caseNumber} {akte.title} {zusatz ? ( {zusatz} ) : null} ) } /** * Der Freigabeliste fehlen die Namen: der Auftrag kennt nur Kennungen. Sie * werden hier nachgeschlagen, damit die Leitung sieht, worum es geht — mehr * als Aktenzeichen und Anfragender steht dort bewusst nicht. */ async function beschrifte( jobs: Awaited>, ): Promise< { id: string kind: string label: string requestedBy: string clearanceAtTime: number createdAt: string }[] > { if (jobs.length === 0) return [] const [faelle, dokumente, nutzer] = await Promise.all([ db.case.findMany({ where: { id: { in: jobs.filter((j) => j.kind === 'CASE').map((j) => j.targetId ?? '') } }, select: { id: true, caseNumber: true }, }), db.document.findMany({ where: { id: { in: jobs.filter((j) => j.kind === 'DOCUMENT').map((j) => j.targetId ?? '') } }, select: { id: true, documentNumber: true }, }), db.user.findMany({ where: { id: { in: jobs.map((j) => j.requestedById) } }, select: { id: true, displayName: true }, }), ]) const nummer = new Map([ ...faelle.map((f) => [f.id, f.caseNumber] as const), ...dokumente.map((d) => [d.id, d.documentNumber] as const), ]) const name = new Map(nutzer.map((n) => [n.id, n.displayName])) return jobs.map((job) => ({ id: job.id, kind: job.kind, label: nummer.get(job.targetId ?? '') ?? '—', requestedBy: name.get(job.requestedById) ?? job.requestedById, clearanceAtTime: job.clearanceAtTime, createdAt: job.createdAt.toISOString(), })) }