feat(ausruestung): catalog-driven item tracking, im_haus in overview, order quantity override, fix stale queries
This commit is contained in:
@@ -12,6 +12,7 @@ import { PageHeader } from '../components/templates';
|
||||
import { useNotification } from '../contexts/NotificationContext';
|
||||
import { usePermissionContext } from '../contexts/PermissionContext';
|
||||
import { ausruestungsanfrageApi } from '../services/ausruestungsanfrage';
|
||||
import { personalEquipmentApi } from '../services/personalEquipment';
|
||||
import { vehiclesApi } from '../services/vehicles';
|
||||
import { membersService } from '../services/members';
|
||||
import type { AusruestungAnfragePosition } from '../types/ausruestungsanfrage.types';
|
||||
@@ -24,8 +25,6 @@ interface PositionAssignment {
|
||||
standort?: string;
|
||||
userId?: string;
|
||||
benutzerName?: string;
|
||||
groesse?: string;
|
||||
kategorie?: string;
|
||||
}
|
||||
|
||||
function getUnassignedPositions(positions: AusruestungAnfragePosition[]): AusruestungAnfragePosition[] {
|
||||
@@ -92,6 +91,12 @@ export default function AusruestungsanfrageZuweisung() {
|
||||
name: v.bezeichnung ?? v.kurzname,
|
||||
}));
|
||||
|
||||
const { data: allPersonalItems = [] } = useQuery({
|
||||
queryKey: ['persoenliche-ausruestung', 'all-for-count'],
|
||||
queryFn: () => personalEquipmentApi.getAll(),
|
||||
staleTime: 2 * 60 * 1000,
|
||||
});
|
||||
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const updateAssignment = (posId: number, patch: Partial<PositionAssignment>) => {
|
||||
@@ -137,12 +142,12 @@ export default function AusruestungsanfrageZuweisung() {
|
||||
standort: a.typ === 'ausruestung' ? a.standort : undefined,
|
||||
userId: a.typ === 'persoenlich' ? a.userId : undefined,
|
||||
benutzerName: a.typ === 'persoenlich' ? (a.benutzerName || anfrage.fuer_benutzer_name || anfrage.anfrager_name) : undefined,
|
||||
groesse: a.typ === 'persoenlich' ? a.groesse : undefined,
|
||||
kategorie: a.typ === 'persoenlich' ? a.kategorie : undefined,
|
||||
}));
|
||||
await ausruestungsanfrageApi.assignItems(anfrageId, payload);
|
||||
showSuccess('Gegenstände zugewiesen');
|
||||
navigate(`/ausruestungsanfrage/${id}`);
|
||||
queryClient.invalidateQueries({ queryKey: ['persoenliche-ausruestung'] });
|
||||
queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage'] });
|
||||
} catch {
|
||||
showError('Fehler beim Zuweisen');
|
||||
} finally {
|
||||
@@ -233,11 +238,10 @@ export default function AusruestungsanfrageZuweisung() {
|
||||
size="small"
|
||||
onChange={(_e, val) => val && updateAssignment(pos.id, { typ: val })}
|
||||
sx={{ mb: 1.5 }}
|
||||
disabled={!pos.artikel_id}
|
||||
>
|
||||
<ToggleButton value="ausruestung">Ausrüstung</ToggleButton>
|
||||
<ToggleButton value="persoenlich">Persönlich</ToggleButton>
|
||||
<ToggleButton value="keine">Nicht erfassen</ToggleButton>
|
||||
<ToggleButton value="ausruestung" disabled={!pos.artikel_id}>Ausrüstung</ToggleButton>
|
||||
<ToggleButton value="persoenlich" disabled={!pos.artikel_id}>Persönlich</ToggleButton>
|
||||
<ToggleButton value="keine">Nicht verfolgt</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
|
||||
{a.typ === 'ausruestung' && (
|
||||
@@ -262,7 +266,7 @@ export default function AusruestungsanfrageZuweisung() {
|
||||
)}
|
||||
|
||||
{a.typ === 'persoenlich' && (
|
||||
<Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'wrap' }}>
|
||||
<Box sx={{ display: 'flex', gap: 1.5, flexWrap: 'wrap', alignItems: 'center' }}>
|
||||
<Autocomplete
|
||||
size="small"
|
||||
options={memberOptions}
|
||||
@@ -278,20 +282,19 @@ export default function AusruestungsanfrageZuweisung() {
|
||||
)}
|
||||
sx={{ minWidth: 200, flex: 1 }}
|
||||
/>
|
||||
<TextField
|
||||
size="small"
|
||||
label="Größe"
|
||||
value={a.groesse ?? ''}
|
||||
onChange={(e) => updateAssignment(pos.id, { groesse: e.target.value })}
|
||||
sx={{ minWidth: 100 }}
|
||||
/>
|
||||
<TextField
|
||||
size="small"
|
||||
label="Kategorie"
|
||||
value={a.kategorie ?? ''}
|
||||
onChange={(e) => updateAssignment(pos.id, { kategorie: e.target.value })}
|
||||
sx={{ minWidth: 140 }}
|
||||
/>
|
||||
{(() => {
|
||||
if (!a.userId || !pos.artikel_id) return null;
|
||||
const count = allPersonalItems.filter(i => i.user_id === a.userId && i.artikel_id === pos.artikel_id).length;
|
||||
if (count === 0) return null;
|
||||
return <Typography variant="caption" color="text.secondary">Hat bereits {count} Stk.</Typography>;
|
||||
})()}
|
||||
{pos.eigenschaften && pos.eigenschaften.length > 0 && (
|
||||
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', mb: 1 }}>
|
||||
{pos.eigenschaften.map(e => (
|
||||
<Chip key={e.eigenschaft_id} label={`${e.eigenschaft_name}: ${e.wert}`} size="small" variant="outlined" />
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user