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:
@@ -1,9 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { MessageSquarePlus } from "lucide-react";
|
||||
import { MessageSquarePlus, Printer } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { Button, LINK_BUTTON_CLASS } from "@/components/ui/Button";
|
||||
import { useToast } from "@/components/ui/Toast";
|
||||
import {
|
||||
alleReichungen,
|
||||
@@ -34,6 +35,8 @@ type Props = {
|
||||
/** Text, solange keine Liste existiert. */
|
||||
leerText: string;
|
||||
anlegenLabel: string;
|
||||
/** Ziel für den Ausdruck — eine eigene Seite, siehe PrintChecklist. */
|
||||
druckHref: string;
|
||||
onSpeichern: (
|
||||
itemKey: string,
|
||||
teil: { erledigt?: boolean; wert?: string | null; kommentar?: string | null }
|
||||
@@ -41,7 +44,16 @@ type Props = {
|
||||
onAnlegen: () => Promise<ActionResult>;
|
||||
};
|
||||
|
||||
export function ChecklistPanel({ gruppen, staende, vorhanden, leerText, anlegenLabel, onSpeichern, onAnlegen }: Props) {
|
||||
export function ChecklistPanel({
|
||||
gruppen,
|
||||
staende,
|
||||
vorhanden,
|
||||
leerText,
|
||||
anlegenLabel,
|
||||
druckHref,
|
||||
onSpeichern,
|
||||
onAnlegen,
|
||||
}: Props) {
|
||||
const { showToast } = useToast();
|
||||
const router = useRouter();
|
||||
const [laeuft, setLaeuft] = useState<string | null>(null);
|
||||
@@ -86,6 +98,15 @@ export function ChecklistPanel({ gruppen, staende, vorhanden, leerText, anlegenL
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex justify-end">
|
||||
{/* Neuer Tab: der Ausdruck ist eine eigene Seite, und wer ihn schliesst,
|
||||
steht wieder in der Akte statt auf einer leeren Historie. */}
|
||||
<Link href={druckHref} target="_blank" className={LINK_BUTTON_CLASS}>
|
||||
<Printer className="h-4 w-4" />
|
||||
Als PDF speichern
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="rounded border border-border bg-surface px-3 py-2.5">
|
||||
<div className="flex flex-wrap items-baseline justify-between gap-2">
|
||||
<span className="text-sm font-semibold text-ink">
|
||||
|
||||
Reference in New Issue
Block a user