Ein Wert, ein Ort: Startwerte und Raten read-only, Verteil-Dialoge als einziger Eingabeort
Deploy App / deploy (push) Successful in 1m13s
Deploy App / deploy (push) Successful in 1m13s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -239,10 +239,15 @@ const KINDS: Kind[] = [
|
||||
export interface InventoryDraft {
|
||||
base: Record<string, PhaseData>;
|
||||
names: Record<string, string>;
|
||||
// Cash ist kein Element, sondern eine Eigenschaft des Szenarios (`Scenario.initialCash`) --
|
||||
// deshalb kein Plus-Knopf, sondern ein festes Feld. Es fehlte bis 0.39 ganz: Die Summe
|
||||
// «Vermögen heute» rechnete es bereits mit, erfassen konnte man es hier aber nirgends.
|
||||
// `null` = unberührt (dann wird beim Speichern auch nichts geschrieben).
|
||||
cash: number | null;
|
||||
}
|
||||
|
||||
export function emptyInventoryDraft(): InventoryDraft {
|
||||
return { base: {}, names: {} };
|
||||
return { base: {}, names: {}, cash: null };
|
||||
}
|
||||
|
||||
// Bestand eines Elements aus Stammdaten -- dieselbe Rechnung wie in der Kachel «Kennzahlen»,
|
||||
@@ -286,15 +291,27 @@ export function InventoryFields({
|
||||
plan.householdType === "COUPLE" ? ["HOUSEHOLD", "PERSON_A", "PERSON_B"] : ["PERSON_A"];
|
||||
const [page, setPage] = useState(0);
|
||||
const scope = scopes[page];
|
||||
const cash = draft.cash ?? Math.round(plan.initialCash || 0);
|
||||
|
||||
// Live-Summe aus dem ENTWURF: Sie soll sich beim Tippen bewegen, nicht erst beim Speichern.
|
||||
const today = plan.elements.reduce(
|
||||
(sum, e) => sum + wealthOf(e.category, draft.base[e.id] ?? e.baseData ?? {}),
|
||||
plan.initialCash || 0
|
||||
cash
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Cash steht ausserhalb der Reiter: Es ist kein Element und gehört keiner Person --
|
||||
es ist der Topf, aus dem alles fliesst und in den alles zurückfliesst. */}
|
||||
<div className="rounded-xl border border-border bg-surface-2 p-3">
|
||||
<MoneyField
|
||||
label="Cash heute (Konto- und Sparguthaben)"
|
||||
help="Alles, was sofort verfügbar ist. Aus diesem Topf zahlt FPT die Ausgaben; was du sparst und nicht zuteilst, bleibt hier liegen."
|
||||
value={cash}
|
||||
onChange={(x) => setDraft((d) => ({ ...d, cash: x }))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{scopes.length > 1 && (
|
||||
<div className="flex gap-1 rounded-lg border border-border bg-surface-2 p-1 text-xs">
|
||||
{scopes.map((sc, i) => (
|
||||
@@ -436,7 +453,7 @@ function BaseDataCard({
|
||||
const names = { ...d.names };
|
||||
delete base[el.id];
|
||||
delete names[el.id];
|
||||
return { base, names };
|
||||
return { ...d, base, names };
|
||||
});
|
||||
onChanged();
|
||||
}
|
||||
@@ -481,6 +498,10 @@ export async function saveInventoryDraft(plan: PlanInput, draft: InventoryDraft)
|
||||
const base = draft.base[el.id];
|
||||
if (base) await api.put(`/api/elements/${el.id}/base`, base);
|
||||
}
|
||||
// Cash hängt am Szenario, nicht an einem Element -- eigener Endpunkt.
|
||||
if (draft.cash !== null && draft.cash !== plan.initialCash) {
|
||||
await api.patch(`/api/scenarios/${plan.id}`, { initialCash: draft.cash });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -508,7 +529,10 @@ export function InventoryDialog({
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const confirm = useConfirm();
|
||||
|
||||
const dirty = Object.keys(draft.base).length > 0 || Object.keys(draft.names).length > 0;
|
||||
const dirty =
|
||||
Object.keys(draft.base).length > 0 ||
|
||||
Object.keys(draft.names).length > 0 ||
|
||||
(draft.cash !== null && draft.cash !== plan.initialCash);
|
||||
|
||||
async function closeGuarded() {
|
||||
if (!dirty) return onClose();
|
||||
|
||||
Reference in New Issue
Block a user