Phasen-Kopf: Verteil-Prozent bei der Quote, Start->End-Alter je Person, Vermoegen Start->Ende
Deploy App / deploy (push) Successful in 1m0s
Deploy App / deploy (push) Successful in 1m0s
- Sparquote/Verzehr zeigt in Klammern den bereits verteilten/gedeckten Prozentsatz, z. B. "Sparquote 10'000 (100% verteilt)". - Statt einer Alterszeile je Phase nun pro Person "Name Startalter -> Endalter". - Neue Zeile "Vermoegen Startvermoegen -> Endvermoegen" (nominal). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -308,6 +308,7 @@ export function PlanView({
|
|||||||
<PhaseHeader
|
<PhaseHeader
|
||||||
key={col.phase.id}
|
key={col.phase.id}
|
||||||
phase={col.phase}
|
phase={col.phase}
|
||||||
|
personLabel={personLabel}
|
||||||
onClick={() => setSelected({ type: "phase", phaseId: col.phase.id })}
|
onClick={() => setSelected({ type: "phase", phaseId: col.phase.id })}
|
||||||
active={selected?.type === "phase" && selected.phaseId === col.phase.id}
|
active={selected?.type === "phase" && selected.phaseId === col.phase.id}
|
||||||
/>
|
/>
|
||||||
@@ -596,9 +597,21 @@ function phaseCellContent(ce: ReturnType<PhaseComputed["elements"]["find"]> | un
|
|||||||
return ce.summary || "–";
|
return ce.summary || "–";
|
||||||
}
|
}
|
||||||
|
|
||||||
function PhaseHeader({ phase, onClick, active }: { phase: PhaseComputed; onClick: () => void; active: boolean }) {
|
function PhaseHeader({
|
||||||
|
phase,
|
||||||
|
personLabel,
|
||||||
|
onClick,
|
||||||
|
active,
|
||||||
|
}: {
|
||||||
|
phase: PhaseComputed;
|
||||||
|
personLabel: (role: string) => string;
|
||||||
|
onClick: () => void;
|
||||||
|
active: boolean;
|
||||||
|
}) {
|
||||||
const quotaLabel = phase.isConsumption ? "Verzehr" : "Sparquote";
|
const quotaLabel = phase.isConsumption ? "Verzehr" : "Sparquote";
|
||||||
const quotaRemaining = Math.max(0, phase.quotaRemaining);
|
const quotaTarget = Math.abs(phase.quota);
|
||||||
|
const quotaPct = quotaTarget > 0 ? Math.round((phase.quotaAllocated / quotaTarget) * 100) : 100;
|
||||||
|
const distributedWord = phase.isConsumption ? "gedeckt" : "verteilt";
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
@@ -619,14 +632,20 @@ function PhaseHeader({ phase, onClick, active }: { phase: PhaseComputed; onClick
|
|||||||
{phase.type === "ERWERB" ? "Erwerb" : phase.type === "PENSION" ? "Pension" : "Misch"}
|
{phase.type === "ERWERB" ? "Erwerb" : phase.type === "PENSION" ? "Pension" : "Misch"}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-[10px] text-faint">{phase.durationYears} J.</span>
|
<span className="text-[10px] text-faint">{phase.durationYears} J.</span>
|
||||||
<span className="text-[10px] text-faint">Alter {phase.persons.map((p) => p.startAge).join("/")}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 space-y-0.5 text-[10px] leading-tight text-muted">
|
<div className="mt-1 space-y-0.5 text-[10px] leading-tight text-muted">
|
||||||
|
{phase.persons.map((p) => (
|
||||||
|
<div key={p.role} className="text-faint">
|
||||||
|
{personLabel(p.role)} {p.startAge} → {p.endAge}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
<div>Einkommen {formatChf(phase.incomeTotal)}</div>
|
<div>Einkommen {formatChf(phase.incomeTotal)}</div>
|
||||||
<div>Ausgaben {formatChf(phase.expenseTotal)}</div>
|
<div>Ausgaben {formatChf(phase.expenseTotal)}</div>
|
||||||
<div className={phase.quotaComplete ? "text-success" : "text-danger"}>
|
<div className={phase.quotaComplete ? "text-success" : "text-danger"}>
|
||||||
{quotaLabel} {formatChf(Math.abs(phase.quota))}
|
{quotaLabel} {formatChf(quotaTarget)} ({quotaPct}% {distributedWord})
|
||||||
{!phase.quotaComplete && <span> · offen {formatChf(quotaRemaining)}</span>}
|
</div>
|
||||||
|
<div>
|
||||||
|
Vermoegen {formatChf(phase.startWealthNominal)} → {formatChf(phase.endWealthNominal)}
|
||||||
</div>
|
</div>
|
||||||
<div className={phase.availableCapitalComplete ? "" : "text-danger"}>
|
<div className={phase.availableCapitalComplete ? "" : "text-danger"}>
|
||||||
Kapital {phase.availableCapital === null ? "n.a." : formatChf(phase.availableCapital)}
|
Kapital {phase.availableCapital === null ? "n.a." : formatChf(phase.availableCapital)}
|
||||||
|
|||||||
Reference in New Issue
Block a user