2025-01-08 20:29:07 +08:00
|
|
|
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
|
|
|
import { SectionDto } from "@nice/common";
|
|
|
|
import { AnimatePresence, motion } from "framer-motion";
|
|
|
|
import React from "react";
|
|
|
|
import { LectureItem } from "./LectureItem";
|
|
|
|
|
|
|
|
// components/CourseSyllabus/SectionItem.tsx
|
|
|
|
interface SectionItemProps {
|
|
|
|
section: SectionDto;
|
2025-02-21 17:41:12 +08:00
|
|
|
index?: number;
|
2025-01-08 20:29:07 +08:00
|
|
|
isExpanded: boolean;
|
|
|
|
onToggle: (sectionId: string) => void;
|
|
|
|
onLectureClick: (lectureId: string) => void;
|
|
|
|
ref: React.RefObject<HTMLDivElement>;
|
|
|
|
}
|
|
|
|
|
|
|
|
export const SectionItem = React.forwardRef<HTMLDivElement, SectionItemProps>(
|
2025-02-21 17:41:12 +08:00
|
|
|
({ section, index, isExpanded, onToggle, onLectureClick }, ref) => (
|
2025-02-24 09:33:11 +08:00
|
|
|
<div
|
2025-01-08 20:29:07 +08:00
|
|
|
ref={ref}
|
2025-02-24 09:33:11 +08:00
|
|
|
// initial={{ opacity: 0, y: 20 }}
|
|
|
|
// animate={{ opacity: 1, y: 0 }}
|
|
|
|
// transition={{ duration: 0.3 }}
|
2025-01-08 20:29:07 +08:00
|
|
|
className="border rounded-lg overflow-hidden bg-white shadow-sm hover:shadow-md transition-shadow">
|
|
|
|
<button
|
|
|
|
className="w-full flex items-center justify-between p-4 hover:bg-gray-50 transition-colors"
|
|
|
|
onClick={() => onToggle(section.id)}>
|
|
|
|
<div className="flex items-center gap-4">
|
|
|
|
<span className="text-lg font-medium text-gray-700">
|
2025-02-21 17:41:12 +08:00
|
|
|
第{index}章
|
2025-01-08 20:29:07 +08:00
|
|
|
</span>
|
2025-02-21 17:41:12 +08:00
|
|
|
<div className="flex flex-col items-start">
|
2025-01-08 20:29:07 +08:00
|
|
|
<h3 className="text-left font-medium text-gray-900">
|
|
|
|
{section.title}
|
|
|
|
</h3>
|
|
|
|
<p className="text-sm text-gray-500">
|
2025-02-21 13:14:47 +08:00
|
|
|
{section?.lectures?.length}节课 ·{" "}
|
|
|
|
{/* {Math.floor(section?.totalDuration / 60)}分钟 */}
|
2025-01-08 20:29:07 +08:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<motion.div
|
|
|
|
animate={{ rotate: isExpanded ? 180 : 0 }}
|
|
|
|
transition={{ duration: 0.2 }}>
|
|
|
|
<ChevronDownIcon className="w-5 h-5 text-gray-500" />
|
|
|
|
</motion.div>
|
|
|
|
</button>
|
|
|
|
|
|
|
|
<AnimatePresence>
|
|
|
|
{isExpanded && (
|
|
|
|
<motion.div
|
|
|
|
initial={{ height: 0, opacity: 0 }}
|
|
|
|
animate={{ height: "auto", opacity: 1 }}
|
|
|
|
exit={{ height: 0, opacity: 0 }}
|
|
|
|
transition={{ duration: 0.3 }}
|
|
|
|
className="border-t">
|
|
|
|
{section.lectures.map((lecture) => (
|
|
|
|
<LectureItem
|
|
|
|
key={lecture.id}
|
|
|
|
lecture={lecture}
|
|
|
|
onClick={onLectureClick}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</motion.div>
|
|
|
|
)}
|
|
|
|
</AnimatePresence>
|
2025-02-24 09:33:11 +08:00
|
|
|
</div>
|
2025-01-08 20:29:07 +08:00
|
|
|
)
|
|
|
|
);
|