Files
course-craft-service/apps/web/src/components/editor/lesson-sidebar.tsx
2026-02-06 02:17:59 +03:00

119 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { ChevronDown, ChevronRight, FileText, Plus } from 'lucide-react';
import { useState } from 'react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
interface Lesson {
id: string;
title: string;
}
interface Chapter {
id: string;
title: string;
lessons: Lesson[];
}
interface Course {
id: string;
title: string;
chapters: Chapter[];
}
interface LessonSidebarProps {
course: Course;
activeLesson: string;
onSelectLesson: (lessonId: string) => void;
/** Скрыть кнопки «Добавить урок/главу» (режим просмотра) */
readOnly?: boolean;
}
export function LessonSidebar({
course,
activeLesson,
onSelectLesson,
readOnly = false,
}: LessonSidebarProps) {
const [expandedChapters, setExpandedChapters] = useState<string[]>(
course.chapters.map((ch) => ch.id)
);
const toggleChapter = (chapterId: string) => {
setExpandedChapters((prev) =>
prev.includes(chapterId)
? prev.filter((id) => id !== chapterId)
: [...prev, chapterId]
);
};
return (
<div className="h-full flex flex-col">
{/* Header */}
<div className="p-4 border-b">
<h2 className="font-semibold truncate">{course.title}</h2>
</div>
{/* Chapters list */}
<div className="flex-1 overflow-auto p-2">
{course.chapters.map((chapter) => {
const isExpanded = expandedChapters.includes(chapter.id);
return (
<div key={chapter.id} className="mb-2">
{/* Chapter header */}
<button
className="flex items-center gap-2 w-full rounded-md px-2 py-1.5 text-sm font-medium hover:bg-muted transition-colors"
onClick={() => toggleChapter(chapter.id)}
>
{isExpanded ? (
<ChevronDown className="h-4 w-4 shrink-0" />
) : (
<ChevronRight className="h-4 w-4 shrink-0" />
)}
<span className="truncate">{chapter.title}</span>
</button>
{/* Lessons */}
{isExpanded && (
<div className="ml-4 mt-1 space-y-1">
{chapter.lessons.map((lesson) => (
<button
key={lesson.id}
className={cn(
'flex items-center gap-2 w-full rounded-md px-2 py-1.5 text-sm transition-colors text-left',
activeLesson === lesson.id
? 'bg-primary text-primary-foreground'
: 'hover:bg-muted text-muted-foreground'
)}
onClick={() => onSelectLesson(lesson.id)}
>
<FileText className="h-4 w-4 shrink-0" />
<span className="truncate">{lesson.title}</span>
</button>
))}
{!readOnly && (
<button className="flex items-center gap-2 w-full rounded-md px-2 py-1.5 text-sm text-muted-foreground hover:bg-muted transition-colors">
<Plus className="h-4 w-4 shrink-0" />
<span>Добавить урок</span>
</button>
)}
</div>
)}
</div>
);
})}
</div>
{!readOnly && (
<div className="p-2 border-t">
<Button variant="ghost" size="sm" className="w-full justify-start">
<Plus className="mr-2 h-4 w-4" />
Добавить главу
</Button>
</div>
)}
</div>
);
}