Mobile Dropdowns und Aktionen vereinheitlichen
All checks were successful
CI / Build and Deploy (push) Successful in 2m17s

This commit is contained in:
jan
2026-05-06 21:27:40 +02:00
parent 3e5ac7730d
commit 208520cff8
2 changed files with 124 additions and 9 deletions

View File

@@ -271,6 +271,31 @@ export function BudgetColumn({
const selectedBudget = group.budgets.find((budget) => budget.id === selectedBudgetId) ?? group.budgets[0] ?? null;
const visibleBudgets = isCompactLayout && selectedBudget ? [selectedBudget] : group.budgets;
const mobilePrimarySelectSx = {
width: "100%",
"& .MuiOutlinedInput-root": {
minHeight: 64,
borderRadius: "28px",
backgroundColor: alpha(theme.palette.background.paper, isDark ? 0.72 : 0.96),
"& fieldset": {
borderColor: alpha(theme.palette.primary.main, isDark ? 0.54 : 0.38)
},
"&:hover fieldset": {
borderColor: alpha(theme.palette.primary.main, 0.72)
},
"&.Mui-focused fieldset": {
borderWidth: 2,
borderColor: theme.palette.primary.main
}
},
"& .MuiInputLabel-root": {
color: theme.palette.text.secondary
},
"& .MuiInputBase-input": {
fontSize: "1.08rem",
fontWeight: 600
}
} as const;
return (
<Card
@@ -441,6 +466,7 @@ export function BudgetColumn({
value={selectedBudget?.id ?? ""}
onChange={(event) => setSelectedBudgetId(event.target.value)}
fullWidth
sx={mobilePrimarySelectSx}
>
{group.budgets.map((budget) => (
<MenuItem key={budget.id} value={budget.id}>

View File

@@ -175,6 +175,17 @@ function sortManagedUsersList(users: DashboardManagedUser[]) {
type MobileSection = "overview" | "actions";
type MobileAction =
| "expense"
| "budgetRelease"
| "workingGroup"
| "budget"
| "periods"
| "backup"
| "userCreate"
| "approvalThreshold"
| "users"
| "logs";
type DesktopSection = "overview" | "budgetGroups" | "periods" | "users" | "logs";
const currencyFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
@@ -300,6 +311,26 @@ export function DashboardShell({
...(canManageAccounts ? [{ value: "users" as const, label: "Nutzerverwaltung" }] : []),
...(canManageAccounts ? [{ value: "logs" as const, label: "Backup & Log" }] : [])
];
const mobileActions = [
{ value: "expense" as const, label: "Neue Ausgabe" },
...(canManagePeriods ? [{ value: "budgetRelease" as const, label: "Bereits an AG übergeben" }] : []),
...(canManageBudgets(viewer.role)
? [
{ value: "workingGroup" as const, label: "AG anlegen" },
{ value: "budget" as const, label: "Budget anlegen" }
]
: []),
...(canManagePeriods ? [{ value: "periods" as const, label: "Zeitraum" }] : []),
...(canManageAccounts
? [
{ value: "backup" as const, label: "CSV-Backup" },
{ value: "userCreate" as const, label: "Nutzer anlegen" },
{ value: "approvalThreshold" as const, label: "Freigabe-Schwelle" },
{ value: "users" as const, label: "Nutzer verwalten" },
{ value: "logs" as const, label: "Änderungsverlauf" }
]
: [])
];
const showDesktopSectionTabs = !isCompactLayout && desktopSections.length > 1;
const defaultEditableGroup =
@@ -340,6 +371,7 @@ export function DashboardShell({
const [message, setMessage] = useState<DashboardMessage | null>(null);
const [busy, setBusy] = useState(false);
const [mobileSection, setMobileSection] = useState<MobileSection>("overview");
const [selectedMobileAction, setSelectedMobileAction] = useState<MobileAction>("expense");
const [desktopSection, setDesktopSection] = useState<DesktopSection>("overview");
const [selectedCurrentPeriodId, setSelectedCurrentPeriodId] = useState(currentPeriodId);
const [selectedMobileGroupId, setSelectedMobileGroupId] = useState(visibleGroups[0]?.id ?? "");
@@ -377,6 +409,12 @@ export function DashboardShell({
}
}, [desktopSection, desktopSections]);
useEffect(() => {
if (!mobileActions.some((action) => action.value === selectedMobileAction)) {
setSelectedMobileAction(mobileActions[0]?.value ?? "expense");
}
}, [mobileActions, selectedMobileAction]);
useEffect(() => {
const directGroupId = searchParams.get("group");
const budgetId = searchParams.get("budget");
@@ -1450,6 +1488,32 @@ export function DashboardShell({
overflow: "hidden"
};
const mobilePrimarySelectSx = {
width: "100%",
"& .MuiOutlinedInput-root": {
minHeight: 64,
borderRadius: "28px",
backgroundColor: alpha(theme.palette.background.paper, isDark ? 0.72 : 0.96),
"& fieldset": {
borderColor: alpha(theme.palette.primary.main, isDark ? 0.54 : 0.38)
},
"&:hover fieldset": {
borderColor: alpha(theme.palette.primary.main, 0.72)
},
"&.Mui-focused fieldset": {
borderWidth: 2,
borderColor: theme.palette.primary.main
}
},
"& .MuiInputLabel-root": {
color: theme.palette.text.secondary
},
"& .MuiInputBase-input": {
fontSize: "1.08rem",
fontWeight: 600
}
} as const;
const periodManagementPanel = canManagePeriods ? (
<Stack spacing={2}>
<Box>
@@ -1655,7 +1719,24 @@ export function DashboardShell({
: null)
}}
>
{isCompactLayout || desktopSection === "overview" ? (
{isCompactLayout ? (
<TextField
select
label="Aktion auswählen"
value={selectedMobileAction}
onChange={(event) => setSelectedMobileAction(event.target.value as MobileAction)}
fullWidth
sx={mobilePrimarySelectSx}
>
{mobileActions.map((action) => (
<MenuItem key={action.value} value={action.value}>
{action.label}
</MenuItem>
))}
</TextField>
) : null}
{(isCompactLayout ? selectedMobileAction === "expense" : desktopSection === "overview") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2.5}>
@@ -1777,7 +1858,7 @@ export function DashboardShell({
</Card>
) : null}
{canManagePeriods && (isCompactLayout || desktopSection === "overview") ? (
{canManagePeriods && (isCompactLayout ? selectedMobileAction === "budgetRelease" : desktopSection === "overview") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2.5}>
@@ -1869,7 +1950,7 @@ export function DashboardShell({
</Card>
) : null}
{canManageBudgets(viewer.role) && (isCompactLayout || desktopSection === "budgetGroups") ? (
{canManageBudgets(viewer.role) && (isCompactLayout ? selectedMobileAction === "workingGroup" : desktopSection === "budgetGroups") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2.5}>
@@ -1902,7 +1983,7 @@ export function DashboardShell({
</Card>
) : null}
{canManageBudgets(viewer.role) && (isCompactLayout || desktopSection === "budgetGroups") ? (
{canManageBudgets(viewer.role) && (isCompactLayout ? selectedMobileAction === "budget" : desktopSection === "budgetGroups") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2.5}>
@@ -1983,13 +2064,13 @@ export function DashboardShell({
</Card>
) : null}
{canManagePeriods && isCompactLayout ? (
{canManagePeriods && isCompactLayout && selectedMobileAction === "periods" ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>{periodManagementPanel}</CardContent>
</Card>
) : null}
{canManageAccounts && (isCompactLayout || desktopSection === "logs") ? (
{canManageAccounts && (isCompactLayout ? selectedMobileAction === "backup" : desktopSection === "logs") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2}>
@@ -2038,8 +2119,12 @@ export function DashboardShell({
</Card>
) : null}
{canManageAccounts && (isCompactLayout || desktopSection === "users") ? (
{canManageAccounts &&
(isCompactLayout
? selectedMobileAction === "userCreate" || selectedMobileAction === "approvalThreshold"
: desktopSection === "users") ? (
<Stack spacing={3}>
{!isCompactLayout || selectedMobileAction === "userCreate" ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2.5}>
@@ -2141,7 +2226,9 @@ export function DashboardShell({
</Stack>
</CardContent>
</Card>
) : null}
{!isCompactLayout || selectedMobileAction === "approvalThreshold" ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2}>
@@ -2168,9 +2255,10 @@ export function DashboardShell({
</Stack>
</CardContent>
</Card>
) : null}
</Stack>
) : null}
{canManageAccounts && (isCompactLayout || desktopSection === "users") ? (
{canManageAccounts && (isCompactLayout ? selectedMobileAction === "users" : desktopSection === "users") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2}>
@@ -2412,7 +2500,7 @@ export function DashboardShell({
</CardContent>
</Card>
) : null}
{canManageAccounts && (isCompactLayout || desktopSection === "logs") ? (
{canManageAccounts && (isCompactLayout ? selectedMobileAction === "logs" : desktopSection === "logs") ? (
<Card sx={islandCardSx}>
<CardContent sx={{ p: 3 }}>
<Stack spacing={2}>
@@ -2532,6 +2620,7 @@ export function DashboardShell({
setFocusedBudgetId(null);
}}
fullWidth
sx={mobilePrimarySelectSx}
>
{visibleGroups.map((group) => (
<MenuItem key={group.id} value={group.id}>