rework internal order system
This commit is contained in:
@@ -286,8 +286,8 @@ async function getRequests(filters?: { status?: string; anfrager_id?: string })
|
||||
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
||||
const result = await pool.query(
|
||||
`SELECT a.*,
|
||||
u.display_name AS anfrager_name,
|
||||
u2.display_name AS bearbeitet_von_name,
|
||||
COALESCE(u.given_name || ' ' || u.family_name, u.name) AS anfrager_name,
|
||||
COALESCE(u2.given_name || ' ' || u2.family_name, u2.name) AS bearbeitet_von_name,
|
||||
(SELECT COUNT(*)::int FROM ausruestung_anfrage_positionen p WHERE p.anfrage_id = a.id) AS positionen_count
|
||||
FROM ausruestung_anfragen a
|
||||
LEFT JOIN users u ON u.id = a.anfrager_id
|
||||
@@ -314,8 +314,8 @@ async function getMyRequests(userId: string) {
|
||||
async function getRequestById(id: number) {
|
||||
const reqResult = await pool.query(
|
||||
`SELECT a.*,
|
||||
u.display_name AS anfrager_name,
|
||||
u2.display_name AS bearbeitet_von_name
|
||||
COALESCE(u.given_name || ' ' || u.family_name, u.name) AS anfrager_name,
|
||||
COALESCE(u2.given_name || ' ' || u2.family_name, u2.name) AS bearbeitet_von_name
|
||||
FROM ausruestung_anfragen a
|
||||
LEFT JOIN users u ON u.id = a.anfrager_id
|
||||
LEFT JOIN users u2 ON u2.id = a.bearbeitet_von
|
||||
|
||||
@@ -725,6 +725,10 @@ function KatalogTab() {
|
||||
queryFn: () => ausruestungsanfrageApi.getKategorien(),
|
||||
});
|
||||
|
||||
// Split categories into top-level and children
|
||||
const topKategorien = useMemo(() => kategorien.filter(k => !k.parent_id), [kategorien]);
|
||||
const subKategorienOf = useCallback((parentId: number) => kategorien.filter(k => k.parent_id === parentId), [kategorien]);
|
||||
|
||||
// Build display names for hierarchical categories (e.g. "Kleidung > A-Uniform")
|
||||
const kategorieOptions = useMemo(() => {
|
||||
const map = new Map(kategorien.map(k => [k.id, k]));
|
||||
@@ -738,6 +742,10 @@ function KatalogTab() {
|
||||
return kategorien.map(k => ({ id: k.id, name: getDisplayName(k), isChild: !!k.parent_id }));
|
||||
}, [kategorien]);
|
||||
|
||||
// For artikel dialog: track main + sub category separately
|
||||
const [artikelMainKat, setArtikelMainKat] = useState<number | ''>('');
|
||||
const artikelSubKats = useMemo(() => artikelMainKat ? subKategorienOf(artikelMainKat as number) : [], [artikelMainKat, subKategorienOf]);
|
||||
|
||||
const createItemMut = useMutation({
|
||||
mutationFn: (data: AusruestungArtikelFormData) => ausruestungsanfrageApi.createItem(data),
|
||||
onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['ausruestungsanfrage'] }); showSuccess('Artikel erstellt'); setArtikelDialogOpen(false); },
|
||||
@@ -757,11 +765,19 @@ function KatalogTab() {
|
||||
const openNewArtikel = () => {
|
||||
setEditArtikel(null);
|
||||
setArtikelForm({ bezeichnung: '' });
|
||||
setArtikelMainKat('');
|
||||
setArtikelDialogOpen(true);
|
||||
};
|
||||
const openEditArtikel = (a: AusruestungArtikel) => {
|
||||
setEditArtikel(a);
|
||||
setArtikelForm({ bezeichnung: a.bezeichnung, beschreibung: a.beschreibung, kategorie_id: a.kategorie_id ?? null });
|
||||
// Determine main category (could be the item's category or its parent)
|
||||
const kat = kategorien.find(k => k.id === a.kategorie_id);
|
||||
if (kat?.parent_id) {
|
||||
setArtikelMainKat(kat.parent_id);
|
||||
} else {
|
||||
setArtikelMainKat(a.kategorie_id || '');
|
||||
}
|
||||
setArtikelDialogOpen(true);
|
||||
};
|
||||
const saveArtikel = () => {
|
||||
@@ -846,14 +862,36 @@ function KatalogTab() {
|
||||
<TextField label="Beschreibung" multiline rows={2} value={artikelForm.beschreibung ?? ''} onChange={e => setArtikelForm(f => ({ ...f, beschreibung: e.target.value }))} />
|
||||
<TextField
|
||||
select
|
||||
label="Kategorie"
|
||||
value={artikelForm.kategorie_id ?? ''}
|
||||
onChange={e => setArtikelForm(f => ({ ...f, kategorie_id: e.target.value ? Number(e.target.value) : null }))}
|
||||
label="Hauptkategorie"
|
||||
value={artikelMainKat}
|
||||
onChange={e => {
|
||||
const val = e.target.value ? Number(e.target.value) : '';
|
||||
setArtikelMainKat(val);
|
||||
// If no subcategories, set kategorie_id to main; otherwise clear it
|
||||
if (val) {
|
||||
const subs = subKategorienOf(val as number);
|
||||
setArtikelForm(f => ({ ...f, kategorie_id: subs.length === 0 ? (val as number) : null }));
|
||||
} else {
|
||||
setArtikelForm(f => ({ ...f, kategorie_id: null }));
|
||||
}
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
<MenuItem value="">Keine</MenuItem>
|
||||
{kategorieOptions.map(k => <MenuItem key={k.id} value={k.id}>{k.name}</MenuItem>)}
|
||||
{topKategorien.map(k => <MenuItem key={k.id} value={k.id}>{k.name}</MenuItem>)}
|
||||
</TextField>
|
||||
{artikelMainKat && artikelSubKats.length > 0 && (
|
||||
<TextField
|
||||
select
|
||||
label="Unterkategorie"
|
||||
value={artikelForm.kategorie_id ?? ''}
|
||||
onChange={e => setArtikelForm(f => ({ ...f, kategorie_id: e.target.value ? Number(e.target.value) : (artikelMainKat as number) }))}
|
||||
fullWidth
|
||||
>
|
||||
<MenuItem value={artikelMainKat as number}>Keine (nur Hauptkategorie)</MenuItem>
|
||||
{artikelSubKats.map(k => <MenuItem key={k.id} value={k.id}>{k.name}</MenuItem>)}
|
||||
</TextField>
|
||||
)}
|
||||
{canManage && <EigenschaftenEditor artikelId={editArtikel?.id ?? null} />}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
|
||||
Reference in New Issue
Block a user