import { BookOpenCheck, ChevronLeft, CircleAlert, CircleOff, Loader2, Menu, Play, X, } from 'lucide-react'; import { useState } from 'react'; import { type AiCourse } from '../../lib/ai'; import { cn } from '../../lib/classname'; import { slugify } from '../../lib/slugger'; import { useIsPaidUser } from '../../queries/billing'; import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal'; import { CheckIcon } from '../ReactIcons/CheckIcon'; import { ErrorIcon } from '../ReactIcons/ErrorIcon'; import { AICourseLesson } from './AICourseLesson'; import { AICourseLimit } from './AICourseLimit'; import { AICourseSidebarModuleList } from './AICourseSidebarModuleList'; import { AILimitsPopup } from './AILimitsPopup'; import { RegenerateOutline } from './RegenerateOutline'; type AICourseContentProps = { courseSlug?: string; course: AiCourse; isLoading: boolean; error?: string; onRegenerateOutline: (prompt?: string) => void; }; export function AICourseContent(props: AICourseContentProps) { const { course, courseSlug, isLoading, error, onRegenerateOutline } = props; const [showUpgradeModal, setShowUpgradeModal] = useState(false); const [showAILimitsPopup, setShowAILimitsPopup] = useState(false); const [activeModuleIndex, setActiveModuleIndex] = useState(0); const [activeLessonIndex, setActiveLessonIndex] = useState(0); const [sidebarOpen, setSidebarOpen] = useState(false); const [viewMode, setViewMode] = useState<'module' | 'outline'>('outline'); const { isPaidUser } = useIsPaidUser(); const aiCourseProgress = course.done || []; const [expandedModules, setExpandedModules] = useState< Record >({}); const goToNextModule = () => { if (activeModuleIndex >= course.modules.length) { return; } const nextModuleIndex = activeModuleIndex + 1; setActiveModuleIndex(nextModuleIndex); setActiveLessonIndex(0); setExpandedModules((prev) => { const newState: Record = {}; course.modules.forEach((_, idx) => { newState[idx] = false; }); newState[nextModuleIndex] = true; return newState; }); }; const goToNextLesson = () => { const currentModule = course.modules[activeModuleIndex]; if (currentModule && activeLessonIndex < currentModule.lessons.length - 1) { setActiveLessonIndex(activeLessonIndex + 1); } else { goToNextModule(); } }; const goToPrevLesson = () => { if (activeLessonIndex > 0) { setActiveLessonIndex(activeLessonIndex - 1); return; } const prevModule = course.modules[activeModuleIndex - 1]; if (!prevModule) { return; } const prevModuleIndex = activeModuleIndex - 1; setActiveModuleIndex(prevModuleIndex); setActiveLessonIndex(prevModule.lessons.length - 1); // Expand the previous module in the sidebar setExpandedModules((prev) => { const newState: Record = {}; // Set all modules to collapsed course.modules.forEach((_, idx) => { newState[idx] = false; }); // Expand only the previous module newState[prevModuleIndex] = true; return newState; }); }; const currentModule = course.modules[activeModuleIndex]; const currentLesson = currentModule?.lessons[activeLessonIndex]; const totalModules = course.modules.length; const totalLessons = currentModule?.lessons.length || 0; const totalCourseLessons = course.modules.reduce( (total, module) => total + module.lessons.length, 0, ); const totalDoneLessons = (course?.done || []).length; const finishedPercentage = Math.round( (totalDoneLessons / totalCourseLessons) * 100, ); const modals = ( <> {showUpgradeModal && ( setShowUpgradeModal(false)} /> )} {showAILimitsPopup && ( setShowAILimitsPopup(false)} onUpgrade={() => { setShowAILimitsPopup(false); setShowUpgradeModal(true); }} /> )} ); if (error && !isLoading) { const isLimitReached = error.includes('limit'); const isNotFound = error.includes('not exist'); let icon = ; let title = 'Error occurred'; let message = error; if (isLimitReached) { icon = ; title = 'Limit Reached'; message = 'You have reached the daily AI usage limit. Please upgrade your account to continue.'; } else if (isNotFound) { icon = ; title = 'Course Not Found'; message = 'The course you are looking for does not exist. Why not create your own course?'; } const showUpgradeButton = isLimitReached && !isPaidUser; return ( <> {modals}
{icon}

{title}

{message}

{showUpgradeButton && (

Back to AI Tutor

)} {(isNotFound || !showUpgradeButton) && ( )}
); } const isViewingLesson = viewMode === 'module'; return (
{modals}
{ if (isViewingLesson) { e.preventDefault(); setViewMode('outline'); } }} className="flex flex-row items-center gap-1.5 text-sm font-medium text-gray-700 hover:text-gray-900" aria-label="Back to generator" > Back {isViewingLesson ? 'to Outline' : 'to AI Tutor'}
setShowUpgradeModal(true)} onShowLimits={() => setShowAILimitsPopup(true)} />

{course.title || 'Loading Course...'}

{totalModules} modules {totalCourseLessons} lessons {viewMode === 'module' && ( )} {finishedPercentage > 0 && ( <> {finishedPercentage}% complete )}
setShowUpgradeModal(true)} onShowLimits={() => setShowAILimitsPopup(true)} />
{viewMode === 'module' && ( )}
{viewMode === 'module' && ( setShowUpgradeModal(true)} /> )} {viewMode === 'outline' && (

{course.title || 'Loading course ..'}

{course.title ? course.difficulty : 'Please wait ..'}

{!isLoading && ( )}
{course.title ? (
{course.modules.map((courseModule, moduleIdx) => { return (

{courseModule.title}

{courseModule.lessons.map((lesson, lessonIdx) => { const key = `${slugify(String(moduleIdx))}-${slugify(String(lessonIdx))}`; const isCompleted = aiCourseProgress.includes(key); return (
{ setActiveModuleIndex(moduleIdx); setActiveLessonIndex(lessonIdx); setExpandedModules((prev) => { const newState: Record = {}; course.modules.forEach((_, idx) => { newState[idx] = false; }); newState[moduleIdx] = true; return newState; }); setSidebarOpen(false); setViewMode('module'); }} > {!isCompleted && ( {lessonIdx + 1} )} {isCompleted && ( )}

{lesson.replace(/^Lesson\s*?\d+[\.:]\s*/, '')}

{isCompleted ? 'View' : 'Start'} →
); })}
); })}
) : (
)}
)}
AI can make mistakes, check important info.
{sidebarOpen && (
setSidebarOpen(false)} >
)}
); }