book_manage/apps/web/src/components/models/course/detail/course-syllabus.tsx

78 lines
3.5 KiB
TypeScript

import { ChevronDownIcon, ClockIcon, PlayCircleIcon } from '@heroicons/react/24/outline'
import { useState } from 'react'
import { Section, SectionDto } from "@nice/common"
interface CourseSyllabusProps {
sections: SectionDto[]
onLectureClick?: (lectureId: string) => void
}
export const CourseSyllabus: React.FC<CourseSyllabusProps> = ({
sections,
onLectureClick
}) => {
const [expandedSections, setExpandedSections] = useState<string[]>([])
const toggleSection = (sectionId: string) => {
setExpandedSections(prev =>
prev.includes(sectionId)
? prev.filter(id => id !== sectionId)
: [...prev, sectionId]
)
}
return (
<div className="space-y-4">
{sections.map((section) => (
<div key={section.id} className="border rounded-lg">
{/* 章节标题 */}
<button
className="w-full flex items-center justify-between p-4 hover:bg-gray-50"
onClick={() => toggleSection(section.id)}
>
<div className="flex items-center gap-4">
<span className="text-lg font-medium">
{Math.floor(section.order)}
</span>
<div>
<h3 className="text-left font-medium">{section.title}</h3>
<p className="text-sm text-gray-500">
{section.totalLectures} · {Math.floor(section.totalDuration / 60)}
</p>
</div>
</div>
<ChevronDownIcon
className={`w-5 h-5 transition-transform duration-200 ${expandedSections.includes(section.id) ? 'rotate-180' : ''
}`}
/>
</button>
{/* 课时列表 */}
{expandedSections.includes(section.id) && (
<div className="border-t">
{section.lectures.map((lecture) => (
<button
key={lecture.id}
className="w-full flex items-center gap-4 p-4 hover:bg-gray-50 text-left"
onClick={() => onLectureClick?.(lecture.id)}
>
<PlayCircleIcon className="w-5 h-5 text-blue-500 flex-shrink-0" />
<div className="flex-grow">
<h4 className="font-medium">{lecture.title}</h4>
{lecture.description && (
<p className="text-sm text-gray-500 mt-1">{lecture.description}</p>
)}
</div>
<div className="flex items-center gap-1 text-sm text-gray-500">
<ClockIcon className="w-4 h-4" />
<span>{lecture.duration}</span>
</div>
</button>
))}
</div>
)}
</div>
))}
</div>
)
}