import React, { useCallback, useEffect, useMemo, useState } from 'react' import api from '../utils/api' import NavStateLink from '../components/NavStateLink' import FrameworkProgramsFilterBlock from '../components/planning/FrameworkProgramsFilterBlock' import FrameworkProgramListCard from '../components/planning/FrameworkProgramListCard' import SkillProfileFullModal from '../components/skills/SkillProfileFullModal' import { useAuth } from '../context/AuthContext' import { getTenantClubDependencyKey } from '../utils/activeClub' import { buildFrameworkProgramsListReturnContext } from '../utils/navReturnContext' import { EMPTY_FRAMEWORK_IMPORT_FILTERS, filterFrameworkPrograms, hasActiveFrameworkImportFilters, } from '../utils/frameworkProgramListHelpers' export default function TrainingFrameworkProgramsListPage() { const { user } = useAuth() const tenantClubDepKey = useMemo(() => getTenantClubDependencyKey(user), [user]) const frameworkListReturn = useMemo(() => buildFrameworkProgramsListReturnContext(), []) const [rows, setRows] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState('') const [catalogFocusAreas, setCatalogFocusAreas] = useState([]) const [catalogTrainingTypes, setCatalogTrainingTypes] = useState([]) const [catalogTargetGroups, setCatalogTargetGroups] = useState([]) const [catalogSkills, setCatalogSkills] = useState([]) const [filters, setFilters] = useState(() => ({ ...EMPTY_FRAMEWORK_IMPORT_FILTERS })) const [skillSummaries, setSkillSummaries] = useState({}) const [summariesLoading, setSummariesLoading] = useState(false) const [profileModal, setProfileModal] = useState(null) const filteredRows = useMemo( () => filterFrameworkPrograms(rows, filters, skillSummaries), [rows, filters, skillSummaries] ) const filterActive = hasActiveFrameworkImportFilters(filters) const load = useCallback(async () => { setLoading(true) setError('') try { const [list, fa, tt, tg, skills] = await Promise.all([ api.listTrainingFrameworkPrograms(), api.listFocusAreas({ status: 'active' }), api.listTrainingTypes({ status: 'active' }), api.listTargetGroups({ status: 'active' }), api.listSkillsCatalog({ status: 'active' }), ]) setRows(Array.isArray(list) ? list : []) setCatalogFocusAreas(Array.isArray(fa) ? fa : []) setCatalogTrainingTypes(Array.isArray(tt) ? tt : []) setCatalogTargetGroups(Array.isArray(tg) ? tg : []) setCatalogSkills(Array.isArray(skills) ? skills : []) } catch (e) { setError(e.message || 'Laden fehlgeschlagen') setRows([]) setCatalogFocusAreas([]) setCatalogTrainingTypes([]) setCatalogTargetGroups([]) setCatalogSkills([]) } finally { setLoading(false) } }, []) useEffect(() => { load() }, [load, tenantClubDepKey]) useEffect(() => { if (!rows.length) { setSkillSummaries({}) return undefined } let cancelled = false setSummariesLoading(true) api .batchSkillProfileSummaries({ frameworkProgramIds: rows.map((r) => r.id) }) .then((data) => { if (!cancelled) setSkillSummaries(data?.summaries || {}) }) .catch(() => { if (!cancelled) setSkillSummaries({}) }) .finally(() => { if (!cancelled) setSummariesLoading(false) }) return () => { cancelled = true } }, [rows, tenantClubDepKey]) async function handleDelete(id, title) { if (!confirm(`Rahmenprogramm „${title || id}“ wirklich löschen?`)) return try { await api.deleteTrainingFrameworkProgram(id) await load() } catch (e) { alert(e.message || 'Löschen fehlgeschlagen') } } return (
Vorlagen für Entwicklungsziele und Sessions — die Übernahme in Gruppentermine erfolgt in der Trainingsplanung.
Rahmenprogramme werden geladen…
Lege ein neues Programm an — mit Titel, mindestens einem Entwicklungsziel und optional Sessions samt Übungsablauf.
{filterActive ? 'Kein Rahmenprogramm passt zu den gewählten Filtern. Passe die Kriterien an oder setze den Filter zurück.' : 'Keine Einträge.'}