Print a checklist without printing the application around it
The checklist gets a print view: one A4 page, header carrying personnel number, name, date of extract, entry date and position, the items in two flowing columns so twenty-five fit, and two signature lines at the foot. It prints the *state*, dated — not a blank form. The default filename in the save dialog comes from the document title, which is set to the agreed convention: 20260818_2884_Aigner-Manuel_Onboarding-Checklist Surname first, like everywhere else in the application, so a folder of these sorts by person and within a person by date. Umlauts are resolved rather than stripped: the naive route (NFKD, then every non-ASCII to a dash) turns "Müller" into "Mu-ller", because decomposition splits the umlaut and the diaeresis becomes the dash. "Weiß" needs its own rule — it has no decomposition and would otherwise vanish. The reported defect: the printout carried the application's own top bar — hamburger, bell, "Neueinstellung", sign-out. Those are controls; on paper they are decoration, and on a checklist filed in a personnel record, misleading. The rule now sits on AppShell rather than on this one page, so the org-chart print view — which had the same problem — gets it too, along with anything printed later. The shell's padding goes with it: the type area is set by @page on the print page itself, and the shell's would have been added on top. The browser's own header line (date, title, URL) is separate — that is a checkbox in the print dialog, not something CSS can reach. 440 tests pass, including 13 new ones pinning the filename convention. Not yet seen in a browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
54
app/(app)/employees/[id]/checkliste/page.tsx
Normal file
54
app/(app)/employees/[id]/checkliste/page.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { PrintChecklist } from "@/components/employees/PrintChecklist";
|
||||
import { currentUserId } from "@/lib/auth/session";
|
||||
import { artTitel, checklistDateiname, parseArt } from "@/lib/checklist-print";
|
||||
import { loadChecklistPrint } from "@/lib/checklist-print-data";
|
||||
import { withUser } from "@/lib/db";
|
||||
import { todayIso } from "@/lib/format";
|
||||
import { OFFBOARDING_GRUPPEN } from "@/lib/offboarding";
|
||||
import { ONBOARDING_GRUPPEN } from "@/lib/onboarding";
|
||||
|
||||
// Eigene Route statt eines Druckstils auf dem Reiter.
|
||||
//
|
||||
// Der Reiter ist zum Arbeiten gebaut: Haken zum Anklicken, Eingabefelder,
|
||||
// Kommentarknöpfe. Auf Papier ist davon nichts nützlich. Hier entsteht aus
|
||||
// denselben Daten ein Blatt, das den Stand festhält — mit Kopf, Fortschritt
|
||||
// und Platz für zwei Unterschriften.
|
||||
|
||||
type Props = {
|
||||
params: Promise<{ id: string }>;
|
||||
searchParams: Promise<{ art?: string }>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Der Titel ist zugleich der Dateivorschlag im Druckdialog. Er wird hier
|
||||
* gesetzt *und* in der Komponente noch einmal — hier für den Tab und den Fall,
|
||||
* dass jemand die Seite direkt druckt, dort, weil der Titel aus den geladenen
|
||||
* Daten kommt und die Metadaten sonst ein zweites Mal laden müssten.
|
||||
*/
|
||||
export async function generateMetadata({ params, searchParams }: Props) {
|
||||
const [{ id }, sp] = await Promise.all([params, searchParams]);
|
||||
const art = parseArt(sp.art);
|
||||
const daten = await withUser(await currentUserId(), (tx) => loadChecklistPrint(tx, id, art));
|
||||
if (!daten) return { title: artTitel(art) };
|
||||
return { title: checklistDateiname(art, daten.kopf, todayIso()) };
|
||||
}
|
||||
|
||||
export default async function ChecklistPrintPage({ params, searchParams }: Props) {
|
||||
const [{ id }, sp] = await Promise.all([params, searchParams]);
|
||||
const art = parseArt(sp.art);
|
||||
const today = todayIso();
|
||||
|
||||
const daten = await withUser(await currentUserId(), (tx) => loadChecklistPrint(tx, id, art, today));
|
||||
if (!daten) notFound();
|
||||
|
||||
return (
|
||||
<PrintChecklist
|
||||
art={art}
|
||||
kopf={daten.kopf}
|
||||
gruppen={art === "offboarding" ? OFFBOARDING_GRUPPEN : ONBOARDING_GRUPPEN}
|
||||
staende={daten.staende}
|
||||
today={today}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user