import { useState, useEffect } from 'react' import { api } from '../utils/api' import AdminPageNav from '../components/AdminPageNav' import PageSectionNav from '../components/PageSectionNav' const CATALOG_SUBTABS = [ { id: 'focus-areas', label: 'Fokusbereiche' }, { id: 'training-styles', label: 'Stilrichtungen' }, { id: 'training-types', label: 'Trainingsstil' }, { id: 'hierarchy', label: 'Hierarchie' }, { id: 'target-groups', label: 'Zielgruppen' }, { id: 'target-groups-matrix', label: 'Zuordnungen' }, { id: 'training-characters', label: 'Trainingscharakter' }, { id: 'skill-categories', label: 'Fähigkeitskategorien' }, { id: 'trainer-assignments', label: 'Trainer-Zuordnungen' }, ] export default function AdminCatalogsPage() { const [activeTab, setActiveTab] = useState('focus-areas') const [loading, setLoading] = useState(false) const [error, setError] = useState('') // Focus Areas const [focusAreas, setFocusAreas] = useState([]) const [editingFA, setEditingFA] = useState(null) const [newFA, setNewFA] = useState({ name: '', description: '', color: '#1D9E75', icon: '' }) // Style Directions (Stilrichtungen) const [trainingStyles, setTrainingStyles] = useState([]) const [editingTS, setEditingTS] = useState(null) const [newTS, setNewTS] = useState({ name: '', description: '', focus_area_id: null }) // Training Characters const [trainingCharacters, setTrainingCharacters] = useState([]) const [editingTC, setEditingTC] = useState(null) const [newTC, setNewTC] = useState({ name: '', description: '' }) // Training Types (Breitensport, Leistungssport, etc.) const [trainingTypes, setTrainingTypes] = useState([]) const [editingTT, setEditingTT] = useState(null) const [newTT, setNewTT] = useState({ name: '', abbreviation: '', description: '', focus_area_id: null }) // Skill Categories const [skillCategories, setSkillCategories] = useState([]) const [editingSC, setEditingSC] = useState(null) const [newSC, setNewSC] = useState({ name: '', description: '', parent_category_id: null }) // Target Groups (Global - unabhängig von Stilen) const [targetGroups, setTargetGroups] = useState([]) const [editingTG, setEditingTG] = useState(null) const [newTG, setNewTG] = useState({ name: '', description: '', min_age: null, max_age: null }) // Trainer Focus Areas const [trainerAssignments, setTrainerAssignments] = useState([]) const [profiles, setProfiles] = useState([]) const [newAssignment, setNewAssignment] = useState({ profile_id: '', focus_area_id: '' }) // Hierarchy (Tree-View) const [hierarchyData, setHierarchyData] = useState([]) const [expandedNodes, setExpandedNodes] = useState(new Set()) // M:N Assignment Matrix const [assignments, setAssignments] = useState([]) const [matrixLoading, setMatrixLoading] = useState(false) useEffect(() => { loadData() }, [activeTab]) async function loadData() { setLoading(true) setError('') try { if (activeTab === 'focus-areas') { const data = await api.listFocusAreas() setFocusAreas(data) } else if (activeTab === 'training-styles') { const data = await api.listStyleDirections() setTrainingStyles(data) } else if (activeTab === 'training-characters') { const data = await api.listTrainingCharacters() setTrainingCharacters(data) } else if (activeTab === 'training-types') { const data = await api.listTrainingTypes() setTrainingTypes(data) } else if (activeTab === 'skill-categories') { const data = await api.listSkillCategories() setSkillCategories(data) } else if (activeTab === 'target-groups') { const groups = await api.listTargetGroups() setTargetGroups(groups) } else if (activeTab === 'trainer-assignments') { const [assignments, profs, areas] = await Promise.all([ api.listTrainerFocusAreas(), fetch('/api/profiles').then(r => r.json()), api.listFocusAreas() ]) setTrainerAssignments(assignments) setProfiles(profs) setFocusAreas(areas) } else if (activeTab === 'hierarchy') { const data = await api.getStyleDirectionsHierarchy() setHierarchyData(data) } else if (activeTab === 'target-groups-matrix') { const [styles, groups, assigns] = await Promise.all([ api.listStyleDirections(), api.listTargetGroups(), api.listStyleDirectionTargetGroups() ]) setTrainingStyles(styles) setTargetGroups(groups) setAssignments(assigns) } } catch (e) { setError(e.message) } finally { setLoading(false) } } // Focus Areas async function createFocusArea() { try { await api.createFocusArea(newFA) setNewFA({ name: '', description: '', color: '#1D9E75', icon: '' }) loadData() } catch (e) { setError(e.message) } } async function updateFocusArea(id, data) { try { await api.updateFocusArea(id, data) setEditingFA(null) loadData() } catch (e) { setError(e.message) } } async function deleteFocusArea(id) { if (!confirm('Fokusbereich wirklich löschen?')) return try { await api.deleteFocusArea(id) loadData() } catch (e) { setError(e.message) } } // Style Directions (formerly Training Styles) async function createStyleDirection() { try { await api.createStyleDirection(newTS) setNewTS({ name: '', description: '', focus_area_id: null }) loadData() } catch (e) { setError(e.message) } } async function updateStyleDirection(id, data) { try { await api.updateStyleDirection(id, data) setEditingTS(null) loadData() } catch (e) { setError(e.message) } } async function deleteStyleDirection(id) { if (!confirm('Stilrichtung wirklich löschen?')) return try { await api.deleteStyleDirection(id) loadData() } catch (e) { setError(e.message) } } // Training Characters async function createTrainingCharacter() { try { await api.createTrainingCharacter(newTC) setNewTC({ name: '', description: '' }) loadData() } catch (e) { setError(e.message) } } async function updateTrainingCharacter(id, data) { try { await api.updateTrainingCharacter(id, data) setEditingTC(null) loadData() } catch (e) { setError(e.message) } } async function deleteTrainingCharacter(id) { if (!confirm('Trainingscharakter wirklich löschen?')) return try { await api.deleteTrainingCharacter(id) loadData() } catch (e) { setError(e.message) } } // Training Types async function createTrainingType() { try { await api.createTrainingType(newTT) setNewTT({ name: '', abbreviation: '', description: '', focus_area_id: null }) loadData() } catch (e) { setError(e.message) } } async function updateTrainingType(id, data) { try { await api.updateTrainingType(id, data) setEditingTT(null) loadData() } catch (e) { setError(e.message) } } async function deleteTrainingType(id) { if (!confirm('Trainingsstil wirklich löschen?')) return try { await api.deleteTrainingType(id) loadData() } catch (e) { setError(e.message) } } // Skill Categories async function createSkillCategory() { try { await api.createSkillCategory(newSC) setNewSC({ name: '', description: '', parent_category_id: null }) loadData() } catch (e) { setError(e.message) } } async function updateSkillCategory(id, data) { try { await api.updateSkillCategory(id, data) setEditingSC(null) loadData() } catch (e) { setError(e.message) } } async function deleteSkillCategory(id) { if (!confirm('Fähigkeitskategorie wirklich löschen?')) return try { await api.deleteSkillCategory(id) loadData() } catch (e) { setError(e.message) } } // Target Groups async function createTargetGroup() { try { await api.createTargetGroup(newTG) setNewTG({ name: '', description: '', min_age: null, max_age: null }) loadData() } catch (e) { setError(e.message) } } async function updateTargetGroup(id, data) { try { await api.updateTargetGroup(id, data) setEditingTG(null) loadData() } catch (e) { setError(e.message) } } async function deleteTargetGroup(id) { if (!confirm('Zielgruppe wirklich löschen?')) return try { await api.deleteTargetGroup(id) loadData() } catch (e) { setError(e.message) } } // Trainer Assignments async function assignTrainer() { try { await api.assignTrainerFocusArea(newAssignment) setNewAssignment({ profile_id: '', focus_area_id: '' }) loadData() } catch (e) { setError(e.message) } } async function removeAssignment(id) { if (!confirm('Zuordnung wirklich entfernen?')) return try { await api.deleteTrainerFocusArea(id) loadData() } catch (e) { setError(e.message) } } return (

Stammdaten-Kataloge

{error &&
{error}
} {loading ? (
) : ( <> {/* Focus Areas */} {activeTab === 'focus-areas' && (

Neuer Fokusbereich

setNewFA({ ...newFA, name: e.target.value })} placeholder="z.B. Karate" />