UI-Gesamtumbau: Du-Form, Inspector-Panel, Onboarding-Assistent, Tour, Palette
Deploy App / deploy (push) Successful in 1m1s
Deploy App / deploy (push) Successful in 1m1s
Rein an der Oberflaeche -- Berechnung, Datenmodell und API-Semantik unveraendert (103 Tests unveraendert gruen). Paket A (Fundament): - durchgehend Du-Form und echte Umlaute in allen sichtbaren Texten, inkl. API-Fehlermeldungen (vorher Mix aus Sie/Du und ae/oe/ue) - neue UI-Primitiven (ui.tsx): Button, Modal mit ESC/Fokus-Falle/Animation, Bestaetigungs-Dialog statt window.confirm, Toasts statt alert, Skeleton-Loader, EmptyState - eigene Attention-Farbe (Amber) fuer offene Entscheide, getrennt vom Akzent - Micro-Interactions mit prefers-reduced-motion-Fallback Paket B (Onboarding, Roadmap Nr. 10): - gefuehrter Plan-Assistent in 5 Schritten; Einkommen bewusst pro Person (raeumt die 9.9-AHV-Falle aus); reine Orchestrierung bestehender Endpunkte - Beispielplan mit einem Klick; Uebergaenge absichtlich offen - interaktive Tour ueber die Planansicht (localStorage, jederzeit neu startbar) - abgeleitete "Naechste Schritte"-Karte (offene Entscheide, fehlende Elemente, fehlende Pensionsphase, Ruin -> Einflussfaktoren) Paket C (Struktur): - Inspector-Panel rechts statt Modals fuer alle Einzel-Bearbeitungen; Matrix bleibt sichtbar, Zellklick wechselt den Inhalt - Phasenkopf auf vier Kern-Infos entschlackt (Rest in der 0.11-Detailansicht) - Matrix mit eigenem Scrollbereich, Koepfe beidachsig fixiert - Sidebar-Gruppen "Meine Plaene" / "Wissen"; "So rechnet FPT" statt SPEZIFIKATION; "Szenario-Profil" statt "Plan-Einstellungen" - Aktions-Icons ohne Hover sichtbar (Touch) Paket D (Extras): - Sparklines je Element-Zeile aus den 0.11-Verlaufswerten - Befehls-Palette (Ctrl/Cmd+K) - Ruin-Banner verlinkt auf die Einflussfaktoren Nebenbei: der ProfileMenu-Lint-Fehler und der Selection-Rest (9.17) sind behoben -- npm run lint laeuft erstmals fehlerfrei. SPEZIFIKATION auf 0.13: neue Kapitel 3.2.8, 3.7.6-3.7.9, 9.23, 9.24; 3.6.3 und 3.7.1 ueberarbeitet, 9.17 bereinigt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,8 +27,8 @@ import { CATEGORY_LABELS } from "@/lib/elements";
|
||||
import type { PlanInput, ScenarioMeta } from "@/lib/types";
|
||||
import type { PlanComputed } from "@/lib/calculations";
|
||||
|
||||
// Farben der Szenario-Serien -- wie im Vermoegensverlauf, damit die Zuordnung vertraut bleibt.
|
||||
const PALETTE = ["#4f46e5", "#0ea5e9", "#16a34a", "#d97706", "#dc2626", "#7c3aed"];
|
||||
// Farben der Szenario-Serien -- wie im Vermögensverlauf, damit die Zuordnung vertraut bleibt.
|
||||
const PALETTE = ["#4f46e5", "#0ea5e9", "#16a34a", "#d97706", "#dc2626", "#7c3äd"];
|
||||
|
||||
const RETURN_LEVEL_OPTIONS: { value: ReturnVolatilityLevel; label: string }[] = [
|
||||
{ value: "sehr_niedrig", label: "Sehr niedrig" },
|
||||
@@ -92,8 +92,8 @@ export function MonteCarloDialog({
|
||||
plan: PlanInput;
|
||||
computed: PlanComputed;
|
||||
meta: ScenarioMeta;
|
||||
// Alle Szenarien dieses Plans (auch nicht ausgewaehlte) -- sie werden geladen, damit sich
|
||||
// die Herkunfts-Kette der Elemente auch ueber uebersprungene Zwischen-Szenarien aufloest.
|
||||
// Alle Szenarien dieses Plans (auch nicht ausgewählte) -- sie werden geladen, damit sich
|
||||
// die Herkunfts-Kette der Elemente auch über übersprungene Zwischen-Szenarien auflöst.
|
||||
scenarios: ScenarioMeta[];
|
||||
onClose: () => void;
|
||||
}) {
|
||||
@@ -119,8 +119,8 @@ export function MonteCarloDialog({
|
||||
|
||||
const scenarioKey = scenarios.map((s) => s.id).join(",");
|
||||
|
||||
// Die uebrigen Szenarien einmalig nachladen. Ein Plan hat realistisch eine Handvoll
|
||||
// Szenarien -- gegenueber tausenden Simulationslaeufen faellt das nicht ins Gewicht.
|
||||
// Die übrigen Szenarien einmalig nachladen. Ein Plan hat realistisch eine Handvoll
|
||||
// Szenarien -- gegenüber tausenden Simulationsläufen fällt das nicht ins Gewicht.
|
||||
useEffect(() => {
|
||||
const missing = scenarios.filter((s) => s.id !== meta.id);
|
||||
if (missing.length === 0) return;
|
||||
@@ -156,7 +156,7 @@ export function MonteCarloDialog({
|
||||
[scenarios, loaded]
|
||||
);
|
||||
|
||||
// Ein Parametersatz je LOGISCHEM Element (ueber die sourceElementId-Kette zusammengefasst).
|
||||
// Ein Parametersatz je LOGISCHEM Element (über die sourceElementId-Kette zusammengefasst).
|
||||
const groups = useMemo(
|
||||
() => buildElementGroups(allLoaded, selectedIds),
|
||||
[allLoaded, selectedIds]
|
||||
@@ -195,8 +195,8 @@ export function MonteCarloDialog({
|
||||
return [g.rootId, { mean: Number(d.mean) || 0, sigma: returnSigma(d), floor: floorFor(g.category) }];
|
||||
})
|
||||
);
|
||||
// EIN Seed fuer alle Szenarien: strukturgleiche Szenarien teilen damit dieselben
|
||||
// Marktpfade, und die Unterschiede sind strukturell statt zufaellig.
|
||||
// EIN Seed für alle Szenarien: strukturgleiche Szenarien teilen damit dieselben
|
||||
// Marktpfade, und die Unterschiede sind strukturell statt zufällig.
|
||||
const seed = (Math.random() * 2 ** 32) >>> 0;
|
||||
const runInputs: ScenarioRunInput[] = selected.map((s) => ({
|
||||
scenarioId: s.id,
|
||||
@@ -239,7 +239,7 @@ export function MonteCarloDialog({
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Erklaerung */}
|
||||
{/* Erklärung */}
|
||||
<div className="rounded-xl border border-border bg-surface-2 p-4 text-xs leading-relaxed text-muted">
|
||||
<p className="mb-2">
|
||||
<strong className="text-fg">Was ist das?</strong> Dein Plan rechnet mit einer festen Rendite und Inflation
|
||||
@@ -479,7 +479,7 @@ function MonteCarloResults({
|
||||
}) {
|
||||
const single = results.length === 1;
|
||||
|
||||
// Einzelnes Szenario: der gewohnte Faecher (Band + Median + Planungslinie).
|
||||
// Einzelnes Szenario: der gewohnte Fächer (Band + Median + Planungslinie).
|
||||
const singleData = useMemo(() => {
|
||||
if (!single) return [];
|
||||
return results[0].bands.map((b) => ({
|
||||
@@ -490,7 +490,7 @@ function MonteCarloResults({
|
||||
}));
|
||||
}, [single, results, detPoints]);
|
||||
|
||||
// Mehrere Szenarien: nur die Median-Linien -- uebereinandergelegte Baender waeren Farbbrei.
|
||||
// Mehrere Szenarien: nur die Median-Linien -- übereinandergelegte Bänder wären Farbbrei.
|
||||
const compareData = useMemo(() => {
|
||||
if (single) return [];
|
||||
const ages = Array.from(new Set(results.flatMap((r) => r.bands.map((b) => b.age)))).sort((a, b) => a - b);
|
||||
|
||||
Reference in New Issue
Block a user