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

70 lines
2.1 KiB
TypeScript
Raw Normal View History

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
)
);