change label
This commit is contained in:
@@ -257,41 +257,41 @@ export default function AusruestungsanfrageDetail() {
|
|||||||
{editItems.map((item, idx) => (
|
{editItems.map((item, idx) => (
|
||||||
<Box key={idx} sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
|
<Box key={idx} sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
|
||||||
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
|
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
freeSolo
|
freeSolo
|
||||||
options={catalogItems}
|
options={catalogItems}
|
||||||
getOptionLabel={o => typeof o === 'string' ? o : o.bezeichnung}
|
getOptionLabel={o => typeof o === 'string' ? o : o.bezeichnung}
|
||||||
value={item.artikel_id ? catalogItems.find(c => c.id === item.artikel_id) || item.bezeichnung : item.bezeichnung}
|
value={item.artikel_id ? catalogItems.find(c => c.id === item.artikel_id) || item.bezeichnung : item.bezeichnung}
|
||||||
onChange={(_, v) => {
|
onChange={(_, v) => {
|
||||||
if (typeof v === 'string') {
|
if (typeof v === 'string') {
|
||||||
updateEditItem(idx, 'bezeichnung', v);
|
updateEditItem(idx, 'bezeichnung', v);
|
||||||
updateEditItem(idx, 'artikel_id', undefined);
|
updateEditItem(idx, 'artikel_id', undefined);
|
||||||
} else if (v) {
|
} else if (v) {
|
||||||
setEditItems(prev => prev.map((it, i) => i === idx ? { ...it, artikel_id: v.id, bezeichnung: v.bezeichnung } : it));
|
setEditItems(prev => prev.map((it, i) => i === idx ? { ...it, artikel_id: v.id, bezeichnung: v.bezeichnung } : it));
|
||||||
loadEigenschaftenForItem(v.id);
|
loadEigenschaftenForItem(v.id);
|
||||||
setEditItemEigenschaftValues(prev => { const n = { ...prev }; delete n[idx]; return n; });
|
setEditItemEigenschaftValues(prev => { const n = { ...prev }; delete n[idx]; return n; });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onInputChange={(_, val, reason) => {
|
onInputChange={(_, val, reason) => {
|
||||||
if (reason === 'input') {
|
if (reason === 'input') {
|
||||||
setEditItems(prev => prev.map((it, i) => i === idx ? { ...it, bezeichnung: val, artikel_id: undefined } : it));
|
setEditItems(prev => prev.map((it, i) => i === idx ? { ...it, bezeichnung: val, artikel_id: undefined } : it));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
renderInput={params => <TextField {...params} label="Artikel" size="small" />}
|
renderInput={params => <TextField {...params} label="Artikel" size="small" />}
|
||||||
sx={{ flexGrow: 1 }}
|
sx={{ flexGrow: 1 }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
type="number"
|
type="number"
|
||||||
label="Menge"
|
label="Menge"
|
||||||
value={item.menge}
|
value={item.menge}
|
||||||
onChange={e => updateEditItem(idx, 'menge', Math.max(1, Number(e.target.value)))}
|
onChange={e => updateEditItem(idx, 'menge', Math.max(1, Number(e.target.value)))}
|
||||||
sx={{ width: 90 }}
|
sx={{ width: 90 }}
|
||||||
inputProps={{ min: 1 }}
|
inputProps={{ min: 1 }}
|
||||||
/>
|
/>
|
||||||
<IconButton size="small" onClick={() => removeEditItem(idx)}>
|
<IconButton size="small" onClick={() => removeEditItem(idx)}>
|
||||||
<DeleteIcon fontSize="small" />
|
<DeleteIcon fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
{item.artikel_id && editItemEigenschaften[item.artikel_id]?.length > 0 && (
|
{item.artikel_id && editItemEigenschaften[item.artikel_id]?.length > 0 && (
|
||||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, ml: 1, pl: 1.5, borderLeft: '2px solid', borderColor: 'divider' }}>
|
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, ml: 1, pl: 1.5, borderLeft: '2px solid', borderColor: 'divider' }}>
|
||||||
@@ -430,7 +430,7 @@ export default function AusruestungsanfrageDetail() {
|
|||||||
<Chip label="Im Haus" size="small" color="success" />
|
<Chip label="Im Haus" size="small" color="success" />
|
||||||
)}
|
)}
|
||||||
{p.geliefert && p.zuweisung_typ === 'keine' && (
|
{p.geliefert && p.zuweisung_typ === 'keine' && (
|
||||||
<Chip label="Nicht verfolgt" size="small" color="default" variant="outlined" />
|
<Chip label="Nicht zugewiesen" size="small" color="default" variant="outlined" />
|
||||||
)}
|
)}
|
||||||
{p.geliefert && p.zuweisung_typ === 'persoenlich' && (
|
{p.geliefert && p.zuweisung_typ === 'persoenlich' && (
|
||||||
<Chip label="Persönlich" size="small" color="primary" variant="outlined" />
|
<Chip label="Persönlich" size="small" color="primary" variant="outlined" />
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ export default function AusruestungsanfrageZuweisung() {
|
|||||||
>
|
>
|
||||||
<ToggleButton value="ausruestung" disabled={!pos.artikel_id}>Ausrüstung</ToggleButton>
|
<ToggleButton value="ausruestung" disabled={!pos.artikel_id}>Ausrüstung</ToggleButton>
|
||||||
<ToggleButton value="persoenlich" disabled={!pos.artikel_id}>Persönlich</ToggleButton>
|
<ToggleButton value="persoenlich" disabled={!pos.artikel_id}>Persönlich</ToggleButton>
|
||||||
<ToggleButton value="keine">Nicht verfolgt</ToggleButton>
|
<ToggleButton value="keine">Nicht zuweisen</ToggleButton>
|
||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
|
|
||||||
{a.typ === 'ausruestung' && (
|
{a.typ === 'ausruestung' && (
|
||||||
|
|||||||
@@ -102,166 +102,166 @@ function PersoenlicheAusruestungPage() {
|
|||||||
<Tabs value={activeTab} onChange={(_e, v) => setActiveTab(v)} sx={{ mb: 3 }}>
|
<Tabs value={activeTab} onChange={(_e, v) => setActiveTab(v)} sx={{ mb: 3 }}>
|
||||||
<Tab label="Zuweisungen" />
|
<Tab label="Zuweisungen" />
|
||||||
<Tab label="Katalog" />
|
<Tab label="Katalog" />
|
||||||
{canApprove && <Tab label="Nicht verfolgt" />}
|
{canApprove && <Tab label="Nicht zugewiesen" />}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
{activeTab === 0 && (
|
{activeTab === 0 && (
|
||||||
<>
|
<>
|
||||||
{/* Filters */}
|
{/* Filters */}
|
||||||
<Box sx={{ display: 'flex', gap: 2, mb: 3, flexWrap: 'wrap', alignItems: 'center' }}>
|
<Box sx={{ display: 'flex', gap: 2, mb: 3, flexWrap: 'wrap', alignItems: 'center' }}>
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="Suche…"
|
placeholder="Suche…"
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
sx={{ minWidth: 200 }}
|
sx={{ minWidth: 200 }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
select
|
select
|
||||||
label="Zustand"
|
label="Zustand"
|
||||||
value={filterZustand}
|
value={filterZustand}
|
||||||
onChange={(e) => setFilterZustand(e.target.value)}
|
onChange={(e) => setFilterZustand(e.target.value)}
|
||||||
sx={{ minWidth: 140 }}
|
sx={{ minWidth: 140 }}
|
||||||
>
|
>
|
||||||
<MenuItem value="">Alle</MenuItem>
|
<MenuItem value="">Alle</MenuItem>
|
||||||
{ZUSTAND_OPTIONS.map(([key, label]) => (
|
{ZUSTAND_OPTIONS.map(([key, label]) => (
|
||||||
<MenuItem key={key} value={key}>{label}</MenuItem>
|
<MenuItem key={key} value={key}>{label}</MenuItem>
|
||||||
))}
|
))}
|
||||||
</TextField>
|
</TextField>
|
||||||
{canViewAll && (
|
{canViewAll && (
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
size="small"
|
size="small"
|
||||||
options={memberOptions}
|
options={memberOptions}
|
||||||
getOptionLabel={(o) => o.name}
|
getOptionLabel={(o) => o.name}
|
||||||
value={memberOptions.find((m) => m.id === filterUser) ?? null}
|
value={memberOptions.find((m) => m.id === filterUser) ?? null}
|
||||||
onChange={(_e, v) => setFilterUser(v?.id ?? '')}
|
onChange={(_e, v) => setFilterUser(v?.id ?? '')}
|
||||||
renderInput={(params) => <TextField {...params} label="Benutzer" />}
|
renderInput={(params) => <TextField {...params} label="Benutzer" />}
|
||||||
sx={{ minWidth: 200 }}
|
sx={{ minWidth: 200 }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ ml: 'auto' }}>
|
<Typography variant="body2" color="text.secondary" sx={{ ml: 'auto' }}>
|
||||||
{filtered.length} {filtered.length === 1 ? 'Eintrag' : 'Einträge'}
|
{filtered.length} {filtered.length === 1 ? 'Eintrag' : 'Einträge'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Table */}
|
{/* Table */}
|
||||||
<Box sx={{ overflowX: 'auto' }}>
|
<Box sx={{ overflowX: 'auto' }}>
|
||||||
<Box
|
<Box
|
||||||
component="table"
|
component="table"
|
||||||
sx={{
|
sx={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
borderCollapse: 'collapse',
|
borderCollapse: 'collapse',
|
||||||
'& th, & td': {
|
'& th, & td': {
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
py: 1.5,
|
py: 1.5,
|
||||||
px: 2,
|
px: 2,
|
||||||
borderBottom: '1px solid',
|
borderBottom: '1px solid',
|
||||||
borderColor: 'divider',
|
borderColor: 'divider',
|
||||||
},
|
},
|
||||||
'& th': {
|
'& th': {
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontSize: '0.75rem',
|
fontSize: '0.75rem',
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
color: 'text.secondary',
|
color: 'text.secondary',
|
||||||
letterSpacing: '0.06em',
|
letterSpacing: '0.06em',
|
||||||
},
|
},
|
||||||
'& tbody tr': {
|
'& tbody tr': {
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
'&:hover': { bgcolor: 'action.hover' },
|
'&:hover': { bgcolor: 'action.hover' },
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Bezeichnung</th>
|
<th>Bezeichnung</th>
|
||||||
<th>Kategorie</th>
|
<th>Kategorie</th>
|
||||||
{canViewAll && <th>Benutzer</th>}
|
{canViewAll && <th>Benutzer</th>}
|
||||||
<th>Größe</th>
|
<th>Größe</th>
|
||||||
<th>Zustand</th>
|
<th>Zustand</th>
|
||||||
<th>Anschaffung</th>
|
<th>Anschaffung</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={canViewAll ? 6 : 5}>
|
<td colSpan={canViewAll ? 6 : 5}>
|
||||||
<Typography color="text.secondary" sx={{ py: 4, textAlign: 'center' }}>
|
<Typography color="text.secondary" sx={{ py: 4, textAlign: 'center' }}>
|
||||||
Lade Daten…
|
Lade Daten…
|
||||||
</Typography>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : filtered.length === 0 ? (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={canViewAll ? 6 : 5}>
|
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', py: 6 }}>
|
|
||||||
<CheckroomIcon sx={{ fontSize: 48, color: 'text.disabled', mb: 1 }} />
|
|
||||||
<Typography color="text.secondary">
|
|
||||||
Keine Einträge gefunden
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : (
|
|
||||||
filtered.map((item) => (
|
|
||||||
<tr key={item.id} onClick={() => navigate(`/persoenliche-ausruestung/${item.id}`)}>
|
|
||||||
<td>
|
|
||||||
<Typography variant="body2" fontWeight={500}>
|
|
||||||
{item.bezeichnung}
|
|
||||||
</Typography>
|
|
||||||
{item.artikel_bezeichnung && (
|
|
||||||
<Typography variant="caption" color="text.secondary">
|
|
||||||
{item.artikel_bezeichnung}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
{item.eigenschaften && item.eigenschaften.length > 0 && (
|
|
||||||
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', mt: 0.5 }}>
|
|
||||||
{item.eigenschaften.map((e) => (
|
|
||||||
<Chip
|
|
||||||
key={e.id}
|
|
||||||
label={`${e.name}: ${e.wert}`}
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
sx={{ height: 20, fontSize: '0.7rem' }}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Typography variant="body2">{item.kategorie ?? '—'}</Typography>
|
|
||||||
</td>
|
|
||||||
{canViewAll && (
|
|
||||||
<td>
|
|
||||||
<Typography variant="body2">
|
|
||||||
{item.user_display_name ?? item.benutzer_name ?? '—'}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</td>
|
</td>
|
||||||
)}
|
</tr>
|
||||||
<td>
|
) : filtered.length === 0 ? (
|
||||||
<Typography variant="body2">{item.groesse ?? '—'}</Typography>
|
<tr>
|
||||||
</td>
|
<td colSpan={canViewAll ? 6 : 5}>
|
||||||
<td>
|
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', py: 6 }}>
|
||||||
<Chip
|
<CheckroomIcon sx={{ fontSize: 48, color: 'text.disabled', mb: 1 }} />
|
||||||
label={ZUSTAND_LABELS[item.zustand]}
|
<Typography color="text.secondary">
|
||||||
color={ZUSTAND_COLORS[item.zustand]}
|
Keine Einträge gefunden
|
||||||
size="small"
|
</Typography>
|
||||||
variant="outlined"
|
</Box>
|
||||||
/>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>
|
) : (
|
||||||
<Typography variant="body2">
|
filtered.map((item) => (
|
||||||
{item.anschaffung_datum
|
<tr key={item.id} onClick={() => navigate(`/persoenliche-ausruestung/${item.id}`)}>
|
||||||
? new Date(item.anschaffung_datum).toLocaleDateString('de-AT')
|
<td>
|
||||||
: '—'}
|
<Typography variant="body2" fontWeight={500}>
|
||||||
</Typography>
|
{item.bezeichnung}
|
||||||
</td>
|
</Typography>
|
||||||
</tr>
|
{item.artikel_bezeichnung && (
|
||||||
))
|
<Typography variant="caption" color="text.secondary">
|
||||||
)}
|
{item.artikel_bezeichnung}
|
||||||
</tbody>
|
</Typography>
|
||||||
</Box>
|
)}
|
||||||
</Box>
|
{item.eigenschaften && item.eigenschaften.length > 0 && (
|
||||||
|
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', mt: 0.5 }}>
|
||||||
|
{item.eigenschaften.map((e) => (
|
||||||
|
<Chip
|
||||||
|
key={e.id}
|
||||||
|
label={`${e.name}: ${e.wert}`}
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
sx={{ height: 20, fontSize: '0.7rem' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Typography variant="body2">{item.kategorie ?? '—'}</Typography>
|
||||||
|
</td>
|
||||||
|
{canViewAll && (
|
||||||
|
<td>
|
||||||
|
<Typography variant="body2">
|
||||||
|
{item.user_display_name ?? item.benutzer_name ?? '—'}
|
||||||
|
</Typography>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
<td>
|
||||||
|
<Typography variant="body2">{item.groesse ?? '—'}</Typography>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Chip
|
||||||
|
label={ZUSTAND_LABELS[item.zustand]}
|
||||||
|
color={ZUSTAND_COLORS[item.zustand]}
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Typography variant="body2">
|
||||||
|
{item.anschaffung_datum
|
||||||
|
? new Date(item.anschaffung_datum).toLocaleDateString('de-AT')
|
||||||
|
: '—'}
|
||||||
|
</Typography>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user