diff --git a/app/(app)/page.tsx b/app/(app)/page.tsx
index 4305d06..016b860 100644
--- a/app/(app)/page.tsx
+++ b/app/(app)/page.tsx
@@ -207,7 +207,7 @@ export default async function DashboardPage({
// „(HC)" für Headcount — der Unterschied zur Kachel links ist genau
// der, den die Abkürzung benennt: Köpfe, die heute arbeiten.
{ label: "Aktive Mitarbeiter:innen (HC)", value: activeCount, tone: "default", href: "/employees?status=Aktiv" },
- { label: "Langzeitabwesend", value: karenzCount, tone: "warning", href: "/employees?status=Karenz" },
+ { label: "Langzeitabwesende", value: karenzCount, tone: "warning", href: "/employees?status=Karenz" },
// Ohne Zeitgrenze — anders als die Karte „Anstehend" darunter, die nur
// den eingestellten Vorschauzeitraum zeigt. Ein Eintritt in vier
// Monaten ist vereinbart und zählt, auch wenn er dort nicht auftaucht.
@@ -224,13 +224,14 @@ export default async function DashboardPage({
titel: "Personalbewegung",
kacheln: [
{
- label: "Eintritte (Jahr)",
+ // YTD: seit Jahresbeginn bis heute, nicht das ganze Kalenderjahr.
+ label: "Eintritte (YTD)",
value: hiresYtd,
tone: "success",
href: `/reports?mode=events&eventType=Eintritt&from=${yearStart}&to=${yearEnd}`,
},
{
- label: "Austritte (Jahr)",
+ label: "Austritte (YTD)",
value: exitsYtd,
tone: "danger",
href: `/reports?mode=events&eventType=Austritt&from=${yearStart}&to=${yearEnd}`,
@@ -363,7 +364,20 @@ export default async function DashboardPage({
- {h.first_name && h.last_name ? fmtName(h.first_name, h.last_name) : "Unbekannt"}
+ {/* Der Name führt in die Akte. Ohne den Link war die Karte
+ eine Sackgasse: man sah, dass etwas passiert ist, und
+ musste die Person danach in der Liste suchen. */}
+ {h.first_name && h.last_name ? (
+
+ {fmtName(h.first_name, h.last_name)}
+
+ ) : (
+ Unbekannt
+ )}
{h.event_type}
diff --git a/components/audit/AuditFilters.tsx b/components/audit/AuditFilters.tsx
index ac311a3..551fe6c 100644
--- a/components/audit/AuditFilters.tsx
+++ b/components/audit/AuditFilters.tsx
@@ -22,7 +22,11 @@ const ACTIONS: { value: string; label: string }[] = [
{ value: "Karenz", label: "Langzeitabwesenheit" },
{ value: "Vertragsänderung", label: "Vertragsänderung" },
{ value: "Stammdatenänderung", label: "Stammdatenänderung" },
- { value: "Gehaltsanpassung", label: "Gehaltsanpassung" },
+ // „Gehaltsanpassung" steht nicht mehr zur Auswahl: das Gehalt ist aus dem
+ // Funktionsumfang genommen (es wird in Loga geführt), keine Funktion
+ // schreibt diese Art mehr, und ein Filter, der immer leer ausgeht, sieht
+ // aus wie ein Fehler. Der Wert bleibt im Aufzählungstyp — alte Einträge
+ // aus der Zeit davor sollen lesbar bleiben.
];
export function AuditFilters() {
diff --git a/components/employees/HistorieBearbeiten.tsx b/components/employees/HistorieBearbeiten.tsx
index 9d59f99..8b8dd7c 100644
--- a/components/employees/HistorieBearbeiten.tsx
+++ b/components/employees/HistorieBearbeiten.tsx
@@ -9,6 +9,7 @@ import { TextField } from "@/components/ui/Field";
import { Modal } from "@/components/ui/Modal";
import { useToast } from "@/components/ui/Toast";
import { fmtDate } from "@/lib/format";
+import { auswahlFuer } from "@/lib/historie-felder";
import type { AuditChange } from "@/lib/types";
// Berichtigen, nicht neu erfassen.
@@ -181,14 +182,37 @@ export function HistorieBearbeiten({
{c.vorher === null || c.vorher === "" ? leer : c.vorher}
- setWerte((v) => ({ ...v, [c.feld]: e.target.value }))}
- className="w-full rounded border border-border px-2 py-1 text-sm text-ink
- focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-brand-500"
- />
+ {/* Führt das Feld eine feste Liste, wird sie auch hier
+ angeboten: getippt entstünde sonst ein Wert, den keine
+ Auswertung mehr findet — die Berichtigung schreibt in
+ dieselbe Spalte wie das Formular, nur ohne dessen
+ Prüfung. Welche Felder das sind, steht in
+ lib/historie-felder.ts. */}
+ {auswahlFuer(c.feld) ? (
+
+ ) : (
+ setWerte((v) => ({ ...v, [c.feld]: e.target.value }))}
+ className="w-full rounded border border-border px-2 py-1 text-sm text-ink
+ focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-brand-500"
+ />
+ )}
))}
diff --git a/components/employees/NotfallkontaktModal.tsx b/components/employees/NotfallkontaktModal.tsx
index f536a19..b336901 100644
--- a/components/employees/NotfallkontaktModal.tsx
+++ b/components/employees/NotfallkontaktModal.tsx
@@ -42,7 +42,6 @@ export function NotfallkontaktModal({
const [name, setName] = useState(kontakt.name ?? "");
const [telefon, setTelefon] = useState(kontakt.telefon ?? "");
const [verhaeltnis, setVerhaeltnis] = useState(kontakt.verhaeltnis ?? "");
- const [effectiveDate, setEffectiveDate] = useState(todayIso());
const [pending, setPending] = useState(false);
const vorhanden = Boolean(kontakt.name);
@@ -58,7 +57,7 @@ export function NotfallkontaktModal({
setPending(true);
const result = await changeEmployeeData({
employee_id: employeeId,
- effective_date: effectiveDate,
+ effective_date: todayIso(),
person: {
emergency_contact_name: name.trim(),
emergency_contact_phone: telefon.trim(),
@@ -93,8 +92,11 @@ export function NotfallkontaktModal({
>
}
>
+ {/* Kein „Wirksam ab": ein Notfallkontakt gilt ab sofort. Das Feld stand
+ hier, weil die Datenbankfunktion einen Stichtag kennt — bei einer
+ Telefonnummer, die im Ernstfall gewählt wird, ist ein Datum in der
+ Zukunft keine sinnvolle Angabe, sondern eine Frage zu viel. */}
-
{/* Dieselbe Liste wie im Einstellungsassistenten (EMERGENCY_RELATIONS)
diff --git a/components/employees/RoleEmploymentFields.tsx b/components/employees/RoleEmploymentFields.tsx
index e52b43a..5c7edd0 100644
--- a/components/employees/RoleEmploymentFields.tsx
+++ b/components/employees/RoleEmploymentFields.tsx
@@ -2,7 +2,6 @@
import { SelectField, TextField } from "@/components/ui/Field";
import {
- BEGUENSTIGUNG_AB_GRAD,
GRUND_BEGUENSTIGT_BEHINDERT,
KUENDIGUNGSSCHUTZ_GRUENDE,
} from "@/lib/kuendigungsschutz";
@@ -222,7 +221,7 @@ export function RoleEmploymentFields({ value, onChange }: { value: RoleEmploymen
{value.hasKuendigungsschutz && (
<>
onChange({ kuendigungsschutzGrund: v })}
@@ -278,7 +277,6 @@ export function RoleEmploymentFields({ value, onChange }: { value: RoleEmploymen
type="number"
value={value.behinderungGrad}
onChange={(v) => onChange({ behinderungGrad: v })}
- hint={`In Prozent laut Bescheid. Die Begünstigung beginnt bei ${BEGUENSTIGUNG_AB_GRAD}%.`}
/>
- {/* Eigener Block: im Ernstfall greift jemand danach, und dann darf
- er nicht zwischen den Adressfeldern der Person untergehen. */}
-
@@ -402,6 +385,26 @@ export function DatenAendernPanel({
+
+ {/* Unterhalb der Angehörigen und ganz am Schluss — dieselbe Reihenfolge
+ wie im Reiter „Stammdaten". Vorher stand der Block mitten im
+ Abschnitt „Person", zwischen den Adressfeldern; beides sind
+ Personen im Umfeld, und die beiden gehören nebeneinander. */}
+
- Teilnehmerliste für die Mitarbeiterbefragung: Personalnummer, Name, Standort und die
- Organisationskette von der eigenen Einheit bis ganz oben. Sprache immer „de“, Rolle immer „Respondee“.
- Die Spalte „Email“ bleibt leer, bis die Firmen-E-Mail-Adresse erfasst wird.
-