import { useState, useMemo } from 'react'; import { Box, Typography, Container, Button, Chip, TextField, Autocomplete, ToggleButton, ToggleButtonGroup, Stack, Divider, LinearProgress, } from '@mui/material'; import { Assignment as AssignmentIcon } from '@mui/icons-material'; import { useQuery } from '@tanstack/react-query'; import { useParams, useNavigate } from 'react-router-dom'; import DashboardLayout from '../components/dashboard/DashboardLayout'; import { PageHeader } from '../components/templates'; import { useNotification } from '../contexts/NotificationContext'; import { ausruestungsanfrageApi } from '../services/ausruestungsanfrage'; import { vehiclesApi } from '../services/vehicles'; import { membersService } from '../services/members'; import type { AusruestungAnfragePosition } from '../types/ausruestungsanfrage.types'; type AssignmentTyp = 'ausruestung' | 'persoenlich' | 'keine'; interface PositionAssignment { typ: AssignmentTyp; fahrzeugId?: string; standort?: string; userId?: string; benutzerName?: string; groesse?: string; kategorie?: string; } function getUnassignedPositions(positions: AusruestungAnfragePosition[]): AusruestungAnfragePosition[] { return positions.filter((p) => p.geliefert && !p.zuweisung_typ); } export default function AusruestungsanfrageZuweisung() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { showSuccess, showError } = useNotification(); const anfrageId = Number(id); const { data: detail, isLoading, isError } = useQuery({ queryKey: ['ausruestungsanfrage', 'request', anfrageId], queryFn: () => ausruestungsanfrageApi.getRequest(anfrageId), enabled: !isNaN(anfrageId), retry: 1, }); const unassigned = useMemo(() => { if (!detail) return []; return getUnassignedPositions(detail.positionen); }, [detail]); const [assignments, setAssignments] = useState>({}); // Initialize assignments when unassigned positions load useMemo(() => { if (unassigned.length > 0 && Object.keys(assignments).length === 0) { const init: Record = {}; for (const p of unassigned) { init[p.id] = { typ: 'persoenlich' }; } setAssignments(init); } }, [unassigned]); const { data: vehicleList } = useQuery({ queryKey: ['vehicles', 'sidebar'], queryFn: () => vehiclesApi.getAll(), staleTime: 2 * 60 * 1000, }); const { data: membersList } = useQuery({ queryKey: ['members-list-compact'], queryFn: () => membersService.getMembers({ pageSize: 500 }), staleTime: 5 * 60 * 1000, }); const memberOptions = (membersList?.items ?? []).map((m) => ({ id: m.id, name: [m.given_name, m.family_name].filter(Boolean).join(' ') || m.email, })); const vehicleOptions = (vehicleList ?? []).map((v) => ({ id: v.id, name: v.bezeichnung ?? v.kurzname, })); const [submitting, setSubmitting] = useState(false); const updateAssignment = (posId: number, patch: Partial) => { setAssignments((prev) => ({ ...prev, [posId]: { ...prev[posId], ...patch }, })); }; const handleSkipAll = () => { const updated: Record = {}; for (const p of unassigned) { updated[p.id] = { typ: 'keine' }; } setAssignments(updated); }; const handleSubmit = async () => { if (!detail) return; setSubmitting(true); try { const anfrage = detail.anfrage; const payload = Object.entries(assignments).map(([posId, a]) => ({ positionId: Number(posId), typ: a.typ, fahrzeugId: a.typ === 'ausruestung' ? a.fahrzeugId : undefined, 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}`); } catch { showError('Fehler beim Zuweisen'); } finally { setSubmitting(false); } }; const backPath = `/ausruestungsanfrage/${id}`; return ( {isLoading ? ( ) : isError || !detail ? ( Fehler beim Laden der Anfrage. ) : unassigned.length === 0 ? ( Keine unzugewiesenen Positionen vorhanden. ) : ( <> Wähle für jeden gelieferten Gegenstand, wie er erfasst werden soll. }> {unassigned.map((pos) => { const a = assignments[pos.id] ?? { typ: 'persoenlich' as const }; return ( {pos.bezeichnung} val && updateAssignment(pos.id, { typ: val })} sx={{ mb: 1.5 }} > Ausrüstung Persönlich Nicht erfassen {a.typ === 'ausruestung' && ( o.name} value={vehicleOptions.find((v) => v.id === a.fahrzeugId) ?? null} onChange={(_e, v) => updateAssignment(pos.id, { fahrzeugId: v?.id })} renderInput={(params) => } sx={{ minWidth: 200, flex: 1 }} /> updateAssignment(pos.id, { standort: e.target.value })} sx={{ minWidth: 160, flex: 1 }} /> )} {a.typ === 'persoenlich' && ( o.name} value={memberOptions.find((m) => m.id === a.userId) ?? null} onChange={(_e, v) => updateAssignment(pos.id, { userId: v?.id, benutzerName: v?.name })} renderInput={(params) => ( )} sx={{ minWidth: 200, flex: 1 }} /> updateAssignment(pos.id, { groesse: e.target.value })} sx={{ minWidth: 100 }} /> updateAssignment(pos.id, { kategorie: e.target.value })} sx={{ minWidth: 140 }} /> )} ); })} )} ); }