Baustein 6: Checklisten mit Durchlaeufen und PDF-Export

- Durchlauf aus einer Vorlage, mit Datum, Ticket und Kunde
- Schritt fuer Schritt abhaken, Bemerkung je Schritt
- Fortschritt gesamt und je Gruppe (Vorbereiten/Durchfuehren/Pruefen/Abschliessen)
- Abschliessen erst, wenn alles abgehakt ist; Meldung nennt die offenen Schritte
- Abgeschlossene Durchlaeufe sind gesperrt und bleiben als Nachweis
- Titel und Schritttexte werden beim Start kopiert, nicht verwiesen
- PDF-Export mit gezeichneten Ankreuzkaestchen und Unterschriftenzeilen
- Gemeinsame PDF-Grundlage fuer alle kuenftigen Ausgaben
- Ausbilder liest mit und darf das PDF abrufen, hakt aber nicht ab
- Abgeschlossene Durchlaeufe zaehlen im Wochenfortschritt mit

Behoben beim Durchstich: Die Fusszeile wurde unterhalb des Satzspiegels
gesetzt, wodurch PDFKit je Fusszeile eine leere Seite anhaengte - aus zwei
Seiten wurden sechs. Ein Test zaehlt jetzt die Seitenobjekte im PDF.

29 neue Tests, insgesamt 186.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-10 21:00:30 +02:00
co-authored by Claude Opus 5
parent ffbca01bdc
commit b9d6041f3b
41 changed files with 2074 additions and 5 deletions
+117
View File
@@ -1224,3 +1224,120 @@ input[type="file"] {
font: inherit;
min-height: 44px;
}
/* --- Checklisten --- */
.laufzeile {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
background: var(--flaeche);
border: 1px solid var(--rand-zart);
border-radius: var(--radius);
padding: 0.65rem 0.9rem;
}
.laufzeile-haupt {
flex: 1 1 240px;
display: grid;
gap: 0.1rem;
text-decoration: none;
color: var(--text);
}
.laufzeile-haupt:hover { color: var(--petrol); }
.laufzeile-titel { font-weight: 650; }
.laufzeile-stand {
display: flex;
align-items: center;
gap: 0.6rem;
}
.laufzeile-stand .balken { flex-shrink: 0; }
.gruppenstand { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
.gruppenstand li {
display: grid;
grid-template-columns: 1fr 70px 3rem;
align-items: center;
gap: 0.6rem;
font-size: 0.9rem;
}
.gruppenstand .leise { text-align: right; font-variant-numeric: tabular-nums; }
.schrittliste { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.35rem; }
.schrittliste li {
display: flex;
gap: 0.7rem;
align-items: flex-start;
background: var(--flaeche);
border: 1px solid var(--rand-zart);
border-radius: var(--radius-klein);
padding: 0.55rem 0.7rem;
}
.schrittliste li[data-erledigt="ja"] {
background: var(--gut-flaeche);
border-color: var(--gut);
}
.schrittliste li[data-erledigt="ja"] .schritt-text { color: var(--gut); }
.schritt-haken { flex-shrink: 0; }
.hakenknopf {
width: 30px;
height: 30px;
border-radius: var(--radius-klein);
border: 2px solid var(--rand);
background: var(--grund);
color: var(--gut);
font-size: 1.05rem;
font-weight: 700;
line-height: 1;
cursor: pointer;
display: grid;
place-items: center;
padding: 0;
}
.hakenknopf:hover:not(:disabled) { border-color: var(--petrol); }
.hakenknopf[aria-pressed="true"] { border-color: var(--gut); background: var(--gut-flaeche); }
.hakenknopf:disabled { opacity: 0.55; cursor: not-allowed; }
.schritt-inhalt { flex: 1; display: grid; gap: 0.25rem; }
.schritt-text { line-height: 1.45; }
.schritt-notiz > summary {
cursor: pointer;
font-size: 0.85rem;
color: var(--text-leise);
list-style: none;
padding: 0.15rem 0;
min-height: 28px;
display: inline-flex;
align-items: center;
gap: 0.3rem;
}
.schritt-notiz > summary::-webkit-details-marker { display: none; }
.schritt-notiz > summary::before { content: "+"; font-weight: 700; }
.schritt-notiz[open] > summary::before { content: "−"; }
.schritt-notiz > form { margin-top: 0.35rem; }
.schritt-bemerkung {
margin: 0;
font-size: 0.88rem;
font-style: italic;
color: var(--text-leise);
border-left: 3px solid var(--rand);
padding-left: 0.6rem;
}
@media (max-width: 640px) {
.hakenknopf { width: 38px; height: 38px; }
.laufzeile-stand { width: 100%; justify-content: space-between; }
.gruppenstand li { grid-template-columns: 1fr 60px 3rem; }
}
@media print {
.schritt-notiz > summary { display: none; }
.schritt-notiz[open] > form { display: none; }
.hakenknopf { border-color: #666; }
}