'use client' import React, { useState, useEffect, useMemo } from 'react' import { useParams, useRouter } from 'next/navigation' import Link from 'next/link' import { Course, Lesson, Enrollment, QuizQuestion, COURSE_CATEGORY_INFO, ENROLLMENT_STATUS_INFO, isEnrollmentOverdue, getDaysUntilDeadline } from '@/lib/sdk/academy/types' import { fetchCourse, fetchEnrollments, deleteCourse, submitQuiz, updateLesson, generateVideos, getVideoStatus } from '@/lib/sdk/academy/api' type TabId = 'overview' | 'lessons' | 'enrollments' | 'videos' export default function CourseDetailPage() { const params = useParams() const router = useRouter() const courseId = params.id as string const [course, setCourse] = useState(null) const [enrollments, setEnrollments] = useState([]) const [activeTab, setActiveTab] = useState('overview') const [isLoading, setIsLoading] = useState(true) const [selectedLesson, setSelectedLesson] = useState(null) const [quizAnswers, setQuizAnswers] = useState>({}) const [quizResult, setQuizResult] = useState(null) const [isSubmittingQuiz, setIsSubmittingQuiz] = useState(false) const [videoStatus, setVideoStatus] = useState(null) const [isGeneratingVideos, setIsGeneratingVideos] = useState(false) const [isEditing, setIsEditing] = useState(false) const [editContent, setEditContent] = useState('') const [editTitle, setEditTitle] = useState('') const [isSaving, setIsSaving] = useState(false) const [saveMessage, setSaveMessage] = useState<{ type: 'success' | 'error', text: string } | null>(null) useEffect(() => { const loadData = async () => { setIsLoading(true) try { const [courseData, enrollmentData] = await Promise.all([ fetchCourse(courseId).catch(() => null), fetchEnrollments(courseId).catch(() => []) ]) setCourse(courseData) setEnrollments(Array.isArray(enrollmentData) ? enrollmentData : []) if (courseData && courseData.lessons && courseData.lessons.length > 0) { setSelectedLesson(courseData.lessons[0]) } } catch (error) { console.error('Failed to load course:', error) } finally { setIsLoading(false) } } loadData() }, [courseId]) const handleDeleteCourse = async () => { if (!confirm('Sind Sie sicher, dass Sie diesen Kurs loeschen moechten? Diese Aktion kann nicht rueckgaengig gemacht werden.')) return try { await deleteCourse(courseId) router.push('/sdk/academy') } catch (error) { console.error('Failed to delete course:', error) } } const handleSubmitQuiz = async () => { if (!selectedLesson) return const questions = selectedLesson.quizQuestions || [] const answers = questions.map((q: QuizQuestion) => quizAnswers[q.id] ?? -1) setIsSubmittingQuiz(true) try { const result = await submitQuiz(selectedLesson.id, { answers }) setQuizResult(result) } catch (error: any) { console.error('Quiz submission failed:', error) setQuizResult({ error: error.message || 'Fehler bei der Auswertung' }) } finally { setIsSubmittingQuiz(false) } } const handleStartEdit = () => { if (!selectedLesson) return setEditContent(selectedLesson.contentMarkdown || '') setEditTitle(selectedLesson.title || '') setIsEditing(true) setSaveMessage(null) } const handleCancelEdit = () => { setIsEditing(false) setSaveMessage(null) } const handleSaveLesson = async () => { if (!selectedLesson) return setIsSaving(true) setSaveMessage(null) try { await updateLesson(selectedLesson.id, { title: editTitle, content_url: editContent, }) const updatedLesson = { ...selectedLesson, title: editTitle, contentMarkdown: editContent } setSelectedLesson(updatedLesson) if (course) { const updatedLessons = course.lessons.map(l => l.id === updatedLesson.id ? updatedLesson : l) setCourse({ ...course, lessons: updatedLessons }) } setIsEditing(false) setSaveMessage({ type: 'success', text: 'Lektion gespeichert.' }) } catch (error: any) { setSaveMessage({ type: 'error', text: error.message || 'Fehler beim Speichern.' }) } finally { setIsSaving(false) } } const handleApproveLesson = async () => { if (!selectedLesson) return if (!confirm('Lektion fuer Video-Verarbeitung freigeben? Der Text wird als final markiert.')) return setIsSaving(true) setSaveMessage(null) try { await updateLesson(selectedLesson.id, { description: 'approved_for_video', }) const updatedLesson = { ...selectedLesson } if (course) { const updatedLessons = course.lessons.map(l => l.id === updatedLesson.id ? updatedLesson : l) setCourse({ ...course, lessons: updatedLessons }) } setSaveMessage({ type: 'success', text: 'Lektion fuer Video-Verarbeitung freigegeben.' }) } catch (error: any) { setSaveMessage({ type: 'error', text: error.message || 'Fehler bei der Freigabe.' }) } finally { setIsSaving(false) } } const handleGenerateVideos = async () => { setIsGeneratingVideos(true) try { const status = await generateVideos(courseId) setVideoStatus(status) } catch (error) { console.error('Video generation failed:', error) } finally { setIsGeneratingVideos(false) } } const handleCheckVideoStatus = async () => { try { const status = await getVideoStatus(courseId) setVideoStatus(status) } catch (error) { console.error('Failed to check video status:', error) } } if (isLoading) { return (
) } if (!course) { return (

Kurs nicht gefunden

Zurueck zur Uebersicht
) } const categoryInfo = COURSE_CATEGORY_INFO[course.category] || COURSE_CATEGORY_INFO['custom'] const sortedLessons = [...(course.lessons || [])].sort((a, b) => a.order - b.order) const completedEnrollments = enrollments.filter(e => e.status === 'completed').length const overdueEnrollments = enrollments.filter(e => isEnrollmentOverdue(e)).length return (
{/* Header */}
{categoryInfo.label} {course.status === 'published' ? 'Veroeffentlicht' : 'Entwurf'}

{course.title}

{course.description}

{/* Stats Row */}
Lektionen
{sortedLessons.length}
Dauer
{course.durationMinutes} Min.
Teilnehmer
{enrollments.length}
Abgeschlossen
{completedEnrollments}
{/* Tabs */}
{/* Overview Tab */} {activeTab === 'overview' && (

Kurs-Details

Bestehensgrenze
{course.passingScore}%
Pflicht fuer
{course.requiredForRoles?.join(', ') || 'Alle'}
Erstellt am
{new Date(course.createdAt).toLocaleDateString('de-DE')}
Aktualisiert am
{new Date(course.updatedAt).toLocaleDateString('de-DE')}
{/* Lesson List Preview */}

Lektionen ({sortedLessons.length})

{sortedLessons.map((lesson, i) => (
{i + 1}
{lesson.title}
{lesson.durationMinutes} Min. | {lesson.type === 'video' ? 'Video' : lesson.type === 'quiz' ? 'Quiz' : 'Text'}
{lesson.type === 'quiz' ? 'Quiz' : lesson.type === 'video' ? 'Video' : 'Text'}
))}
)} {/* Lessons Tab - with content viewer and quiz player */} {activeTab === 'lessons' && (
{/* Lesson Navigation */}

Lektionen

{sortedLessons.map((lesson, i) => ( ))}
{/* Lesson Content */}
{selectedLesson ? (
{isEditing ? ( setEditTitle(e.target.value)} className="text-xl font-semibold text-gray-900 border border-gray-300 rounded-lg px-3 py-1 flex-1 mr-3" /> ) : (

{selectedLesson.title}

)}
{selectedLesson.type === 'quiz' ? 'Quiz' : selectedLesson.type === 'video' ? 'Video' : 'Text'} {selectedLesson.type !== 'quiz' && !isEditing && ( <> )} {isEditing && ( <> )}
{/* Save/Approve Message */} {saveMessage && (
{saveMessage.text}
)} {/* Video Player */} {selectedLesson.type === 'video' && selectedLesson.videoUrl && (
)} {/* Text Content - Edit Mode */} {isEditing && (selectedLesson.type === 'text' || selectedLesson.type === 'video') && (