2025-02-20 20:02:27 +08:00
|
|
|
import { useState, useMemo } from "react";
|
|
|
|
import { mockCourses } from "./mockData";
|
|
|
|
import FilterSection from "./components/FilterSection";
|
|
|
|
import CourseList from "./components/CourseList";
|
|
|
|
import { api } from "@nice/client";
|
|
|
|
import { LectureType, PostType } from "@nice/common";
|
2025-02-06 16:32:31 +08:00
|
|
|
|
2025-02-20 20:13:11 +08:00
|
|
|
|
2025-02-06 16:32:31 +08:00
|
|
|
export default function CoursesPage() {
|
2025-02-20 20:02:27 +08:00
|
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
|
|
const [selectedCategory, setSelectedCategory] = useState("");
|
|
|
|
const [selectedLevel, setSelectedLevel] = useState("");
|
|
|
|
const pageSize = 12;
|
|
|
|
const { data, isLoading } = api.post.findManyWithPagination.useQuery({
|
|
|
|
where: {
|
|
|
|
type: PostType.COURSE,
|
|
|
|
terms: {
|
|
|
|
some: {
|
|
|
|
AND: [
|
|
|
|
...(selectedCategory
|
|
|
|
? [
|
|
|
|
{
|
|
|
|
name: selectedCategory,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
: []),
|
|
|
|
...(selectedLevel
|
|
|
|
? [
|
|
|
|
{
|
|
|
|
name: selectedLevel,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
: []),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const filteredCourses = useMemo(() => {
|
|
|
|
return mockCourses.filter((course) => {
|
|
|
|
const matchCategory =
|
|
|
|
!selectedCategory || course.category === selectedCategory;
|
|
|
|
const matchLevel = !selectedLevel || course.level === selectedLevel;
|
|
|
|
return matchCategory && matchLevel;
|
|
|
|
});
|
|
|
|
}, [selectedCategory, selectedLevel]);
|
2025-02-20 20:13:11 +08:00
|
|
|
|
2025-02-20 20:02:27 +08:00
|
|
|
const paginatedCourses = useMemo(() => {
|
|
|
|
const startIndex = (currentPage - 1) * pageSize;
|
|
|
|
return filteredCourses.slice(startIndex, startIndex + pageSize);
|
|
|
|
}, [filteredCourses, currentPage]);
|
2025-02-20 20:13:11 +08:00
|
|
|
|
2025-02-20 20:02:27 +08:00
|
|
|
const handlePageChange = (page: number) => {
|
|
|
|
setCurrentPage(page);
|
|
|
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
|
|
};
|
2025-02-06 16:32:31 +08:00
|
|
|
|
2025-02-20 20:02:27 +08:00
|
|
|
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) => {
|
2025-02-24 11:50:56 +08:00
|
|
|
console.log(category);
|
2025-02-20 20:02:27 +08:00
|
|
|
setSelectedCategory(category);
|
|
|
|
setCurrentPage(1);
|
|
|
|
}}
|
|
|
|
onLevelChange={(level) => {
|
|
|
|
setSelectedLevel(level);
|
|
|
|
setCurrentPage(1);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-02-06 16:32:31 +08:00
|
|
|
|
2025-02-20 20:02:27 +08:00
|
|
|
{/* 右侧课程列表区域 */}
|
|
|
|
<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>
|
|
|
|
);
|
|
|
|
}
|