// Namensgebung und Kopfdaten für den Ausdruck einer Checkliste. // // Reine Funktionen, ohne Datenbank und ohne React — damit die Konvention // geprüft werden kann, ohne eine Seite zu bauen. export type ChecklistArt = "onboarding" | "offboarding"; export const CHECKLIST_ARTEN: readonly ChecklistArt[] = ["onboarding", "offboarding"]; export function parseArt(wert: string | undefined): ChecklistArt { return wert === "offboarding" ? "offboarding" : "onboarding"; } /** Wie die Liste im Titel und im Dateinamen heisst. */ export function artLabel(art: ChecklistArt): string { return art === "offboarding" ? "Offboarding-Checklist" : "Onboarding-Checklist"; } export function artTitel(art: ChecklistArt): string { return art === "offboarding" ? "Offboarding-Checkliste" : "Onboarding-Checkliste"; } /** * Umlaute und Sonderzeichen in etwas, das in jedem Dateisystem und in jedem * Skript überlebt. * * Ein blosses NFKD mit anschliessendem Ersetzen aller Nicht-ASCII-Zeichen * würde aus „Müller" ein „Mu-ller" machen: die Zerlegung trennt den Umlaut in * `u` + kombinierenden Trema, und der Trema wird dann zum Trennstrich. Deshalb * werden die kombinierenden Zeichen ausdrücklich entfernt, nicht ersetzt — und * das scharfe S vorher zu „ss", weil es keine Zerlegung hat. */ export function dateiSicher(text: string): string { return text .replace(/ß/g, "ss") .normalize("NFKD") // \p{M} statt eines Zeichenbereichs: die kombinierenden Zeichen sind // unsichtbar, und ein als Literal geschriebener Bereich könnte bei einem // Kodierungswechsel stillschweigend kaputtgehen — dann fiele die Zeile aus // und die nächste machte aus „Müller" ein „Mu-ller", ohne zu scheitern. .replace(/\p{M}/gu, "") .replace(/[^a-zA-Z0-9]+/g, "-") .replace(/^-+|-+$/g, ""); } /** * `YYYYMMDD_PersNummer_Name_Onboarding-Checklist` * * Der Name steht als `Nachname-Vorname` darin, in derselben Reihenfolge, in * der die Anwendung ihn überall anzeigt — so sortiert sich ein Ordner voller * solcher Dateien von selbst nach Person, und innerhalb einer Person nach * Datum, weil das Datum vorne steht. * * Das Datum ist das des Auszugs, nicht des Eintritts: der Dateiname sagt, * wann dieser Stand gezogen wurde. */ export function checklistDateiname( art: ChecklistArt, person: { personnel_number: number; first_name: string; last_name: string }, auszugsdatum: string ): string { const datum = auszugsdatum.slice(0, 10).replace(/-/g, ""); const name = dateiSicher(`${person.last_name}-${person.first_name}`); return `${datum}_${person.personnel_number}_${name}_${artLabel(art)}`; }