1) Die Kacheln stehen jetzt in drei Gruppen — Personalstand, Personalbewegung, Recruiting & Vakanzen — in der Reihenfolge aus dem Entwurf des Kunden. Acht Zahlen nebeneinander sind acht Zahlen; sie beantworten aber drei verschiedene Fragen, und ohne Ueberschrift muss man jede Beschriftung einzeln lesen, um das herauszufinden. "Aktives Dienstverhaeltnis" steht vorn: es ist die Bezugsgroesse fast jeder Personalkennzahl. 2) Der Namensfilter in "Anstehend" ist jetzt immer da. Die Schwelle "erst ab neun Eintraegen" war in der Bedienung falsch — das Feld erschien bei 180 Tagen und verschwand bei 30, und ein Bedienelement, das je nach Zeitraum da ist oder nicht, wirkt wie ein Fehler. 3b) Der Filter heisst jetzt "Aktives Dienstverhaeltnis (Aktiv + Langzeitabwesenheit)" — derselbe Name wie die Kachel, die dorthin verlinkt. 6) Die Personalnummer wird gegen die Datenbank geprueft, waehrend sie eingetippt wird, und nennt bei einem Treffer die Person, die sie schon hat. hire_employee weist sie weiterhin ab — das bleibt die verbindliche Pruefung, denn zwischen Frage und Anlegen kann jemand anderes dieselbe Nummer vergeben. Nur kam diese Abweisung bisher nach sechs Schritten Eingabe, und das Feld steht im ersten Schritt. Gemerkt wird dabei die gepruefte *Nummer* samt Ergebnis, nicht ein Ja/Nein: so ist die Sperre eine Ableitung aus dem, was im Feld steht, und es gibt keinen Zustand, dessen Zuruecksetzen man vergessen koennte. Zu 4) geprueft, nichts geaendert: die FTE-Kachel rechnet bereits Summe der Wochenstunden der heute Aktiven durch 38,5. Der Berichtemanager rechnet dieselbe Formel, nur als Summe der Einzelquotienten geschrieben.
65 lines
2.9 KiB
TypeScript
65 lines
2.9 KiB
TypeScript
import { SvNummerField } from "@/components/employees/SvNummerField";
|
|
import { TitleFields } from "@/components/employees/TitleFields";
|
|
import { SelectField, TextField } from "@/components/ui/Field";
|
|
import { PersonalnummerField } from "./PersonalnummerField";
|
|
import type { HireDraftData } from "./types";
|
|
|
|
type StepPersonProps = {
|
|
draft: HireDraftData;
|
|
update: (patch: Partial<HireDraftData>) => void;
|
|
locations: { id: string; name: string; country: string }[];
|
|
/** Meldet die geprüfte Personalnummer und ihr Ergebnis — steuert „Weiter". */
|
|
onNummerBefund: (befund: { nummer: number; vergeben: boolean }) => void;
|
|
};
|
|
|
|
export function StepPerson({ draft, update, locations, onNummerBefund }: StepPersonProps) {
|
|
return (
|
|
<div className="flex flex-col gap-4">
|
|
<PersonalnummerField
|
|
wert={draft.personnelNumber}
|
|
onChange={(personnelNumber) => update({ personnelNumber })}
|
|
onBefund={onNummerBefund}
|
|
/>
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
<TextField label="Vorname" required value={draft.firstName} onChange={(firstName) => update({ firstName })} />
|
|
<TextField label="Nachname" required value={draft.lastName} onChange={(lastName) => update({ lastName })} />
|
|
</div>
|
|
<TitleFields value={draft} onChange={update} />
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
<SelectField
|
|
label="Geschlecht"
|
|
required
|
|
value={draft.gender}
|
|
onChange={(gender) => update({ gender: gender as HireDraftData["gender"] })}
|
|
options={[
|
|
{ value: "m", label: "männlich" },
|
|
{ value: "w", label: "weiblich" },
|
|
]}
|
|
/>
|
|
<TextField label="Geburtsdatum" required type="date" value={draft.birthDate} onChange={(birthDate) => update({ birthDate })} />
|
|
</div>
|
|
<SvNummerField
|
|
value={draft.svNummer}
|
|
onChange={(svNummer) => update({ svNummer })}
|
|
locationCountry={locations.find((l) => l.id === draft.locationId)?.country}
|
|
birthDate={draft.birthDate || null}
|
|
/>
|
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
{/* Die private Adresse, nicht die Firmenadresse — die entsteht erst
|
|
mit dem Eintritt. Freiwillig: wer keine hat oder keine angeben
|
|
will, soll nicht gezwungen sein, eine zu erfinden. */}
|
|
<TextField label="Private E-Mail" type="email" value={draft.email} onChange={(email) => update({ email })} />
|
|
<TextField label="Private Telefonnummer" type="tel" value={draft.phone} onChange={(phone) => update({ phone })} />
|
|
</div>
|
|
<SelectField
|
|
label="Standort"
|
|
required
|
|
value={draft.locationId}
|
|
onChange={(locationId) => update({ locationId })}
|
|
placeholder="Bitte wählen…"
|
|
options={locations.map((l) => ({ value: l.id, label: `${l.name} (${l.country})` }))}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|