import type { AnstehendArt } from "./dashboard-filter"; import type { EmploymentStatus, NoteCategory } from "./types"; // Die Initialen stehen in Weiss darauf, jeder Ton braucht also 4.5:1 gegen // Weiss — nachgerechnet liegt der schwaechste bei 6.11:1. Die Reihe beginnt // bei den beiden Markenfarben (Blau direkt, Rosa in der dunklen Stufe, weil // #F69686 selbst nur 2.18:1 traegt) und faechert von dort auf, damit zwei // Personen nebeneinander nicht denselben Kreis bekommen. const AVATAR_PALETTE = [ "#164194", // Manner Blau "#0d2857", "#a8402e", // dunkles Manner Rosa "#5c2e91", "#0e700e", "#835b00", "#00666d", "#8a2740", ]; // Stable per-employee avatar color when employees.avatar_color isn't set. export function avatarColorFor(seed: string): string { let hash = 0; for (let i = 0; i < seed.length; i++) { hash = (hash << 5) - hash + seed.charCodeAt(i); hash |= 0; } return AVATAR_PALETTE[Math.abs(hash) % AVATAR_PALETTE.length]; } export const STATUS_STYLES: Record = { Aktiv: "bg-success-bg text-success-text", Karenz: "bg-warning-bg text-warning-text", // Rosa statt Blau: „Geplant" ist kein Hinweis und keine Warnung, sondern // der Normalfall ohne besondere Faerbung — und dafuer ist die Markenfarbe // die richtige. Blau wuerde hier nach Bedienelement aussehen. Geplant: "bg-accent-200 text-brand-700", Ausgetreten: "bg-danger-bg text-danger-text", }; type ColorCategory = "success" | "danger" | "warning" | "info" | "purple" | "brand"; export const CATEGORY_STYLES: Record = { success: "bg-success-bg text-success-text", danger: "bg-danger-bg text-danger-text", warning: "bg-warning-bg text-warning-text", info: "bg-info-bg text-info-text", purple: "bg-purple-bg text-purple-text", // Der Chip ohne eigene Bedeutung. Auf accent-200 statt accent-100, weil // die hellere Stufe dem Fehler-Chip zu nahe kommt (dE 5.6 gegen 13.7). brand: "bg-accent-200 text-brand-700", }; // Audit-log / activity-feed action -> badge color, per the action list in // dem Kommentar an audit_log in der ersten Migration. const ACTION_CATEGORY: Record = { Neueinstellung: "success", Wiedereinstellung: "success", Rückkehr: "success", Austritt: "danger", Versetzung: "info", Ausschreibung: "info", "Interne Besetzung": "info", Beförderung: "purple", Reorganisation: "purple", "Reorganisation rückgängig": "purple", Karenz: "warning", Vertragsänderung: "warning", Stammdatenänderung: "warning", Gehaltsanpassung: "warning", }; export function actionBadgeStyle(action: string): string { return CATEGORY_STYLES[ACTION_CATEGORY[action] ?? "brand"]; } /** * Die vier Arten auf der Karte „Anstehend". * * Eigene Zuordnung statt actionBadgeStyle(): das war der Fehler, den sie * ersetzt. Dort wird ueber den **Beschriftungstext** in die Tabelle der * Protokoll-Aktionen nachgeschlagen, und die kennt eine andere Sprache — * „Neueinstellung", nicht „Eintritt". Zwei der vier Beschriftungen standen * gar nicht darin und fielen auf den neutralen Rosa-Chip zurueck. Ein * Nachschlagen, das bei einem Fehlschlag still etwas Plausibles liefert, * faellt eben nicht auf. * * Deshalb hier: nach dem **Wert** verschluesselt, nicht nach der Beschriftung * — eine umbenannte Beschriftung kann die Farben so nicht mehr stillschweigend * verstellen. Und vollstaendig ueber `Record`: eine fuenfte * Art muesste sich hier eintragen, der Typpruefer laesst sie sonst nicht durch. * * Die Farben selbst, nebeneinander gemessen (dE im CIELAB, Kontrast nach * WCAG — schwaechstes Paar 14.2, schwaechster Kontrast 5.49:1): * * Eintritt gruen jemand kommt * Austritt rot jemand geht * Rueckkehr violett weder das eine noch das andere — eine eigene Klasse * Wiedervorlage gelb ein Termin, an dem etwas zu tun ist * * Tuerkis fuer die Rueckkehr waere die naheliegendere Lesart gewesen, kam * gegen das Gruen des Eintritts aber nur auf dE 13.0. Violett steht mit 30.8 * eindeutig daneben, und die vier sind das, was sie sein sollen: vier Dinge, * die man im Vorbeigehen auseinanderhaelt. */ export const ANSTEHEND_STYLES: Record = { hire: CATEGORY_STYLES.success, exit: CATEGORY_STYLES.danger, return: CATEGORY_STYLES.purple, note: CATEGORY_STYLES.warning, }; export const NOTE_CATEGORY_STYLES: Record = { Vertraulich: CATEGORY_STYLES.purple, "Personalgespräch": CATEGORY_STYLES.info, Wiedervorlage: CATEGORY_STYLES.warning, "Lob / Anerkennung": CATEGORY_STYLES.success, Allgemein: "bg-surface text-ink-muted", };