From cee7081da6ac9a85da29fc0424210950a8126715 Mon Sep 17 00:00:00 2001 From: jan Date: Tue, 12 May 2026 01:53:57 +0200 Subject: [PATCH] Stichtag Timeline fuer Ausgaben und Finanzuebersicht --- src/components/dashboard/budget-column.tsx | 107 +++++--- src/components/dashboard/dashboard-shell.tsx | 274 ++++++++++++------- 2 files changed, 252 insertions(+), 129 deletions(-) diff --git a/src/components/dashboard/budget-column.tsx b/src/components/dashboard/budget-column.tsx index 2f9db10..a19eaf8 100644 --- a/src/components/dashboard/budget-column.tsx +++ b/src/components/dashboard/budget-column.tsx @@ -51,6 +51,13 @@ import { requiresManualApproval } from "@/lib/domain"; +type CutoffSelectionOption = { + value: string; + cutoffId: string; + cutoffPhase: "PRE" | "POST"; + label: string; +}; + type BudgetColumnProps = { group: DashboardWorkingGroup; workingGroups: DashboardWorkingGroup[]; @@ -141,6 +148,42 @@ function createDraft(budget: DashboardBudget): BudgetDraft { }; } +function createCutoffSelectionValue(cutoffId: string, cutoffPhase: "PRE" | "POST") { + return `${cutoffId}:${cutoffPhase}`; +} + +function parseCutoffSelectionValue(value: string) { + const [cutoffId, cutoffPhase] = value.split(":"); + + return { + cutoffId: cutoffId ?? "", + cutoffPhase: cutoffPhase === "POST" ? "POST" : "PRE" + } as const; +} + +function getCutoffSelectionOptions(cutoffs: DashboardPeriodCutoff[]): CutoffSelectionOption[] { + if (cutoffs.length === 0) { + return []; + } + + const options: CutoffSelectionOption[] = cutoffs.map((cutoff) => ({ + value: createCutoffSelectionValue(cutoff.id, "PRE"), + cutoffId: cutoff.id, + cutoffPhase: "PRE" as const, + label: `Pre ${cutoff.name}` + })); + const lastCutoff = cutoffs[cutoffs.length - 1]; + + options.push({ + value: createCutoffSelectionValue(lastCutoff.id, "POST"), + cutoffId: lastCutoff.id, + cutoffPhase: "POST" as const, + label: `Post ${lastCutoff.name}` + }); + + return options; +} + function StatusChips({ expense, canEditDonations, @@ -1078,8 +1121,12 @@ export function BudgetColumn({ const editGroup = workingGroups.find((entry) => entry.id === draft.agId) ?? workingGroups[0] ?? group; const editBudgets = editGroup.budgets; - const selectedCutoff = - cutoffs.find((cutoff) => cutoff.id === draft.cutoffId) ?? cutoffs[0] ?? null; + const cutoffOptions = getCutoffSelectionOptions(cutoffs); + const selectedCutoffValue = createCutoffSelectionValue(draft.cutoffId, draft.cutoffPhase); + const selectedCutoffOption = + cutoffOptions.find((option) => option.value === selectedCutoffValue) ?? + cutoffOptions[0] ?? + null; return ( @@ -1143,38 +1190,24 @@ export function BudgetColumn({ ))} - - updateExpenseDraft(expense, { cutoffId: event.target.value })} - fullWidth - disabled={cutoffs.length === 0} - > - {cutoffs.map((cutoff) => ( - - {cutoff.name} - - ))} - - - updateExpenseDraft(expense, { - cutoffPhase: event.target.value as "PRE" | "POST" - }) - } - fullWidth - > - {`Pre ${selectedCutoff?.name ?? "Open Air"}`} - {`Post ${selectedCutoff?.name ?? "Open Air"}`} - - + { + const next = parseCutoffSelectionValue(event.target.value); + updateExpenseDraft(expense, next); + }} + fullWidth + disabled={cutoffOptions.length === 0} + > + {cutoffOptions.map((option) => ( + + {option.label} + + ))} +