diff --git a/apps/web/src/app/main/courses/components/CourseCard.tsx b/apps/web/src/app/main/courses/components/CourseCard.tsx index d549a1e..5d7c3cd 100755 --- a/apps/web/src/app/main/courses/components/CourseCard.tsx +++ b/apps/web/src/app/main/courses/components/CourseCard.tsx @@ -1,9 +1,10 @@ import { Card, Rate, Tag } from 'antd'; import { Course } from '../mockData'; import { UserOutlined, ClockCircleOutlined } from '@ant-design/icons'; +import { CourseDto } from '@nice/common'; interface CourseCardProps { - course: Course; + course: CourseDto; } export default function CourseCard({ course }: CourseCardProps) { @@ -14,7 +15,7 @@ export default function CourseCard({ course }: CourseCardProps) { cover={ {course.title} } @@ -23,7 +24,7 @@ export default function CourseCard({ course }: CourseCardProps) {

{course.title}

-

{course.instructor}

+

{course.subTitle}

{course.rating} @@ -31,7 +32,7 @@ export default function CourseCard({ course }: CourseCardProps) {
- {course.enrollments} 人在学 + {course.enrollments?.length} 人在学
@@ -39,8 +40,8 @@ export default function CourseCard({ course }: CourseCardProps) {
- {course.category} - {course.level} + {course.terms[0].name} + {course.terms[1].name}
diff --git a/apps/web/src/app/main/courses/components/CourseList.tsx b/apps/web/src/app/main/courses/components/CourseList.tsx index 3d67b1c..f3e3177 100755 --- a/apps/web/src/app/main/courses/components/CourseList.tsx +++ b/apps/web/src/app/main/courses/components/CourseList.tsx @@ -1,9 +1,9 @@ import { Pagination, Empty } from 'antd'; import { Course } from '../mockData'; import CourseCard from './CourseCard'; - +import {CourseDto} from '@nice/common' interface CourseListProps { - courses: Course[]; + courses: CourseDto[]; total: number; pageSize: number; currentPage: number; diff --git a/apps/web/src/app/main/courses/components/FilterSection.tsx b/apps/web/src/app/main/courses/components/FilterSection.tsx index 6de4312..6fe06c4 100755 --- a/apps/web/src/app/main/courses/components/FilterSection.tsx +++ b/apps/web/src/app/main/courses/components/FilterSection.tsx @@ -75,7 +75,7 @@ export default function FilterSection({ : ( <> - 全部课程 + 全部课程 {gateGory.categories.map(category => ( {category} diff --git a/apps/web/src/app/main/courses/page.tsx b/apps/web/src/app/main/courses/page.tsx index cfdd484..c860a82 100755 --- a/apps/web/src/app/main/courses/page.tsx +++ b/apps/web/src/app/main/courses/page.tsx @@ -1,9 +1,11 @@ -import { useState, useMemo } from "react"; +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 { LectureType, PostType } from "@nice/common"; +import { courseDetailSelect, CourseDto, LectureType, PostType } from "@nice/common"; +import { useSearchParams } from "react-router-dom"; +import { set } from "idb-keyval"; export default function CoursesPage() { @@ -11,43 +13,57 @@ export default function CoursesPage() { 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 [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}:{} + ], + }, }, + }, - }, - }); - const filteredCourses = useMemo(() => { - return mockCourses.filter((course) => { - const matchCategory = - !selectedCategory || course.category === selectedCategory; - const matchLevel = !selectedLevel || course.level === selectedLevel; - return matchCategory && matchLevel; + select:courseDetailSelect }); - }, [selectedCategory, selectedLevel]); + 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 = useMemo(() => { + const paginatedCourses :CourseDto[]= useMemo(() => { const startIndex = (currentPage - 1) * pageSize; - return filteredCourses.slice(startIndex, startIndex + pageSize); + return isCourseLoading ? [] : (filteredCourses.slice(startIndex, startIndex + pageSize) as any as CourseDto[]); }, [filteredCourses, currentPage]); const handlePageChange = (page: number) => { @@ -55,6 +71,8 @@ export default function CoursesPage() { window.scrollTo({ top: 0, behavior: "smooth" }); }; + + return (
@@ -69,10 +87,14 @@ export default function CoursesPage() { console.log(category); setSelectedCategory(category); setCurrentPage(1); + setIsAll(!category) + setSearchParams({ searchValue: ''}); }} onLevelChange={(level) => { setSelectedLevel(level); setCurrentPage(1); + setIsAll(!level) + setSearchParams({ searchValue: ''}); }} />
diff --git a/apps/web/src/app/main/layout/MainHeader.tsx b/apps/web/src/app/main/layout/MainHeader.tsx index 80ea733..cc2325d 100755 --- a/apps/web/src/app/main/layout/MainHeader.tsx +++ b/apps/web/src/app/main/layout/MainHeader.tsx @@ -35,6 +35,10 @@ export function MainHeader() { className="w-72 rounded-full" value={searchValue} onChange={(e) => setSearchValue(e.target.value)} + onPressEnter={()=>{ + //console.log(searchValue) + navigate(`/courses/?searchValue=${searchValue}`) + }} />
{isAuthenticated && ( diff --git a/packages/common/src/models/post.ts b/packages/common/src/models/post.ts index fa030b6..4a1aa99 100755 --- a/packages/common/src/models/post.ts +++ b/packages/common/src/models/post.ts @@ -77,5 +77,5 @@ export type Course = Post & { export type CourseDto = Course & { enrollments?: Enrollment[]; sections?: SectionDto[]; - terms: Term[]; + terms: TermDto[]; }; diff --git a/packages/common/src/models/select.ts b/packages/common/src/models/select.ts index 5417c1c..36e072d 100755 --- a/packages/common/src/models/select.ts +++ b/packages/common/src/models/select.ts @@ -70,28 +70,27 @@ export const courseDetailSelect: Prisma.PostSelect = { title: true, subTitle: true, content: true, - - level: true, - // requirements: true, - // objectives: true, - // skills: true, - // audiences: true, - // totalDuration: true, - // totalLectures: true, - // averageRating: true, - // numberOfReviews: true, - // numberOfStudents: true, - // completionRate: true, - state: true, // isFeatured: true, createdAt: true, - publishedAt: true, + updatedAt: true, // 关联表选择 - children: { - include: { - children: true, + terms:{ + select:{ + id:true, + name:true, + taxonomy:{ + select:{ + id:true, + slug:true + } + } + } + }, + enrollments: { + select: { + id: true, }, }, - enrollments: true, meta: true, + rating: true, };