Angehoerige liessen sich bisher nur anlegen und entfernen. Ein Tippfehler im Namen war nur zu beheben, indem man die Person loeschte und neu anlegte -- zwei Eintraege in der Akte fuer eine Korrektur, und der erste sagte "entfernt", was nicht stimmte. Jetzt steht in jeder Zeile ein Stift, wie beim Notfallkontakt. update_employee_dependent kommt bewusst **ohne** Stichtag. Hinzufuegen und Entfernen tragen einen, dort passiert etwas zu einem Zeitpunkt. Eine Berichtigung nicht: der Wert war schon vorher falsch, und ein "wirksam ab" hiesse, die Person habe bis dahin anders geheissen. Der Eintrag in der Akte nennt deshalb Vorher und Nachher statt eines Datums. In "Daten aendern" standen fuer den Notfallkontakt drei Eingabefelder, waehrend die Angehoerigen darueber als Tabelle mit Knoepfen erscheinen -- zwei Bauformen fuer denselben Zweck, direkt untereinander. Dort steht jetzt derselbe Abschnitt wie im Reiter "Stammdaten"; beide laufen ueber das "Wirksam ab" des Formulars, wie die Angehoerigen es schon taten. Damit schreibt auch nur noch eine Stelle diese drei Spalten. Vorher schickte das Formular sie zusaetzlich im eigenen Aufruf mit.
142 lines
5.2 KiB
TypeScript
142 lines
5.2 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { useState } from "react";
|
|
import { addEmployeeDependent, updateEmployeeDependent } from "@/actions/employees";
|
|
import { Button } from "@/components/ui/Button";
|
|
import { SelectField, TextField } from "@/components/ui/Field";
|
|
import { Modal } from "@/components/ui/Modal";
|
|
import { useToast } from "@/components/ui/Toast";
|
|
import { todayIso } from "@/lib/format";
|
|
import type { Database, RelationshipType } from "@/lib/types";
|
|
|
|
const RELATIONSHIPS: RelationshipType[] = ["Ehepartner:in", "Lebenspartner:in", "Kind", "Sonstige"];
|
|
|
|
type Dependent = Database["public"]["Tables"]["employee_dependents"]["Row"];
|
|
|
|
// Dasselbe Fenster für Anlegen und Berichtigen.
|
|
//
|
|
// Der Unterschied ist nicht die Maske, sondern der Stichtag: beim Anlegen
|
|
// passiert etwas zu einem Zeitpunkt, beim Berichtigen war die Angabe schon
|
|
// vorher falsch. Deshalb steht „Wirksam ab" nur im ersten Fall — ein Datum
|
|
// bei einer Korrektur hiesse, die Person habe bis dahin anders geheissen.
|
|
export function AddDependentModal({
|
|
open,
|
|
onClose,
|
|
employeeId,
|
|
defaultEffectiveDate,
|
|
dependent,
|
|
}: {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
employeeId: string;
|
|
defaultEffectiveDate?: string;
|
|
/** Gesetzt: berichtigen statt anlegen. */
|
|
dependent?: Dependent;
|
|
}) {
|
|
const { showToast } = useToast();
|
|
const router = useRouter();
|
|
const bearbeiten = Boolean(dependent);
|
|
const [firstName, setFirstName] = useState(dependent?.first_name ?? "");
|
|
const [lastName, setLastName] = useState(dependent?.last_name ?? "");
|
|
const [svNummer, setSvNummer] = useState(dependent?.sv_nummer ?? "");
|
|
const [birthDate, setBirthDate] = useState(dependent?.birth_date ?? "");
|
|
const [relationship, setRelationship] = useState<RelationshipType>(
|
|
(dependent?.relationship as RelationshipType) ?? "Kind"
|
|
);
|
|
const [effectiveDate, setEffectiveDate] = useState(defaultEffectiveDate ?? todayIso());
|
|
const [prevDefaultEffectiveDate, setPrevDefaultEffectiveDate] = useState(defaultEffectiveDate);
|
|
const [pending, setPending] = useState(false);
|
|
|
|
// This modal stays mounted while closed, so a mount-time initializer would
|
|
// pin the date forever: DatenAendernPanel drives `defaultEffectiveDate` off
|
|
// its own "Wirksam ab" field, and changing it there has to reach the field
|
|
// below. Same adjust-during-render pattern as CountryPicker.
|
|
if (defaultEffectiveDate !== prevDefaultEffectiveDate) {
|
|
setPrevDefaultEffectiveDate(defaultEffectiveDate);
|
|
if (defaultEffectiveDate) setEffectiveDate(defaultEffectiveDate);
|
|
}
|
|
|
|
function reset() {
|
|
setFirstName("");
|
|
setLastName("");
|
|
setSvNummer("");
|
|
setBirthDate("");
|
|
setRelationship("Kind");
|
|
setEffectiveDate(defaultEffectiveDate ?? todayIso());
|
|
}
|
|
|
|
async function handleSubmit() {
|
|
if (!firstName || !lastName || !birthDate || (!bearbeiten && !effectiveDate)) {
|
|
showToast("Bitte alle Pflichtfelder ausfüllen.", "error");
|
|
return;
|
|
}
|
|
setPending(true);
|
|
const result = bearbeiten
|
|
? await updateEmployeeDependent({
|
|
dependent_id: dependent!.id,
|
|
employee_id: employeeId,
|
|
first_name: firstName,
|
|
last_name: lastName,
|
|
relationship,
|
|
sv_nummer: svNummer,
|
|
birth_date: birthDate,
|
|
})
|
|
: await addEmployeeDependent({
|
|
employee_id: employeeId,
|
|
first_name: firstName,
|
|
last_name: lastName,
|
|
relationship,
|
|
sv_nummer: svNummer || undefined,
|
|
birth_date: birthDate,
|
|
effective_date: effectiveDate,
|
|
});
|
|
setPending(false);
|
|
if (result.success) {
|
|
showToast(bearbeiten ? "Angaben berichtigt." : "Angehörige:r hinzugefügt.");
|
|
router.refresh();
|
|
onClose();
|
|
if (!bearbeiten) reset();
|
|
} else {
|
|
showToast(result.error ?? "Fehler beim Speichern.", "error");
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Modal
|
|
open={open}
|
|
onClose={onClose}
|
|
title={bearbeiten ? "Angehörige:n berichtigen" : "Angehörige:n hinzufügen"}
|
|
footer={
|
|
<>
|
|
<Button variant="ghost" onClick={onClose}>
|
|
Abbrechen
|
|
</Button>
|
|
<Button onClick={handleSubmit} pending={pending}>
|
|
{bearbeiten ? "Speichern" : "Hinzufügen"}
|
|
</Button>
|
|
</>
|
|
}
|
|
>
|
|
<div className="flex flex-col gap-4">
|
|
{!bearbeiten && (
|
|
<TextField label="Wirksam ab" required type="date" value={effectiveDate} onChange={setEffectiveDate} />
|
|
)}
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
<TextField label="Vorname" required value={firstName} onChange={setFirstName} />
|
|
<TextField label="Nachname" required value={lastName} onChange={setLastName} />
|
|
</div>
|
|
<TextField label="SVNR" inputMode="numeric" value={svNummer} onChange={setSvNummer} />
|
|
<TextField label="Geburtsdatum" required type="date" value={birthDate} onChange={setBirthDate} />
|
|
<SelectField
|
|
label="Verwandtschaftsverhältnis"
|
|
required
|
|
value={relationship}
|
|
onChange={(v) => setRelationship(v as RelationshipType)}
|
|
options={RELATIONSHIPS.map((r) => ({ value: r, label: r }))}
|
|
/>
|
|
</div>
|
|
</Modal>
|
|
);
|
|
}
|