import { notFound } from "next/navigation"; import { EmployeeDetail } from "@/components/employees/EmployeeDetail"; import { currentUserId } from "@/lib/auth/session"; import { withUser } from "@/lib/db"; import { todayIso } from "@/lib/format"; import { breadcrumbLabel, loadOrgMaps } from "@/lib/org"; import { loadPlacements, loadReportingLines } from "@/lib/placement"; import { loadOpenPositions } from "@/lib/positions"; type PageProps = { params: Promise<{ id: string }> }; export default async function EmployeeDetailPage({ params }: PageProps) { const { id } = await params; const today = todayIso(); const data = await withUser(await currentUserId(), async (tx) => { // Vorgesetzte und direkte Berichte stehen nirgends als Spalte — sie // kommen aus om_reporting_lines(). Beide Abfragen schränken *in* der // Funktion ein, es wandern also neun Zeilen über die Leitung und nicht // achthundert. const [employee, ownLines, reports, history, dependents, notes, orgMaps, placements, openPositions] = await Promise.all([ tx.selectFrom("employees").selectAll().where("id", "=", id).executeTakeFirst(), loadReportingLines(tx, today, { employeeId: id }), loadReportingLines(tx, today, { actingManagerId: id }), tx .selectFrom("employee_history") .selectAll() .where("employee_id", "=", id) .orderBy("event_date", "desc") .orderBy("created_at", "desc") .execute(), tx.selectFrom("employee_dependents").selectAll().where("employee_id", "=", id).orderBy("created_at").execute(), tx.selectFrom("employee_notes").selectAll().where("employee_id", "=", id).orderBy("created_at", "desc").execute(), loadOrgMaps(tx), loadPlacements(tx, { asOf: today, employeeIds: [id] }), loadOpenPositions(tx), ]); if (!employee) return null; const line = ownLines[0] ?? null; // Namen für die beteiligten Personen in einem Zug: die Vertretung, die // formal zuständige Leitung und die direkten Berichte. const relatedIds = Array.from( new Set( [line?.acting_manager_id, line?.formal_manager_id, ...reports.map((r) => r.employee_id)].filter( (x): x is string => Boolean(x) ) ) ); const relatedRows = relatedIds.length ? await tx .selectFrom("employees") .select(["id", "first_name", "last_name", "job_title", "status"]) .where("id", "in", relatedIds) .execute() : []; return { employee, line, reports, history, dependents, notes, orgMaps, placement: placements.get(id) ?? null, openPositions, byId: new Map(relatedRows.map((e) => [e.id, e])), }; }); if (!data) notFound(); const { employee, line, reports, history, dependents, notes, orgMaps, placement, openPositions, byId } = data; return ( { const e = byId.get(r.employee_id); return e ? [e] : []; })} history={history ?? []} dependents={dependents ?? []} notes={notes ?? []} locations={orgMaps.locationList} openPositions={openPositions} /> ); }