import React, { useState, useMemo, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Button, Card, Typography, Tag, Spin, Empty } from 'antd'; import { PlayCircleOutlined, UserOutlined, ClockCircleOutlined, TeamOutlined, StarOutlined, ArrowRightOutlined, EyeOutlined, } from '@ant-design/icons'; import { CourseDto, TaxonomySlug, TermDto } from '@nice/common'; import { api } from '@nice/client'; interface GetTaxonomyProps { categories: string[]; isLoading: boolean; } function useGetTaxonomy({ type }): GetTaxonomyProps { const { data, isLoading }: { data: TermDto[], isLoading: boolean } = api.term.findMany.useQuery({ where: { taxonomy: { //TaxonomySlug.CATEGORY slug: type } }, include: { children: true }, take: 10, // 只取前10个 orderBy: { createdAt: 'desc', // 按创建时间降序排列 }, }) const categories = useMemo(() => { const allCategories = isLoading ? [] : data?.map((course) => course.name); return [...Array.from(new Set(allCategories))]; }, [data]); return { categories, isLoading } } // 不同分类跳转 function useFetchCoursesByCategory(category: string) { const isAll = category === '全部'; const { data, isLoading }: { data: CourseDto[], isLoading: boolean } = api.post.findMany.useQuery({ where: isAll ? {} : { terms: { some: { name: category }, }, }, take: 8, include: { terms: true, depts:true } }); return { data, isLoading }; } const { Title, Text } = Typography; interface Course { id: number; title: string; instructor: string; students: number; rating: number; level: string; duration: string; category: string; progress: number; thumbnail: string; } interface CoursesSectionProps { title: string; description: string; courses: Course[]; isLoading: boolean initialVisibleCoursesCount?: number; } const CoursesSection: React.FC = ({ title, description, initialVisibleCoursesCount = 8, }) => { const navigate = useNavigate(); const [selectedCategory, setSelectedCategory] = useState('全部'); const [visibleCourses, setVisibleCourses] = useState(initialVisibleCoursesCount); const gateGory: GetTaxonomyProps = useGetTaxonomy({ type: TaxonomySlug.CATEGORY, }) const { data, isLoading: isDataLoading } = useFetchCoursesByCategory(selectedCategory); // useEffect(() => { // console.log('data:', data) // }) const handleClick = (course: CourseDto) => { navigate(`/course/${course.id}/detail`); } useEffect(() => { console.log('data:', data) }) // const { data: depts, isLoading: isDeptLoading }: { data: CourseDto[], isLoading: boolean } = api.post.findMany.useQuery({ // where: {}, // include: { // depts: true, // }, // orderBy: { // createdAt: 'desc' // 按创建时间降序排列 // }, // take: 8 // 只获取前8个课程 // }); const filteredCourses = useMemo(() => { return selectedCategory === '全部' ? data : data?.filter(c => c.terms.some(t => t.name === selectedCategory)); }, [selectedCategory, data]); const displayedCourses = isDataLoading ? [] : filteredCourses?.slice(0, visibleCourses); return (
{title} {description}
{gateGory.isLoading ? : ( <> setSelectedCategory("全部")} className={`px-6 py-2 text-base cursor-pointer rounded-full transition-all duration-300 ${selectedCategory === "全部" ? 'bg-blue-600 text-white shadow-lg' : 'bg-white text-gray-600 hover:bg-gray-100' }`} >全部 {gateGory.categories.map((category) => ( { setSelectedCategory(category) console.log(category) }} className={`px-6 py-2 text-base cursor-pointer rounded-full transition-all duration-300 ${selectedCategory === category ? 'bg-blue-600 text-white shadow-lg' : 'bg-white text-gray-600 hover:bg-gray-100' }`} > {category} )) } ) }
{displayedCourses.length === 0 ? (
) : displayedCourses?.map((course) => ( handleClick(course)} key={course.id} hoverable className="group overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-xl hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2" cover={
} >
{course.terms[0].name} {course.terms[1].name}
<button > {course.title}</button>
{course?.depts[0]?.name}
观看次数{course?.meta?.views}次
))}
{filteredCourses?.length >= visibleCourses && (
)}
); }; export default CoursesSection;