V5-Modell: Einkommen nominal, Ausgaben real->nominal, Inflation plan-weit, Sparquoten-Grafik
Deploy App / deploy (push) Successful in 57s
Deploy App / deploy (push) Successful in 57s
- Einkommen: nominale Basis + nominale Lohnerhoehung (Default 0). Real read-only als Info. - Ausgaben: REALE Basis (heutige Kaufkraft) + reale Mehrausgaben (Default 0); nominal = real x plan-weite Inflation, read-only. Loest die "nominale Ausgaben verwirren"-Problematik. - Inflation nur noch plan-weit (Phasen-Override entfernt). - Engine liefert flowDeflatorEnd (Flow-Realwerte) + yearly-Serie (Jahr/Alter/Einkommen/ Ausgabe nominal/real). Nominal/Real-Umschalter nutzt Flow- vs. Bestands-Deflatoren. - Neue Grafik (Dashboard): Einkommen vs. nominale Ausgabe mit eingefaerbter Sparquoten- Flaeche (gruen/rot) + reale Ausgabe als Referenzlinie (Inflationskeil). - In-Tool-Erklaerungen in den Einkommen/Ausgaben-Popups. - Golden Tests aufs neue Modell hergeleitet (8 gruen, u.a. Ausgaben real->nominal, Ruin 94). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,20 +10,17 @@ export function PhaseDetail({
|
||||
phase,
|
||||
maxDurationYears,
|
||||
isLast,
|
||||
inflationDefault,
|
||||
onSaved,
|
||||
onDeleted,
|
||||
}: {
|
||||
phase: PhaseInput;
|
||||
maxDurationYears: number | null;
|
||||
isLast: boolean;
|
||||
inflationDefault: number;
|
||||
onSaved: () => void;
|
||||
onDeleted: () => void;
|
||||
}) {
|
||||
const [name, setName] = useState(phase.name);
|
||||
const [durationYears, setDurationYears] = useState(phase.durationYears);
|
||||
const [inflationRate, setInflationRate] = useState<number | null>(phase.inflationRate);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -33,7 +30,7 @@ export function PhaseDetail({
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
try {
|
||||
await api.put(`/api/phases/${phase.id}`, { name, durationYears, inflationRate });
|
||||
await api.put(`/api/phases/${phase.id}`, { name, durationYears });
|
||||
onSaved();
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : "Speichern fehlgeschlagen.");
|
||||
@@ -69,7 +66,7 @@ export function PhaseDetail({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
<TextField label="Bezeichnung" value={name} onChange={setName} />
|
||||
<NumberField
|
||||
label={`Dauer (Jahre)${cap != null ? ` · max. ${cap}` : ""}`}
|
||||
@@ -79,14 +76,8 @@ export function PhaseDetail({
|
||||
max={cap ?? undefined}
|
||||
onChange={(v) => setDurationYears(cap != null ? Math.min(v, cap) : v)}
|
||||
/>
|
||||
<NumberField
|
||||
label="Inflationsrate (%)"
|
||||
help="Ueberschreibt die Standardannahme aus dem Plan-Grundprofil."
|
||||
value={inflationRate ?? inflationDefault}
|
||||
step={0.1}
|
||||
onChange={setInflationRate}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-faint">Die Inflationsrate gilt plan-weit und wird in den Plan-Einstellungen gesetzt.</p>
|
||||
|
||||
{error && <p className="text-sm text-danger">{error}</p>}
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user