collect-system/apps/web/src/components/models/course/detail/CourseSyllabus/CourseSyllabus.tsx

94 lines
2.5 KiB
TypeScript
Executable File

import { XMarkIcon, BookOpenIcon } from "@heroicons/react/24/outline";
import {
ChevronDownIcon,
ClockIcon,
PlayCircleIcon,
} from "@heroicons/react/24/outline";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
import React, { useState, useRef, useContext } from "react";
import { SectionDto, TaxonomySlug } from "@nice/common";
import { SyllabusHeader } from "./SyllabusHeader";
import { SectionItem } from "./SectionItem";
import { CollapsedButton } from "./CollapsedButton";
import { CourseDetailContext } from "../CourseDetailContext";
import { api } from "@nice/client";
interface CourseSyllabusProps {
sections: SectionDto[];
onLectureClick?: (lectureId: string) => void;
isOpen: boolean;
onToggle: () => void;
}
export const CourseSyllabus: React.FC<CourseSyllabusProps> = ({
sections,
onLectureClick,
isOpen,
onToggle,
}) => {
const { isHeaderVisible } = useContext(CourseDetailContext);
const [expandedSections, setExpandedSections] = useState<string[]>(
sections.map((section) => section.id) // 默认展开所有章节
);
const sectionRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
const toggleSection = (sectionId: string) => {
setExpandedSections((prev) =>
prev.includes(sectionId)
? prev.filter((id) => id !== sectionId)
: [...prev, sectionId]
);
// 直接滚动,无需延迟
sectionRefs.current[sectionId]?.scrollIntoView({
behavior: "smooth",
block: "start",
});
};
return (
<>
{/* 收起按钮直接显示 */}
{!isOpen && (
<div className="fixed top-1/3 right-0 -translate-y-1/2 z-20">
<CollapsedButton onToggle={onToggle} />
</div>
)}
<div
style={{
width: isOpen ? "25%" : "0",
right: 0,
top: isHeaderVisible ? "64px" : "0",
}}
className="fixed top-0 bottom-0 z-20 bg-white shadow-xl">
{isOpen && (
<div className="h-full flex flex-col">
<SyllabusHeader onToggle={onToggle} />
<div className="flex-1 overflow-y-auto p-4">
<div className="space-y-4">
{sections.map((section, index) => (
<SectionItem
key={section.id}
ref={(el) =>
(sectionRefs.current[section.id] =
el)
}
index={index + 1}
section={section}
isExpanded={expandedSections.includes(
section.id
)}
onToggle={toggleSection}
onLectureClick={onLectureClick}
/>
))}
</div>
</div>
</div>
)}
</div>
</>
);
};