Mehrere Stichtage pro Zeitraum verwalten
CI / Build and Deploy (push) Successful in 2m43s

This commit is contained in:
jan
2026-05-12 01:37:28 +02:00
parent 08df13c044
commit 5591d10d96
11 changed files with 790 additions and 88 deletions
+51 -16
View File
@@ -36,6 +36,7 @@ import type {
DashboardBudget,
DashboardExpense,
DashboardExpenseDonation,
DashboardPeriodCutoff,
DashboardViewer,
DashboardWorkingGroup
} from "@/lib/dashboard-types";
@@ -53,6 +54,7 @@ import {
type BudgetColumnProps = {
group: DashboardWorkingGroup;
workingGroups: DashboardWorkingGroup[];
cutoffs: DashboardPeriodCutoff[];
viewer: DashboardViewer;
busy: boolean;
approvalThreshold: number;
@@ -75,6 +77,7 @@ type BudgetColumnProps = {
amount: string;
agId: string;
budgetId: string;
cutoffId: string;
cutoffPhase: "PRE" | "POST";
}
) => Promise<void>;
@@ -208,6 +211,7 @@ function getPaidSpend(expenses: DashboardExpense[]) {
export function BudgetColumn({
group,
workingGroups,
cutoffs,
viewer,
busy,
approvalThreshold,
@@ -240,7 +244,18 @@ export function BudgetColumn({
const [editingExpenseId, setEditingExpenseId] = useState<string | null>(null);
const [editingAssignedDonationId, setEditingAssignedDonationId] = useState<string | null>(null);
const [expenseDrafts, setExpenseDrafts] = useState<
Record<string, { title: string; description: string; amount: string; agId: string; budgetId: string; cutoffPhase: "PRE" | "POST" }>
Record<
string,
{
title: string;
description: string;
amount: string;
agId: string;
budgetId: string;
cutoffId: string;
cutoffPhase: "PRE" | "POST";
}
>
>({});
const [assignedDonationDrafts, setAssignedDonationDrafts] = useState<Record<string, AssignedDonationDraft>>({});
@@ -321,6 +336,7 @@ export function BudgetColumn({
amount: expense.amount.toFixed(2),
agId: group.id,
budgetId: expense.budgetId,
cutoffId: expense.cutoffId ?? cutoffs[0]?.id ?? "",
cutoffPhase: expense.cutoffPhase
};
}
@@ -1062,6 +1078,8 @@ 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;
return (
<Stack spacing={1}>
@@ -1125,21 +1143,38 @@ export function BudgetColumn({
</MenuItem>
))}
</TextField>
<TextField
select
label="Stichtag"
size="small"
value={draft.cutoffPhase}
onChange={(event) =>
updateExpenseDraft(expense, {
cutoffPhase: event.target.value as "PRE" | "POST"
})
}
fullWidth
>
<MenuItem value="PRE">Pre Open Air</MenuItem>
<MenuItem value="POST">Post Open Air</MenuItem>
</TextField>
<Stack direction={{ xs: "column", sm: "row" }} gap={1}>
<TextField
select
label="Stichtag"
size="small"
value={draft.cutoffId}
onChange={(event) => updateExpenseDraft(expense, { cutoffId: event.target.value })}
fullWidth
disabled={cutoffs.length === 0}
>
{cutoffs.map((cutoff) => (
<MenuItem key={cutoff.id} value={cutoff.id}>
{cutoff.name}
</MenuItem>
))}
</TextField>
<TextField
select
label="Zuordnung"
size="small"
value={draft.cutoffPhase}
onChange={(event) =>
updateExpenseDraft(expense, {
cutoffPhase: event.target.value as "PRE" | "POST"
})
}
fullWidth
>
<MenuItem value="PRE">{`Pre ${selectedCutoff?.name ?? "Open Air"}`}</MenuItem>
<MenuItem value="POST">{`Post ${selectedCutoff?.name ?? "Open Air"}`}</MenuItem>
</TextField>
</Stack>
<Stack direction="row" gap={1} useFlexGap flexWrap="wrap">
<Button
type="button"