feat(ausruestung): catalog-driven item tracking, im_haus in overview, order quantity override, fix stale queries
This commit is contained in:
@@ -34,13 +34,12 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
|
||||
const canViewAll = hasPermission('persoenliche_ausruestung:view_all');
|
||||
|
||||
const [formBezeichnung, setFormBezeichnung] = useState<string | AusruestungArtikel | null>(null);
|
||||
const [formKategorie, setFormKategorie] = useState('');
|
||||
const [formArtikel, setFormArtikel] = useState<AusruestungArtikel | null>(null);
|
||||
const [formUserId, setFormUserId] = useState<{ id: string; name: string } | null>(null);
|
||||
const [formBenutzerName, setFormBenutzerName] = useState('');
|
||||
const [formGroesse, setFormGroesse] = useState('');
|
||||
const [formZustand, setFormZustand] = useState<PersoenlicheAusruestungZustand>('gut');
|
||||
const [formNotizen, setFormNotizen] = useState('');
|
||||
const [eigenschaftValues, setEigenschaftValues] = useState<Record<number, string>>({});
|
||||
|
||||
const { data: catalogItems } = useQuery({
|
||||
queryKey: ['ausruestungsanfrage-items-catalog'],
|
||||
@@ -48,6 +47,13 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
staleTime: 10 * 60 * 1000,
|
||||
});
|
||||
|
||||
const { data: artikelEigenschaften = [] } = useQuery({
|
||||
queryKey: ['ausruestungsanfrage', 'eigenschaften', formArtikel?.id],
|
||||
queryFn: () => ausruestungsanfrageApi.getArtikelEigenschaften(formArtikel!.id),
|
||||
enabled: !!formArtikel?.id,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
|
||||
const { data: membersList } = useQuery({
|
||||
queryKey: ['members-list-compact'],
|
||||
queryFn: () => membersService.getMembers({ pageSize: 500 }),
|
||||
@@ -75,20 +81,23 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
});
|
||||
|
||||
const handleCreate = () => {
|
||||
const bezeichnung = typeof formBezeichnung === 'string'
|
||||
? formBezeichnung
|
||||
: formBezeichnung?.bezeichnung ?? '';
|
||||
const bezeichnung = formArtikel?.bezeichnung ?? '';
|
||||
if (!bezeichnung.trim()) return;
|
||||
|
||||
const payload: CreatePersoenlicheAusruestungPayload = {
|
||||
bezeichnung: bezeichnung.trim(),
|
||||
kategorie: formKategorie || undefined,
|
||||
artikel_id: typeof formBezeichnung === 'object' && formBezeichnung ? formBezeichnung.id : undefined,
|
||||
artikel_id: formArtikel?.id,
|
||||
user_id: formUserId?.id || undefined,
|
||||
benutzer_name: formBenutzerName || undefined,
|
||||
groesse: formGroesse || undefined,
|
||||
zustand: formZustand,
|
||||
notizen: formNotizen || undefined,
|
||||
eigenschaften: Object.entries(eigenschaftValues)
|
||||
.filter(([, v]) => v.trim())
|
||||
.map(([id, wert]) => ({
|
||||
eigenschaft_id: Number(id),
|
||||
name: artikelEigenschaften.find(e => e.id === Number(id))?.name ?? '',
|
||||
wert,
|
||||
})),
|
||||
};
|
||||
createMutation.mutate(payload);
|
||||
};
|
||||
@@ -103,20 +112,12 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
|
||||
<Stack spacing={2}>
|
||||
<Autocomplete
|
||||
freeSolo
|
||||
options={catalogItems ?? []}
|
||||
getOptionLabel={(o) => typeof o === 'string' ? o : o.bezeichnung}
|
||||
value={formBezeichnung}
|
||||
getOptionLabel={(o) => o.bezeichnung}
|
||||
value={formArtikel}
|
||||
onChange={(_e, v) => {
|
||||
setFormBezeichnung(v);
|
||||
if (v && typeof v !== 'string' && v.kategorie) {
|
||||
setFormKategorie(v.kategorie);
|
||||
}
|
||||
}}
|
||||
onInputChange={(_e, v) => {
|
||||
if (typeof formBezeichnung === 'string' || formBezeichnung === null) {
|
||||
setFormBezeichnung(v);
|
||||
}
|
||||
setFormArtikel(v);
|
||||
setEigenschaftValues({});
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField {...params} label="Bezeichnung" required size="small" />
|
||||
@@ -124,6 +125,23 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
size="small"
|
||||
/>
|
||||
|
||||
{artikelEigenschaften.map(e =>
|
||||
e.typ === 'options' && e.optionen?.length ? (
|
||||
<TextField key={e.id} select size="small" label={e.name} required={e.pflicht}
|
||||
value={eigenschaftValues[e.id] ?? ''}
|
||||
onChange={ev => setEigenschaftValues(prev => ({ ...prev, [e.id]: ev.target.value }))}
|
||||
>
|
||||
<MenuItem value="">—</MenuItem>
|
||||
{e.optionen.map(opt => <MenuItem key={opt} value={opt}>{opt}</MenuItem>)}
|
||||
</TextField>
|
||||
) : (
|
||||
<TextField key={e.id} size="small" label={e.name} required={e.pflicht}
|
||||
value={eigenschaftValues[e.id] ?? ''}
|
||||
onChange={ev => setEigenschaftValues(prev => ({ ...prev, [e.id]: ev.target.value }))}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
||||
{canViewAll && (
|
||||
<Autocomplete
|
||||
options={memberOptions}
|
||||
@@ -146,20 +164,6 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
label="Kategorie"
|
||||
size="small"
|
||||
value={formKategorie}
|
||||
onChange={(e) => setFormKategorie(e.target.value)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
label="Größe"
|
||||
size="small"
|
||||
value={formGroesse}
|
||||
onChange={(e) => setFormGroesse(e.target.value)}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
label="Zustand"
|
||||
select
|
||||
@@ -188,7 +192,7 @@ export default function PersoenlicheAusruestungNeu() {
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleCreate}
|
||||
disabled={createMutation.isPending || !(typeof formBezeichnung === 'string' ? formBezeichnung.trim() : formBezeichnung?.bezeichnung?.trim())}
|
||||
disabled={createMutation.isPending || !formArtikel}
|
||||
>
|
||||
Erstellen
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user