125 lines
3.8 KiB
TypeScript
Executable File
125 lines
3.8 KiB
TypeScript
Executable File
import { useState, useMemo, useEffect } from "react";
|
|
import { mockCourses } from "./mockData";
|
|
import FilterSection from "./components/FilterSection";
|
|
import CourseList from "./components/CourseList";
|
|
import { api } from "@nice/client";
|
|
import { courseDetailSelect, CourseDto, LectureType, PostType } from "@nice/common";
|
|
import { useSearchParams } from "react-router-dom";
|
|
import { set } from "idb-keyval";
|
|
|
|
|
|
export default function CoursesPage() {
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [selectedCategory, setSelectedCategory] = useState("");
|
|
const [selectedLevel, setSelectedLevel] = useState("");
|
|
const pageSize = 12;
|
|
const [isAll,setIsAll] = useState(true)
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
let coursesData = []
|
|
let isCourseLoading = false
|
|
if(!searchParams.get('searchValue')){
|
|
console.log('no category')
|
|
const {data,isLoading} = api.post.findManyWithPagination.useQuery({
|
|
where: {
|
|
type: PostType.COURSE,
|
|
terms:isAll?{}:{
|
|
some: {
|
|
OR : [
|
|
selectedCategory?{name:selectedCategory}:{},
|
|
selectedLevel?{name:selectedLevel}:{}
|
|
],
|
|
},
|
|
},
|
|
|
|
},
|
|
select:courseDetailSelect
|
|
});
|
|
coursesData = data?.items
|
|
isCourseLoading = isLoading
|
|
}else{
|
|
console.log('searchValue:'+searchParams.get('searchValue'))
|
|
const searchValue = searchParams.get('searchValue')
|
|
const {data,isLoading} = api.post.findManyWithPagination.useQuery({
|
|
where: {
|
|
type: PostType.COURSE,
|
|
OR:[
|
|
{ title: { contains: searchValue, mode: 'insensitive' } },
|
|
{ subTitle: { contains: searchValue, mode: 'insensitive' } },
|
|
{ content: { contains: searchValue, mode: 'insensitive' } },
|
|
{ terms: { some: { name: { contains: searchValue, mode: 'insensitive' } } } }
|
|
]
|
|
},
|
|
select:courseDetailSelect
|
|
})
|
|
coursesData = data?.items
|
|
isCourseLoading = isLoading
|
|
}
|
|
useEffect(() => {
|
|
console.log(coursesData)
|
|
}, [coursesData]);
|
|
const filteredCourses = useMemo(() => {
|
|
return isCourseLoading ? [] : coursesData;
|
|
}, [isCourseLoading, coursesData, selectedCategory, selectedLevel]);
|
|
|
|
const paginatedCourses :CourseDto[]= useMemo(() => {
|
|
const startIndex = (currentPage - 1) * pageSize;
|
|
return isCourseLoading ? [] : (filteredCourses.slice(startIndex, startIndex + pageSize) as any as CourseDto[]);
|
|
}, [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) => {
|
|
console.log(category);
|
|
setSelectedCategory(category);
|
|
setCurrentPage(1);
|
|
setIsAll(!category)
|
|
setSearchParams({ searchValue: ''});
|
|
}}
|
|
onLevelChange={(level) => {
|
|
setSelectedLevel(level);
|
|
setCurrentPage(1);
|
|
setIsAll(!level)
|
|
setSearchParams({ searchValue: ''});
|
|
}}
|
|
/>
|
|
</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>
|
|
);
|
|
}
|