Add second question (jaren werkzaam) to herregistratie wizard step 1
Step 1 was a single field, making the wizard feel thin. Add "Aantal jaren werkzaam" beside "Gewerkte uren" on the same step (no new step): Draft/Valid gain `jaren`, `next` validates both step-1 fields before advancing, and `validate` parses it for the submitted payload. Verified live: an empty jaren blocks advancing with an inline error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,14 @@ import { Uren, parseUren } from '@registratie/domain/value-objects/uren';
|
||||
/** What the user is typing (raw, possibly invalid). */
|
||||
export interface Draft {
|
||||
uren: string;
|
||||
jaren: string;
|
||||
punten: string;
|
||||
}
|
||||
|
||||
/** What we have AFTER parsing — branded/typed, guaranteed valid. */
|
||||
export interface Valid {
|
||||
uren: Uren;
|
||||
jaren: number;
|
||||
punten: number;
|
||||
}
|
||||
|
||||
@@ -25,26 +27,32 @@ export type WizardState =
|
||||
| { tag: 'Submitted'; data: Valid }
|
||||
| { tag: 'Failed'; data: Valid; error: string };
|
||||
|
||||
export const initial: WizardState = { tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} };
|
||||
export const initial: WizardState = { tag: 'Editing', step: 1, draft: { uren: '', jaren: '', punten: '' }, errors: {} };
|
||||
|
||||
/** Parse every field; on success hand back a Valid, else the per-field errors. */
|
||||
function validate(draft: Draft): Result<Partial<Record<keyof Draft, string>>, Valid> {
|
||||
const uren = parseUren(draft.uren);
|
||||
const jaren = parseUren(draft.jaren);
|
||||
const punten = parseUren(draft.punten);
|
||||
const errors: Partial<Record<keyof Draft, string>> = {};
|
||||
if (!uren.ok) errors.uren = uren.error;
|
||||
if (!jaren.ok) errors.jaren = jaren.error;
|
||||
if (!punten.ok) errors.punten = punten.error;
|
||||
if (uren.ok && punten.ok) return { ok: true, value: { uren: uren.value, punten: punten.value } };
|
||||
if (uren.ok && jaren.ok && punten.ok) {
|
||||
return { ok: true, value: { uren: uren.value, jaren: jaren.value, punten: punten.value } };
|
||||
}
|
||||
return { ok: false, error: errors };
|
||||
}
|
||||
|
||||
/** Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op. */
|
||||
/** Step 1 → 2: advance only when BOTH step-1 fields parse. Illegal elsewhere = no-op. */
|
||||
export function next(s: WizardState): WizardState {
|
||||
if (s.tag !== 'Editing' || s.step !== 1) return s;
|
||||
const uren = parseUren(s.draft.uren);
|
||||
return uren.ok
|
||||
? { ...s, step: 2, errors: {} }
|
||||
: { ...s, errors: { uren: uren.error } };
|
||||
const jaren = parseUren(s.draft.jaren);
|
||||
const errors: Partial<Record<keyof Draft, string>> = {};
|
||||
if (!uren.ok) errors.uren = uren.error;
|
||||
if (!jaren.ok) errors.jaren = jaren.error;
|
||||
return Object.keys(errors).length === 0 ? { ...s, step: 2, errors: {} } : { ...s, errors };
|
||||
}
|
||||
|
||||
export function back(s: WizardState): WizardState {
|
||||
|
||||
Reference in New Issue
Block a user