/** * CommCoach Modules View * * CRUD list of all TrainingModules, filterable by status/type. * Each module row expands to show its sessions. * Edit dialog includes persona multi-select for module-persona mapping. */ import React, { useState, useEffect, useCallback } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { useCurrentInstance } from '../../../hooks/useCurrentInstance'; import * as commcoachApi from '../../../api/commcoachApi'; import type { CoachingPersona } from '../../../api/commcoachApi'; import { useLanguage } from '../../../providers/language/LanguageContext'; import styles from './Commcoach.module.css'; const MODULE_TYPE_LABELS: Record = { coaching: 'Coaching', training: 'Training', exam: 'Prüfung', elearning: 'E-Learning', }; const STATUS_LABELS: Record = { active: 'Aktiv', paused: 'Pausiert', archived: 'Archiviert', completed: 'Abgeschlossen', }; export const CommcoachModulesView: React.FC = () => { const { t } = useLanguage(); const { instance, mandateId } = useCurrentInstance(); const instanceId = instance?.id || ''; const navigate = useNavigate(); const [searchParams] = useSearchParams(); const highlightModuleId = searchParams.get('moduleId'); const [modules, setModules] = useState([]); const [loading, setLoading] = useState(true); const [expandedId, setExpandedId] = useState(highlightModuleId); const [sessions, setSessions] = useState>({}); const [editingModule, setEditingModule] = useState(null); const [deleteConfirm, setDeleteConfirm] = useState(null); const [filterType, setFilterType] = useState(''); const [filterStatus, setFilterStatus] = useState(''); const [allPersonas, setAllPersonas] = useState([]); const [editPersonaIds, setEditPersonaIds] = useState([]); const [personasLoaded, setPersonasLoaded] = useState(false); const _loadModules = useCallback(async () => { if (!instanceId) return; setLoading(true); try { const apiRequest = commcoachApi.getApiRequest(); const result = await commcoachApi.listModulesApi(apiRequest, instanceId); setModules(result || []); } catch (err) { console.error('Failed to load modules:', err); } finally { setLoading(false); } }, [instanceId]); useEffect(() => { _loadModules(); }, [_loadModules]); useEffect(() => { if (!instanceId || personasLoaded) return; const _loadAllPersonas = async () => { try { const apiRequest = commcoachApi.getApiRequest(); const personas = await commcoachApi.getPersonasApi(apiRequest, instanceId); setAllPersonas(personas); setPersonasLoaded(true); } catch {} }; _loadAllPersonas(); }, [instanceId, personasLoaded]); const _loadSessions = useCallback(async (moduleId: string) => { if (!instanceId) return; try { const apiRequest = commcoachApi.getApiRequest(); const result = await commcoachApi.listSessionsApi(apiRequest, instanceId, moduleId); setSessions(prev => ({ ...prev, [moduleId]: result || [] })); } catch (err) { console.error('Failed to load sessions:', err); } }, [instanceId]); const _toggleExpand = (moduleId: string) => { if (expandedId === moduleId) { setExpandedId(null); } else { setExpandedId(moduleId); if (!sessions[moduleId]) _loadSessions(moduleId); } }; const _handleDelete = async (moduleId: string) => { try { const apiRequest = commcoachApi.getApiRequest(); await commcoachApi.deleteModuleApi(apiRequest, instanceId, moduleId); setDeleteConfirm(null); _loadModules(); } catch (err) { console.error('Delete failed:', err); } }; const _handleEdit = async (moduleId: string, updates: any) => { try { const apiRequest = commcoachApi.getApiRequest(); await commcoachApi.updateModuleApi(apiRequest, instanceId, moduleId, updates); await commcoachApi.setModulePersonasApi(apiRequest, instanceId, moduleId, editPersonaIds); setEditingModule(null); _loadModules(); } catch (err) { console.error('Update failed:', err); } }; const _openEditDialog = async (mod: any) => { setEditingModule(mod); try { const apiRequest = commcoachApi.getApiRequest(); const ids = await commcoachApi.getModulePersonasApi(apiRequest, instanceId, mod.id); setEditPersonaIds(ids); } catch { setEditPersonaIds([]); } }; const _togglePersonaId = (personaId: string) => { setEditPersonaIds(prev => prev.includes(personaId) ? prev.filter(id => id !== personaId) : [...prev, personaId] ); }; const filteredModules = modules.filter(m => { if (filterType && m.moduleType !== filterType) return false; if (filterStatus && m.status !== filterStatus) return false; return true; }); return (

{t('Module')}

{loading &&
{t('Laden...')}
}
{filteredModules.map(mod => (
_toggleExpand(mod.id)}> {t(MODULE_TYPE_LABELS[mod.moduleType] || mod.moduleType)} {mod.title} {t(STATUS_LABELS[mod.status] || mod.status)} {mod.sessionCount || 0} {t('Sessions')}
{expandedId === mod.id && (
{(sessions[mod.id] || []).length === 0 ? (

{t('Keine Sessions vorhanden')}

) : (
{(sessions[mod.id] || []).map((sess: any) => (
{sess.summary || t('Session')} {sess.status} {sess.startedAt ? new Date(sess.startedAt * 1000).toLocaleDateString() : '-'}
))}
)}
)}
))}
{deleteConfirm && (

{t('Modul und alle zugehörigen Sessions wirklich löschen?')}

)} {editingModule && (

{t('Modul bearbeiten')}

setEditingModule({ ...editingModule, title: e.target.value })} />