import { useState, useMemo, useCallback } from 'react';
import {
Box, Typography, Paper, Button, TextField, IconButton,
Chip, MenuItem, Divider, Checkbox, FormControlLabel, LinearProgress,
} from '@mui/material';
import {
ArrowBack, Edit as EditIcon, Delete as DeleteIcon,
Add as AddIcon,
} from '@mui/icons-material';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useParams, useNavigate } from 'react-router-dom';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { useNotification } from '../contexts/NotificationContext';
import { usePermissionContext } from '../contexts/PermissionContext';
import { ausruestungsanfrageApi } from '../services/ausruestungsanfrage';
import type {
AusruestungArtikel, AusruestungArtikelFormData,
AusruestungEigenschaft, AusruestungKategorie,
} from '../types/ausruestungsanfrage.types';
// ── EigenschaftenEditor ──
function EigenschaftenEditor({ artikelId }: { artikelId: number | null }) {
const { showSuccess, showError } = useNotification();
const queryClient = useQueryClient();
const [newName, setNewName] = useState('');
const [newTyp, setNewTyp] = useState<'options' | 'freitext'>('options');
const [newOptionen, setNewOptionen] = useState('');
const [newPflicht, setNewPflicht] = useState(false);
const { data: eigenschaften = [] } = useQuery({
queryKey: ['ausruestungsanfrage', 'eigenschaften', artikelId],
queryFn: () => ausruestungsanfrageApi.getArtikelEigenschaften(artikelId!),
enabled: artikelId != null,
});
const upsertMut = useMutation({
mutationFn: (data: { eigenschaft_id?: number; name: string; typ: string; optionen?: string[]; pflicht?: boolean; sort_order?: number }) =>
ausruestungsanfrageApi.upsertArtikelEigenschaft(artikelId!, data),
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage', 'eigenschaften', artikelId] }); showSuccess('Eigenschaft gespeichert'); },
onError: () => showError('Fehler beim Speichern'),
});
const deleteMut = useMutation({
mutationFn: (id: number) => ausruestungsanfrageApi.deleteArtikelEigenschaft(id),
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage', 'eigenschaften', artikelId] }); showSuccess('Eigenschaft geloescht'); },
onError: () => showError('Fehler beim Loeschen'),
});
const handleAdd = () => {
if (!newName.trim()) return;
const optionen = newTyp === 'options' ? newOptionen.split(',').map(s => s.trim()).filter(Boolean) : undefined;
upsertMut.mutate({
name: newName.trim(),
typ: newTyp,
optionen,
pflicht: newPflicht,
sort_order: eigenschaften.length,
});
setNewName('');
setNewOptionen('');
setNewPflicht(false);
};
if (artikelId == null) return Bitte speichern Sie den Artikel zuerst, bevor Sie Eigenschaften hinzufuegen.;
return (
Eigenschaften
{eigenschaften.map(e => (
{e.name} ({e.typ === 'options' ? `Auswahl: ${e.optionen?.join(', ')}` : 'Freitext'})
{e.pflicht && }
deleteMut.mutate(e.id)}>
))}
setNewName(e.target.value)} sx={{ flexGrow: 1 }} />
setNewTyp(e.target.value as 'options' | 'freitext')}
sx={{ minWidth: 120 }}
>
setNewPflicht(e.target.checked)} />}
label="Pflicht"
/>
{newTyp === 'options' && (
setNewOptionen(e.target.value)}
placeholder="S, M, L, XL"
fullWidth
/>
)}
}
onClick={handleAdd}
disabled={!newName.trim() || upsertMut.isPending}
>
Eigenschaft hinzufuegen
);
}
// ══════════════════════════════════════════════════════════════════════════════
// Main Component
// ══════════════════════════════════════════════════════════════════════════════
export default function AusruestungsanfrageArtikelDetail() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const queryClient = useQueryClient();
const { showSuccess, showError } = useNotification();
const { hasPermission } = usePermissionContext();
const isCreate = !id || id === 'neu';
const artikelId = isCreate ? null : Number(id);
const canManage = hasPermission('ausruestungsanfrage:manage_catalog');
// ── State ──
const [editing, setEditing] = useState(isCreate);
const [form, setForm] = useState({ bezeichnung: '' });
const [mainKat, setMainKat] = useState('');
// ── Queries ──
const { data: artikel, isLoading, isError } = useQuery({
queryKey: ['ausruestungsanfrage', 'item', artikelId],
queryFn: () => ausruestungsanfrageApi.getItem(artikelId!),
enabled: artikelId != null,
retry: 1,
});
const { data: kategorien = [] } = useQuery({
queryKey: ['ausruestungsanfrage', 'kategorien'],
queryFn: () => ausruestungsanfrageApi.getKategorien(),
});
const { data: eigenschaften = [] } = useQuery({
queryKey: ['ausruestungsanfrage', 'eigenschaften', artikelId],
queryFn: () => ausruestungsanfrageApi.getArtikelEigenschaften(artikelId!),
enabled: artikelId != null,
});
const topKategorien = useMemo(() => kategorien.filter(k => !k.parent_id), [kategorien]);
const subKategorienOf = useCallback((parentId: number) => kategorien.filter(k => k.parent_id === parentId), [kategorien]);
const subKats = useMemo(() => mainKat ? subKategorienOf(mainKat as number) : [], [mainKat, subKategorienOf]);
const kategorieOptions = useMemo(() => {
const map = new Map(kategorien.map(k => [k.id, k]));
const getDisplayName = (k: AusruestungKategorie): string => {
if (k.parent_id) {
const parent = map.get(k.parent_id);
if (parent) return `${parent.name} > ${k.name}`;
}
return k.name;
};
return kategorien.map(k => ({ id: k.id, name: getDisplayName(k) }));
}, [kategorien]);
// ── Mutations ──
const createMut = useMutation({
mutationFn: (data: AusruestungArtikelFormData) => ausruestungsanfrageApi.createItem(data),
onSuccess: (newItem) => {
queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage'] });
showSuccess('Artikel erstellt');
navigate(`/ausruestungsanfrage/artikel/${newItem.id}`, { replace: true });
},
onError: () => showError('Fehler beim Erstellen'),
});
const updateMut = useMutation({
mutationFn: ({ itemId, data }: { itemId: number; data: Partial }) =>
ausruestungsanfrageApi.updateItem(itemId, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage'] });
showSuccess('Artikel aktualisiert');
setEditing(false);
},
onError: () => showError('Fehler beim Aktualisieren'),
});
const deleteMut = useMutation({
mutationFn: (itemId: number) => ausruestungsanfrageApi.deleteItem(itemId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage'] });
showSuccess('Artikel geloescht');
navigate('/ausruestungsanfrage?tab=2');
},
onError: () => showError('Fehler beim Loeschen'),
});
// ── Edit helpers ──
const startEditing = () => {
if (!artikel) return;
setForm({
bezeichnung: artikel.bezeichnung,
beschreibung: artikel.beschreibung,
kategorie_id: artikel.kategorie_id ?? null,
});
const kat = kategorien.find(k => k.id === artikel.kategorie_id);
if (kat?.parent_id) {
setMainKat(kat.parent_id);
} else {
setMainKat(artikel.kategorie_id || '');
}
setEditing(true);
};
const handleSave = () => {
if (!form.bezeichnung.trim()) return;
if (isCreate) {
createMut.mutate(form);
} else if (artikelId) {
updateMut.mutate({ itemId: artikelId, data: form });
}
};
const handleCancel = () => {
if (isCreate) {
navigate('/ausruestungsanfrage?tab=2');
} else {
setEditing(false);
}
};
const getKategorieName = (katId?: number) => {
if (!katId) return '-';
return kategorieOptions.find(k => k.id === katId)?.name || '-';
};
return (
{/* Header */}
navigate('/ausruestungsanfrage?tab=2')}>
{isCreate ? 'Neuer Katalogartikel' : (artikel?.bezeichnung ?? '...')}
{!isCreate && canManage && !editing && (
<>
{ if (artikelId) deleteMut.mutate(artikelId); }}>
>
)}
{!isCreate && isLoading ? (
) : !isCreate && isError ? (
Fehler beim Laden des Artikels.
) : editing ? (
/* ── Edit / Create Mode ── */
setForm(f => ({ ...f, bezeichnung: e.target.value }))}
fullWidth
autoFocus
/>
setForm(f => ({ ...f, beschreibung: e.target.value }))}
fullWidth
/>
{
const val = e.target.value ? Number(e.target.value) : '';
setMainKat(val);
if (val) {
const subs = subKategorienOf(val as number);
setForm(f => ({ ...f, kategorie_id: subs.length === 0 ? (val as number) : null }));
} else {
setForm(f => ({ ...f, kategorie_id: null }));
}
}}
fullWidth
>
{topKategorien.map(k => )}
{mainKat && subKats.length > 0 && (
setForm(f => ({ ...f, kategorie_id: e.target.value ? Number(e.target.value) : (mainKat as number) }))}
fullWidth
>
{subKats.map(k => )}
)}
{canManage && }
) : artikel ? (
/* ── View Mode ── */
<>
Bezeichnung
{artikel.bezeichnung}
Kategorie
{getKategorieName(artikel.kategorie_id)}
{artikel.beschreibung && (
Beschreibung
{artikel.beschreibung}
)}
Status
Erstellt am
{new Date(artikel.erstellt_am).toLocaleDateString('de-AT')}
{eigenschaften.length > 0 && (
Eigenschaften ({eigenschaften.length})
{eigenschaften.map(e => (
{e.name} ({e.typ === 'options' ? `Auswahl: ${e.optionen?.join(', ')}` : 'Freitext'})
{e.pflicht && }
))}
)}
>
) : null}
);
}