feat(persoenliche-ausruestung): show catalog category, remove size/date columns, make zustand admin-configurable

This commit is contained in:
Matthias Hochmeister
2026-04-16 08:19:38 +02:00
parent dac0b79b3b
commit 058ee721e8
14 changed files with 282 additions and 96 deletions

View File

@@ -23,13 +23,7 @@ import { usePermissionContext } from '../contexts/PermissionContext';
import ChatAwareFab from '../components/shared/ChatAwareFab';
import { PageHeader } from '../components/templates';
import { KatalogTab } from '../components/shared/KatalogTab';
import {
ZUSTAND_LABELS,
ZUSTAND_COLORS,
} from '../types/personalEquipment.types';
import type { PersoenlicheAusruestungZustand } from '../types/personalEquipment.types';
const ZUSTAND_OPTIONS = Object.entries(ZUSTAND_LABELS) as [PersoenlicheAusruestungZustand, string][];
import type { ZustandOption } from '../types/personalEquipment.types';
function PersoenlicheAusruestungPage() {
const navigate = useNavigate();
@@ -52,6 +46,15 @@ function PersoenlicheAusruestungPage() {
staleTime: 2 * 60 * 1000,
});
const { data: zustandOptions = [] } = useQuery<ZustandOption[]>({
queryKey: ['persoenliche-ausruestung', 'zustand-options'],
queryFn: () => personalEquipmentApi.getZustandOptions(),
staleTime: 5 * 60 * 1000,
});
const getZustandLabel = (key: string) => zustandOptions.find(o => o.key === key)?.label ?? key;
const getZustandColor = (key: string) => zustandOptions.find(o => o.key === key)?.color ?? 'default';
const { data: membersList } = useQuery({
queryKey: ['members-list-compact'],
queryFn: () => membersService.getMembers({ pageSize: 500 }),
@@ -126,8 +129,8 @@ function PersoenlicheAusruestungPage() {
sx={{ minWidth: 140 }}
>
<MenuItem value="">Alle</MenuItem>
{ZUSTAND_OPTIONS.map(([key, label]) => (
<MenuItem key={key} value={key}>{label}</MenuItem>
{zustandOptions.map((opt) => (
<MenuItem key={opt.key} value={opt.key}>{opt.label}</MenuItem>
))}
</TextField>
{canSeeAll && (
@@ -178,15 +181,13 @@ function PersoenlicheAusruestungPage() {
<th>Bezeichnung</th>
<th>Kategorie</th>
{canSeeAll && <th>Benutzer</th>}
<th>Größe</th>
<th>Zustand</th>
<th>Anschaffung</th>
</tr>
</thead>
<tbody>
{isLoading ? (
<tr>
<td colSpan={canSeeAll ? 6 : 5}>
<td colSpan={canSeeAll ? 4 : 3}>
<Typography color="text.secondary" sx={{ py: 4, textAlign: 'center' }}>
Lade Daten
</Typography>
@@ -194,7 +195,7 @@ function PersoenlicheAusruestungPage() {
</tr>
) : filtered.length === 0 ? (
<tr>
<td colSpan={canSeeAll ? 6 : 5}>
<td colSpan={canSeeAll ? 4 : 3}>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', py: 6 }}>
<CheckroomIcon sx={{ fontSize: 48, color: 'text.disabled', mb: 1 }} />
<Typography color="text.secondary">
@@ -230,7 +231,7 @@ function PersoenlicheAusruestungPage() {
)}
</td>
<td>
<Typography variant="body2">{item.kategorie ?? '—'}</Typography>
<Typography variant="body2">{item.artikel_kategorie_name ?? item.kategorie ?? '—'}</Typography>
</td>
{canSeeAll && (
<td>
@@ -239,24 +240,14 @@ function PersoenlicheAusruestungPage() {
</Typography>
</td>
)}
<td>
<Typography variant="body2">{item.groesse ?? '—'}</Typography>
</td>
<td>
<Chip
label={ZUSTAND_LABELS[item.zustand]}
color={ZUSTAND_COLORS[item.zustand]}
label={getZustandLabel(item.zustand)}
color={getZustandColor(item.zustand) as any}
size="small"
variant="outlined"
/>
</td>
<td>
<Typography variant="body2">
{item.anschaffung_datum
? new Date(item.anschaffung_datum).toLocaleDateString('de-AT')
: '—'}
</Typography>
</td>
</tr>
))
)}