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

80 lines
2.4 KiB
TypeScript
Executable File

import { ChevronDownIcon } from "@heroicons/react/24/outline";
import { SectionDto } from "@nice/common";
import { AnimatePresence, motion } from "framer-motion";
import React, { useMemo } from "react";
import { LectureItem } from "./LectureItem";
import { useParams } from "react-router-dom";
interface SectionItemProps {
section: SectionDto;
index?: number;
isExpanded: boolean;
onToggle: (sectionId: string) => void;
onLectureClick: (lectureId: string) => void;
ref: React.RefObject<HTMLDivElement>;
}
export const SectionItem = React.forwardRef<HTMLDivElement, SectionItemProps>(
({ section, index, isExpanded, onToggle, onLectureClick }, ref) => {
const { lectureId } = useParams();
const isReading = useMemo(() => {
return (section?.lectures || [])
?.map((lecture) => lecture?.id)
.includes(lectureId);
}, [lectureId, section]);
return (
<div
ref={ref}
className="border rounded-lg overflow-hidden bg-white shadow-sm hover:shadow-md transition-shadow">
<div
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">
{index}
</span>
<div className="flex flex-col items-start">
<h3 className="text-left font-medium text-gray-900">
{section.title}
</h3>
<p className="text-sm text-gray-500">
{section?.lectures?.length} ·
</p>
</div>
</div>
<div className=" flex justify-end gap-2">
{isReading && (
<span className="text-primary text-sm">
</span>
)}
<motion.div
animate={{ rotate: isExpanded ? 180 : 0 }}
transition={{ duration: 0.2 }}>
<ChevronDownIcon className="w-5 h-5 text-gray-500" />
</motion.div>
</div>
</div>
<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>
</div>
);
}
);