feat: responsive widgets, atemschutz permission UX, event hard-delete

- fix dashboard grid: use auto-fill instead of auto-fit for equal-width widgets
- atemschutz: skip stats/members API calls for non-privileged users, hide
  empty Aktionen column, add personal status subtitle
- kalender: add permanent delete option for events with confirmation dialog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthias Hochmeister
2026-03-03 14:59:08 +01:00
parent 5dfaf7db54
commit b3a2fd9ff9
3 changed files with 117 additions and 38 deletions

View File

@@ -183,20 +183,25 @@ function Atemschutz() {
try {
setLoading(true);
setError(null);
const [traegerData, statsData, membersData] = await Promise.all([
atemschutzApi.getAll(),
atemschutzApi.getStats(),
membersService.getMembers({ pageSize: 500 }),
]);
setTraeger(traegerData);
setStats(statsData);
setMembers(membersData.items);
if (canViewAll) {
const [traegerData, statsData, membersData] = await Promise.all([
atemschutzApi.getAll(),
atemschutzApi.getStats(),
membersService.getMembers({ pageSize: 500 }),
]);
setTraeger(traegerData);
setStats(statsData);
setMembers(membersData.items);
} else {
const traegerData = await atemschutzApi.getAll();
setTraeger(traegerData);
}
} catch {
setError('Atemschutzdaten konnten nicht geladen werden. Bitte versuchen Sie es erneut.');
} finally {
setLoading(false);
}
}, []);
}, [canViewAll]);
useEffect(() => {
fetchData();
@@ -361,6 +366,11 @@ function Atemschutz() {
<Typography variant="h4" gutterBottom sx={{ mb: 0 }}>
Atemschutzverwaltung
</Typography>
{!loading && !canViewAll && (
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
Dein persönlicher Atemschutz-Status
</Typography>
)}
{!loading && stats && canViewAll && (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, mt: 0.5 }}>
<Typography variant="body2" color="text.secondary">
@@ -471,7 +481,7 @@ function Atemschutz() {
<TableCell>Untersuchung gültig bis</TableCell>
<TableCell>Leistungstest gültig bis</TableCell>
<TableCell align="center">Status</TableCell>
<TableCell align="right">Aktionen</TableCell>
{canWrite && <TableCell align="right">Aktionen</TableCell>}
</TableRow>
</TableHead>
<TableBody>
@@ -549,31 +559,29 @@ function Atemschutz() {
variant="filled"
/>
</TableCell>
<TableCell align="right">
{canWrite && (
<Tooltip title="Bearbeiten">
<Button
size="small"
onClick={() => handleOpenEdit(item)}
sx={{ minWidth: 'auto', mr: 0.5 }}
>
<Edit fontSize="small" />
</Button>
</Tooltip>
)}
{canWrite && (
<Tooltip title="Löschen">
<Button
size="small"
color="error"
onClick={() => setDeleteId(item.id)}
sx={{ minWidth: 'auto' }}
>
<Delete fontSize="small" />
</Button>
</Tooltip>
)}
</TableCell>
{canWrite && (
<TableCell align="right">
<Tooltip title="Bearbeiten">
<Button
size="small"
onClick={() => handleOpenEdit(item)}
sx={{ minWidth: 'auto', mr: 0.5 }}
>
<Edit fontSize="small" />
</Button>
</Tooltip>
<Tooltip title="Löschen">
<Button
size="small"
color="error"
onClick={() => setDeleteId(item.id)}
sx={{ minWidth: 'auto' }}
>
<Delete fontSize="small" />
</Button>
</Tooltip>
</TableCell>
)}
</TableRow>
);
})}