import React, { useState, useEffect, useCallback } from 'react';
import { API, APIHandler, Validators } from './api.js';
const CategoryManager = () => {
const [categories, setCategories] = useState([]);
const [newCategoryName, setNewCategoryName] = useState('');
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchCategories();
}, []);
const fetchCategories = async () => {
try {
const response = await fetch('/backend/categories');
const data = await response.json();
setCategories(data);
} catch (error) {
console.error('Fehler beim Laden der Kategorien:', error);
} finally {
setLoading(false);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('/create_category', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `name=${encodeURIComponent(newCategoryName)}`
});
if (!response.ok) throw new Error('Fehler beim Erstellen');
await fetchCategories();
setNewCategoryName('');
} catch (error) {
console.error('Fehler:', error);
}
};
const handleDelete = async (id) => {
if (!confirm('Kategorie wirklich löschen?')) return;
try {
const response = await fetch(`/delete_category/${id}`, {
method: 'DELETE'
});
if (!response.ok) throw new Error('Fehler beim Löschen');
await fetchCategories();
} catch (error) {
console.error('Fehler:', error);
}
};
if (loading) return
Lade...
;
return (
Name |
Bilder |
Aktionen |
{categories.map(category => (
{category.name} |
{category.imageCount} |
|
))}
);
};
export default CategoryManager;
### END: category-manager.txt
### START: category-manager-updated.txt
import React, { useState, useEffect, useCallback } from 'react';
import { API, APIHandler, Validators } from '@/api';
const CategoryManager = () => {
const [categories, setCategories] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [selectedCategories, setSelectedCategories] = useState(new Set());
const [editingCategory, setEditingCategory] = useState(null);
const [searchTerm, setSearchTerm] = useState('');
const [sortConfig, setSortConfig] = useState({ key: 'name', direction: 'asc' });
// Daten laden
const fetchCategories = useCallback(async () => {
try {
setLoading(true);
const data = await APIHandler.get(API.categories.list);
setCategories(data);
setError(null);
} catch (err) {
setError('Fehler beim Laden der Kategorien: ' + err.message);
console.error('Fetch error:', err);
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
fetchCategories();
}, [fetchCategories]);
// Sortierung
const sortedCategories = React.useMemo(() => {
const sorted = [...categories];
sorted.sort((a, b) => {
if (sortConfig.key === 'imageCount') {
return sortConfig.direction === 'asc'
? a.imageCount - b.imageCount
: b.imageCount - a.imageCount;
}
return sortConfig.direction === 'asc'
? a[sortConfig.key].localeCompare(b[sortConfig.key])
: b[sortConfig.key].localeCompare(a[sortConfig.key]);
});
return sorted;
}, [categories, sortConfig]);
// Kategorie erstellen
const handleCreate = async (name) => {
try {
//const validationErrors = Validators.category({ name });
//if (Object.keys(validationErrors).length > 0) {
// throw new Error(Object.values(validationErrors).join(', '));
//}
await APIHandler.post(API.categories.create, { name });
await fetchCategories();
window.showToast('Erfolg', 'Kategorie wurde erstellt', 'success');
} catch (err) {
window.showToast('Fehler', err.message, 'danger');
}
};
// Kategorie löschen
const handleDelete = async (id) => {
if (!window.confirm('Möchten Sie diese Kategorie wirklich löschen?')) return;
try {
await APIHandler.delete(API.categories.delete(id));
await fetchCategories();
window.showToast('Erfolg', 'Kategorie wurde gelöscht', 'success');
} catch (err) {
window.showToast('Fehler', err.message, 'danger');
}
};
// Kategorie aktualisieren
const handleUpdate = async (id, updates) => {
try {
//const validationErrors = Validators.category(updates);
//if (Object.keys(validationErrors).length > 0) {
// throw new Error(Object.values(validationErrors).join(', '));
//}
await APIHandler.put(API.categories.update(id), updates);
await fetchCategories();
setEditingCategory(null);
window.showToast('Erfolg', 'Kategorie wurde aktualisiert', 'success');
} catch (err) {
window.showToast('Fehler', err.message, 'danger');
}
};
// Massenbearbeitung
const handleBulkDelete = async () => {
if (selectedCategories.size === 0) return;
if (!window.confirm(`Möchten Sie ${selectedCategories.size} Kategorien wirklich löschen?`)) return;
try {
await Promise.all(
Array.from(selectedCategories).map(id =>
APIHandler.delete(API.categories.delete(id))
)
);
setSelectedCategories(new Set());
await fetchCategories();
window.showToast('Erfolg', 'Ausgewählte Kategorien wurden gelöscht', 'success');
} catch (err) {
window.showToast('Fehler', err.message, 'danger');
}
};
// Massenbearbeitung - Kategorien zusammenführen
const handleMergeCategories = async (targetId) => {
const selectedIds = Array.from(selectedCategories);
if (selectedIds.length < 2) return;
try {
await APIHandler.post(API.categories.merge, {
targetId,
sourceIds: selectedIds.filter(id => id !== targetId)
});
setSelectedCategories(new Set());
await fetchCategories();
window.showToast('Erfolg', 'Kategorien wurden zusammengeführt', 'success');
} catch (err) {
window.showToast('Fehler', err.message, 'danger');
}
};
const handleSelectAll = (event) => {
if (event.target.checked) {
setSelectedCategories(new Set(categories.map(cat => cat.id)));
} else {
setSelectedCategories(new Set());
}
};
const handleSort = (key) => {
setSortConfig(current => ({
key,
direction: current.key === key && current.direction === 'asc' ? 'desc' : 'asc'
}));
};
if (loading) {
return (
);
}
if (error) {
return (
Fehler
{error}
);
}
// Filtern basierend auf Suchbegriff
const filteredCategories = searchTerm
? sortedCategories.filter(cat =>
cat.name.toLowerCase().includes(searchTerm.toLowerCase())
)
: sortedCategories;
return (
{/* Toolbar */}
{selectedCategories.size > 0 && (
{selectedCategories.size > 1 && (
)}
)}
setSearchTerm(e.target.value)}
/>
{/* Kategorie Liste */}
{filteredCategories.length === 0 && (
{searchTerm
? 'Keine Kategorien gefunden'
: 'Keine Kategorien vorhanden'}
)}
);
};
export default CategoryManager;
window.CategoryManager = CategoryManager; // <-- Diese Zeile ans Ende setzen