This commit is contained in:
seb
2026-08-06 00:19:21 +02:00
parent 80ca59ab11
commit 855710a198
16 changed files with 270 additions and 185 deletions

View File

@@ -1,95 +1,23 @@
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import { useLocation, useNavigate } from 'react-router-dom';
import { artikelQueryPath } from '../pages/artikel/artikelQuery';
import { defaultCategoryPath, isKategorienPath } from '../pages/artikel/categoryRoute';
const SUB_NAV_WIDTH = 80;
function isSubNavActive(pathname, basePath, segment) {
if (!segment) {
if (isKategorienPath(pathname)) return false;
return pathname === basePath || pathname === `${basePath}/`;
}
if (segment === 'kategorien') {
return isKategorienPath(pathname);
}
const subPath = `${basePath}/${segment}`;
return pathname === subPath || pathname === `${subPath}/`;
}
export default function PageLayout({ title, showTitle = true, titleAction, subNav, basePath, children }) {
const hasSubNav = subNav?.length > 0;
const navigate = useNavigate();
const { pathname } = useLocation();
export default function PageLayout({
title,
showTitle = true,
titleAction,
children,
}) {
return (
<Box sx={{ display: 'flex', gap: 2, minHeight: 0 }}>
<Box
component={hasSubNav ? 'nav' : 'div'}
aria-label={hasSubNav ? 'Unternavigation' : undefined}
sx={{
width: SUB_NAV_WIDTH,
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 1,
}}
>
{hasSubNav &&
subNav.map(({ segment, label, icon: Icon }) => {
const active = isSubNavActive(pathname, basePath, segment);
return (
<IconButton
key={segment || 'index'}
type="button"
aria-label={label}
aria-current={active ? 'page' : undefined}
disableRipple
onMouseDown={(e) => e.preventDefault()}
onClick={() => {
if (!segment && basePath === '/artikel') {
navigate(artikelQueryPath());
return;
}
if (segment === 'kategorien') {
navigate(defaultCategoryPath());
return;
}
navigate(segment ? `${basePath}/${segment}` : basePath);
}}
sx={(theme) => ({
width: 80,
height: 80,
borderRadius: '50%',
color: active ? theme.palette.primary.main : theme.palette.text.secondary,
bgcolor: 'transparent',
'&:hover': {
bgcolor: theme.palette.action.hover,
color: theme.palette.primary.main,
},
})}
>
<Icon sx={{ fontSize: 40 }} />
</IconButton>
);
})}
</Box>
<Box sx={{ flexGrow: 1, minWidth: 0 }}>
{showTitle ? (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, mb: 2 }}>
<Typography variant="h5" sx={{ fontWeight: 700 }}>
{title}
</Typography>
{titleAction}
</Box>
) : null}
{children}
</Box>
<Box sx={{ minWidth: 0 }}>
{showTitle ? (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, mb: 2 }}>
<Typography variant="h5" sx={{ fontWeight: 700 }}>
{title}
</Typography>
{titleAction}
</Box>
) : null}
{children}
</Box>
);
}