73 lines
3.1 KiB
TypeScript
73 lines
3.1 KiB
TypeScript
![]() |
import { useState, useMemo } from 'react';
|
||
|
import { mockCourses } from './mockData';
|
||
|
import FilterSection from './components/FilterSection';
|
||
|
import CourseList from './components/CourseList';
|
||
|
|
||
|
export default function CoursesPage() {
|
||
|
const [currentPage, setCurrentPage] = useState(1);
|
||
|
const [selectedCategory, setSelectedCategory] = useState('');
|
||
|
const [selectedLevel, setSelectedLevel] = useState('');
|
||
|
const pageSize = 12;
|
||
|
|
||
|
const filteredCourses = useMemo(() => {
|
||
|
return mockCourses.filter(course => {
|
||
|
const matchCategory = !selectedCategory || course.category === selectedCategory;
|
||
|
const matchLevel = !selectedLevel || course.level === selectedLevel;
|
||
|
return matchCategory && matchLevel;
|
||
|
});
|
||
|
}, [selectedCategory, selectedLevel]);
|
||
|
|
||
|
const paginatedCourses = useMemo(() => {
|
||
|
const startIndex = (currentPage - 1) * pageSize;
|
||
|
return filteredCourses.slice(startIndex, startIndex + pageSize);
|
||
|
}, [filteredCourses, currentPage]);
|
||
|
|
||
|
const handlePageChange = (page: number) => {
|
||
|
setCurrentPage(page);
|
||
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div className="min-h-screen bg-gray-50">
|
||
|
<div className="container mx-auto px-4 py-8">
|
||
|
<div className="flex gap-4">
|
||
|
{/* 左侧筛选区域 */}
|
||
|
<div className="lg:w-1/5">
|
||
|
<div className="sticky top-24">
|
||
|
<FilterSection
|
||
|
selectedCategory={selectedCategory}
|
||
|
selectedLevel={selectedLevel}
|
||
|
onCategoryChange={category => {
|
||
|
setSelectedCategory(category);
|
||
|
setCurrentPage(1);
|
||
|
}}
|
||
|
onLevelChange={level => {
|
||
|
setSelectedLevel(level);
|
||
|
setCurrentPage(1);
|
||
|
}}
|
||
|
/>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
{/* 右侧课程列表区域 */}
|
||
|
<div className="lg:w-4/5">
|
||
|
<div className="bg-white p-6 rounded-lg shadow-sm">
|
||
|
<div className="flex justify-between items-center mb-6">
|
||
|
<span className="text-gray-600">
|
||
|
共找到 {filteredCourses.length} 门课程
|
||
|
</span>
|
||
|
</div>
|
||
|
<CourseList
|
||
|
courses={paginatedCourses}
|
||
|
total={filteredCourses.length}
|
||
|
pageSize={pageSize}
|
||
|
currentPage={currentPage}
|
||
|
onPageChange={handlePageChange}
|
||
|
/>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
}
|