diff --git a/apps/web/src/app/admin/base-setting/page.tsx b/apps/web/src/app/admin/base-setting/page.tsx index 1f8d42f..eb43d6b 100755 --- a/apps/web/src/app/admin/base-setting/page.tsx +++ b/apps/web/src/app/admin/base-setting/page.tsx @@ -44,12 +44,21 @@ export default function BaseSettingPage() { } async function onSubmit(values: BaseSetting) { setLoading(true); + const appConfig = values?.appConfig || {}; try { await update.mutateAsync({ where: { slug: AppConfigSlug.BASE_SETTING, }, - data: { meta: { ...baseSetting, ...values } }, + data: { + meta: { + ...baseSetting, + appConfig: { + ...baseSetting.appConfig, + ...appConfig, + }, + }, + }, }); setIsFormChanged(false); message.success("已保存"); diff --git a/apps/web/src/app/main/courses/components/CourseCard.tsx b/apps/web/src/app/main/courses/components/CourseCard.tsx index 84688f3..9a9f37d 100755 --- a/apps/web/src/app/main/courses/components/CourseCard.tsx +++ b/apps/web/src/app/main/courses/components/CourseCard.tsx @@ -1,90 +1,90 @@ -import { Card, Rate, Tag ,Typography,Button} from 'antd'; -import { Course } from '../mockData'; -import { UserOutlined, ClockCircleOutlined, PlayCircleOutlined, TeamOutlined } from '@ant-design/icons'; -import { CourseDto } from '@nice/common'; -import { useNavigate } from 'react-router-dom'; - +import { Card, Rate, Tag, Typography, Button } from "antd"; +import { Course } from "../mockData"; +import { + UserOutlined, + ClockCircleOutlined, + PlayCircleOutlined, + TeamOutlined, +} from "@ant-design/icons"; +import { CourseDto, TaxonomySlug } from "@nice/common"; +import { useNavigate } from "react-router-dom"; interface CourseCardProps { - course: CourseDto; + course: CourseDto; } const { Title, Text } = Typography; export default function CourseCard({ course }: CourseCardProps) { - const navigate = useNavigate(); - const handleClick = (course: CourseDto) => { - navigate(`/course/${course.id}/detail`); - } - return ( - handleClick(course)} - key={course.id} - hoverable - className="group overflow-hidden rounded-2xl border border-gray-200 bg-white + const navigate = useNavigate(); + const handleClick = (course: CourseDto) => { + navigate(`/course/${course.id}/detail`); + }; + return ( + 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> - + cover={ +
+
+
+ +
+ }> +
+
+ + {course.terms?.[0].name} + -
- -
- - {course?.depts[0]?.name} - -
- - 观看次数{course?.meta?.views}次 - -
+ + {course.terms?.[1].name} + +
+ + <button> {course.title}</button> + +
+ +
+ + {course?.depts?.[0]?.name} + +
+ + 观看次数{course?.meta?.views}次 + +
-
- -
- -
- - ); +
+ +
+
+ + ); } diff --git a/apps/web/src/app/main/courses/components/CourseList.tsx b/apps/web/src/app/main/courses/components/CourseList.tsx index f3e3177..4550795 100755 --- a/apps/web/src/app/main/courses/components/CourseList.tsx +++ b/apps/web/src/app/main/courses/components/CourseList.tsx @@ -1,44 +1,74 @@ -import { Pagination, Empty } from 'antd'; -import { Course } from '../mockData'; -import CourseCard from './CourseCard'; -import {CourseDto} from '@nice/common' +import { Pagination, Empty } from "antd"; +import CourseCard from "./CourseCard"; +import { CourseDto, Prisma } from "@nice/common"; +import { api } from "@nice/client"; +import { DefaultArgs } from "@prisma/client/runtime/library"; +import { useEffect, useMemo, useState } from "react"; interface CourseListProps { - courses: CourseDto[]; - total: number; - pageSize: number; - currentPage: number; - onPageChange: (page: number) => void; + params?: { + page?: number; + pageSize?: number; + where?: Prisma.PostWhereInput; + select?: Prisma.PostSelect; + }; } +interface CoursesPagnationProps { + data: { + items: CourseDto[]; + totalPages: number; + }; + isLoading: boolean; +} +export default function CourseList({ params }: CourseListProps) { + const [currentPage, setCurrentPage] = useState(params?.page || 1); + const { data, isLoading }: CoursesPagnationProps = + api.post.findManyWithPagination.useQuery({ + ...params, + page: currentPage, + }); + const totalPages = useMemo(() => { + if (data && !isLoading) { + return data?.totalPages; + } + return 1; + }, [data, isLoading]); -export default function CourseList({ - courses, - total, - pageSize, - currentPage, - onPageChange, -}: CourseListProps) { - return ( -
- {courses.length > 0 ? ( - <> -
- {courses.map(course => ( - - ))} -
-
- -
- - ) : ( - - )} -
- ); -} \ No newline at end of file + const courses = useMemo(() => { + if (data && !isLoading) { + return data?.items; + } + return []; + }, [data, isLoading]); + + useEffect(() => { + setCurrentPage(params?.page || 1); + }, [params?.page]); + function onPageChange(page: number, pageSize: number) { + setCurrentPage(page); + window.scrollTo({ top: 0, behavior: "smooth" }); + } + return ( +
+ {courses.length > 0 ? ( + <> +
+ {courses.map((course) => ( + + ))} +
+
+ +
+ + ) : ( + + )} +
+ ); +} diff --git a/apps/web/src/app/main/courses/components/FilterSection.tsx b/apps/web/src/app/main/courses/components/FilterSection.tsx index 9c74447..69fd828 100755 --- a/apps/web/src/app/main/courses/components/FilterSection.tsx +++ b/apps/web/src/app/main/courses/components/FilterSection.tsx @@ -69,9 +69,6 @@ export default function FilterSection({ return (
- {/*
- -
*/} {taxonomies?.map((tax) => { return ( <> @@ -88,27 +85,6 @@ export default function FilterSection({ })} - -
-

难度等级

- onLevelChange(e.target.value)} - className="flex flex-col space-y-3"> - {levels.isLoading ? ( - - ) : ( - <> - 全部难度 - {levels.categories.map((level) => ( - - {level} - - ))} - - )} - -
); } diff --git a/apps/web/src/app/main/courses/instructor/page.tsx b/apps/web/src/app/main/courses/instructor/page.tsx deleted file mode 100755 index a914925..0000000 --- a/apps/web/src/app/main/courses/instructor/page.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { PlusIcon } from "@heroicons/react/24/outline"; -import { CourseList } from "@web/src/components/models/course/list/course-list"; -import { Button } from "@web/src/components/common/element/Button"; -import { api } from "@nice/client"; -import { useState } from "react"; -import { CourseCard } from "@web/src/components/models/course/card/CourseCard"; -import { useNavigate } from "react-router-dom"; -import { useAuth } from "@web/src/providers/auth-provider"; - -export default function InstructorCoursesPage() { - const navigate = useNavigate(); - const [currentPage, setCurrentPage] = useState(1); - const { user } = useAuth(); - - const { data: paginationRes, refetch } = - api.post.findManyWithPagination.useQuery({ - page: currentPage, - pageSize: 8, - where: { - instructors: { - some: { - instructorId: user?.id, - }, - }, - }, - }); - - const handlePageChange = (page: number) => { - setCurrentPage(page); - refetch(); - }; - - return ( -
-
-
-

- 我教授的课程 -

- -
- ( - { - navigate(`/course/${course.id}/editor`, { - replace: true, - }); - }} - course={course} - /> - )} - /> -
-
- ); -} diff --git a/apps/web/src/app/main/courses/page.tsx b/apps/web/src/app/main/courses/page.tsx index 080368d..fa2fe9a 100755 --- a/apps/web/src/app/main/courses/page.tsx +++ b/apps/web/src/app/main/courses/page.tsx @@ -11,170 +11,25 @@ import { } from "@nice/common"; import { useSearchParams } from "react-router-dom"; import { set } from "idb-keyval"; +import { useMainContext } from "../layout/MainProvider"; interface paginationData { - items:CourseDto[], - totalPages:number + items: CourseDto[]; + totalPages: number; } 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(); + const { searchValue, setSearchValue } = useMainContext(); - const [coursesData, setCoursesData] = useState([]); - const [isCourseLoading, setIsCourseLoading] = useState(false); - const [totalPagesNum, setTotalPagesNum] = useState(0); - - if(!searchParams.get('searchValue') && !searchParams.get('searchValue')){ - const {data,isLoading} :{ data:paginationData,isLoading:boolean} = api.post.findManyWithPagination.useQuery({ - where: { - type: PostType.COURSE, - terms: isAll - ? {} - : { - some: { - OR: [ - selectedCategory - ? { name: selectedCategory } - : {}, - selectedLevel - ? { name: selectedLevel } - : {}, - ], - }, - }, - }, - pageSize, - page:currentPage, - select:courseDetailSelect, - }); - console.log(data) - useEffect(()=>{ - console.log(currentPage); - setIsCourseLoading(isLoading) - setCoursesData(data?.items) - setTotalPagesNum(data?.totalPages) - },[currentPage,data]) - }else{ - console.log('searchValue:'+searchParams.get('searchValue')) - const searchValue = searchParams.get('searchValue') - const {data,isLoading} :{ data:paginationData,isLoading:boolean}= 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, - pageSize, - page:currentPage, - }) - useEffect(()=>{ - setIsCourseLoading(isLoading) - setCoursesData(data?.items) - setTotalPagesNum(data?.totalPages) - },[currentPage]) - } - useEffect(() => { - if (searchParams.get("searchValue") == "") { - setSelectedCategory(""); - setSelectedLevel(""); - } - }, [searchParams.get("searchValue")]); - 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" }); - }; - useEffect(() => { - setCurrentPage(1); - }, []); - return ( -
-
-
- {/* 左侧筛选区域 */} -
-
- { - console.log(category); - setSelectedCategory(category); - setCurrentPage(1); - setIsAll(!category) - setSearchParams(prev => { - prev.delete('searchValue'); - return prev; - }); - }} - onLevelChange={(level) => { - setSelectedLevel(level); - setCurrentPage(1); - setIsAll(!level) - setSearchParams(prev => { - prev.delete('searchValue'); - return prev; - }); - }} - /> -
-
- - {/* 右侧课程列表区域 */} -
-
-
- - 共找到 {totalPagesNum * pageSize || 0} 门课程 - -
- -
-
-
+ <> +
+
{searchValue}
+
-
+ ); } diff --git a/apps/web/src/app/main/courses/student/page.tsx b/apps/web/src/app/main/courses/student/page.tsx deleted file mode 100755 index 2508c50..0000000 --- a/apps/web/src/app/main/courses/student/page.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { CourseList } from "@web/src/components/models/course/list/course-list"; -import { api } from "@nice/client"; -import { useState } from "react"; -import { CourseCard } from "@web/src/components/models/course/card/CourseCard"; -import { useAuth } from "@web/src/providers/auth-provider"; - -export default function StudentCoursesPage() { - const [currentPage, setCurrentPage] = useState(1); - const { user } = useAuth(); - - const { data: paginationRes, refetch } = - api.post.findManyWithPagination.useQuery({ - page: currentPage, - pageSize: 8, - where: { - enrollments: { - some: { - studentId: user?.id, - }, - }, - }, - }); - - const handlePageChange = (page: number) => { - setCurrentPage(page); - refetch(); - }; - - return ( -
-
-
-

- 我参加的课程 -

-
- ( - - )}> -
-
- ); -} diff --git a/apps/web/src/app/main/home/components/CoursesSection.tsx b/apps/web/src/app/main/home/components/CoursesSection.tsx index 1fe12af..2117baa 100755 --- a/apps/web/src/app/main/home/components/CoursesSection.tsx +++ b/apps/web/src/app/main/home/components/CoursesSection.tsx @@ -1,275 +1,178 @@ -import React, { useState, useMemo, useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Button, Card, Typography, Tag, Spin, Empty } from 'antd'; +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'; + PlayCircleOutlined, + TeamOutlined, + ArrowRightOutlined, +} from "@ant-design/icons"; +import { CourseDto, TaxonomySlug, TermDto } from "@nice/common"; +import { api } from "@nice/client"; +import CourseCard from "../../courses/components/CourseCard"; interface GetTaxonomyProps { - categories: string[]; - isLoading: boolean; + 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 } + const { data, isLoading }: { data: TermDto[]; isLoading: boolean } = + api.term.findMany.useQuery({ + where: { + taxonomy: { + slug: type, + }, + }, + include: { + children: true, + }, + take: 10, // 只取前10个 + orderBy: {}, + }); + 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 - }, - orderBy: { - createdAt: 'desc', // 按创建时间降序排列 - }, - }); + 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 }; + 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; + title: string; + description: string; + initialVisibleCoursesCount?: number; } - const CoursesSection: React.FC = ({ - title, - description, - initialVisibleCoursesCount = 8, + title, + description, }) => { - const navigate = useNavigate(); - const [selectedCategory, setSelectedCategory] = useState('全部'); - const [visibleCourses, setVisibleCourses] = useState(initialVisibleCoursesCount); - const gateGory: GetTaxonomyProps = useGetTaxonomy({ - type: TaxonomySlug.CATEGORY, - }) + const navigate = useNavigate(); + const [selectedCategory, setSelectedCategory] = useState("全部"); + const gateGory: GetTaxonomyProps = useGetTaxonomy({ + type: TaxonomySlug.CATEGORY, + }); + const { data, isLoading: isDataLoading } = + useFetchCoursesByCategory(selectedCategory); + const filteredCourses = useMemo(() => { + return selectedCategory === "全部" + ? data + : data?.filter((c) => + c.terms.some((t) => t.name === selectedCategory) + ); + }, [selectedCategory, data]); + const displayedCourses = isDataLoading ? [] : filteredCourses; + return ( +
+
+
+
+ + {title} + + + {description} + +
+
- const { data, isLoading: isDataLoading } = useFetchCoursesByCategory(selectedCategory); +
+ {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); + }} + 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} + + ))} + + )} +
- useEffect(() => { - console.log('dept data:', data) - }) - const handleClick = (course: CourseDto) => { - navigate(`/course/${course.id}/detail`); - } - - - 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 && ( -
-
-
- -
-
- )} -
-
- ); +
+ {displayedCourses.length === 0 ? ( +
+ +
+ ) : ( + displayedCourses?.map((course) => ( + + )) + )} +
+ { +
+
+
+ +
+
+ } +
+
+ ); }; - export default CoursesSection; diff --git a/apps/web/src/app/main/home/page.tsx b/apps/web/src/app/main/home/page.tsx index 7250975..0cf5123 100755 --- a/apps/web/src/app/main/home/page.tsx +++ b/apps/web/src/app/main/home/page.tsx @@ -1,163 +1,18 @@ import HeroSection from "./components/HeroSection"; import CategorySection from "./components/CategorySection"; import CoursesSection from "./components/CoursesSection"; -import FeaturedTeachersSection from "./components/FeaturedTeachersSection"; -import { api } from "@nice/client"; -import { useEffect, useState } from "react"; -import TermTree from "@web/src/components/models/term/term-tree"; -interface Courses { - id: number; - title: string; - instructor: string; - students: number; - rating: number; - level: string; - duration: string; - category: string; - progress: number; - thumbnail: string; -} -const HomePage = () => { - // { - // id: 1, - // title: 'Python 零基础入门', - // instructor: '张教授', - // students: 12000, - // rating: 4.8, - // level: '入门', - // duration: '36小时', - // category: '编程语言', - // progress: 16, - // thumbnail: '/images/course1.jpg', - // }, - // { - // id: 2, - // title: '数据结构与算法', - // instructor: '李教授', - // students: 8500, - // rating: 4.9, - // level: '进阶', - // duration: '48小时', - // category: '计算机基础', - // progress: 35, - // thumbnail: '/images/course2.jpg', - // }, - // { - // id: 3, - // title: '前端开发实战', - // instructor: '王教授', - // students: 10000, - // rating: 4.7, - // level: '中级', - // duration: '42小时', - // category: '前端开发', - // progress: 68, - // thumbnail: '/images/course3.jpg', - // }, - // { - // id: 4, - // title: 'Java企业级开发', - // instructor: '刘教授', - // students: 9500, - // rating: 4.6, - // level: '高级', - // duration: '56小时', - // category: '编程语言', - // progress: 15, - // thumbnail: '/images/course4.jpg', - // }, - // { - // id: 5, - // title: '人工智能基础', - // instructor: '陈教授', - // students: 11000, - // rating: 4.9, - // level: '中级', - // duration: '45小时', - // category: '人工智能', - // progress: 20, - // thumbnail: '/images/course5.jpg', - // }, - // { - // id: 6, - // title: '大数据分析', - // instructor: '赵教授', - // students: 8000, - // rating: 4.8, - // level: '进阶', - // duration: '50小时', - // category: '数据科学', - // progress: 45, - // thumbnail: '/images/course6.jpg', - // }, - // { - // id: 7, - // title: '云计算实践', - // instructor: '孙教授', - // students: 7500, - // rating: 4.7, - // level: '高级', - // duration: '48小时', - // category: '云计算', - // progress: 15, - // thumbnail: '/images/course7.jpg', - // }, - // { - // id: 8, - // title: '移动应用开发', - // instructor: '周教授', - // students: 9000, - // rating: 4.8, - // level: '中级', - // duration: '40小时', - // category: '移动开发', - // progress: 70, - // thumbnail: '/images/course8.jpg', - // }, - // ]; - const { data, isLoading }: { data: Courses[]; isLoading: boolean } = - api.post.findMany.useQuery({ - where: {}, - include: { - instructors: true, - }, - orderBy: { - createdAt: "desc", // 按创建时间降序排列 - }, - take: 8, // 只获取前8个课程 - }); - useEffect(() => { - if (data) { - console.log("mockCourses data:", data); - } - }, [data]); - // 数据处理逻辑 - // 修正依赖数组 + +const HomePage = () => { + return (
- - {/* {formattedCourses.map((course)=>{ - return ( - <> - course.title - - ) - })} */} - {/* */} - {/* */}
); }; diff --git a/apps/web/src/app/main/layout/MainHeader.tsx b/apps/web/src/app/main/layout/MainHeader.tsx index 40053e1..47503b5 100755 --- a/apps/web/src/app/main/layout/MainHeader.tsx +++ b/apps/web/src/app/main/layout/MainHeader.tsx @@ -1,19 +1,17 @@ -import { useState } from "react"; +import { useContext, useState } from "react"; import { Input, Layout, Avatar, Button, Dropdown } from "antd"; import { EditFilled, SearchOutlined, UserOutlined } from "@ant-design/icons"; import { useAuth } from "@web/src/providers/auth-provider"; import { useNavigate, useSearchParams } from "react-router-dom"; import { UserMenu } from "./UserMenu/UserMenu"; import { NavigationMenu } from "./NavigationMenu"; - +import { useMainContext } from "./MainProvider"; const { Header } = Layout; export function MainHeader() { - const [searchValue, setSearchValue] = useState(""); const { isAuthenticated, user } = useAuth(); const navigate = useNavigate(); - const [searchParams,setSearchParams] = useSearchParams(); - + const { searchValue, setSearchValue } = useMainContext(); return (
@@ -37,16 +35,17 @@ export function MainHeader() { value={searchValue} onChange={(e) => setSearchValue(e.target.value)} onPressEnter={(e) => { - //console.log(e) - //setSearchValue(""); - setSearchParams((prev)=>{ - if(searchParams.get("category")) prev.delete("category") - return prev - }) - navigate( - `/courses/?searchValue=${searchValue}` - ); - window.scrollTo({ top: 0, behavior: "smooth" }); + if ( + !window.location.pathname.startsWith( + "/courses/" + ) + ) { + navigate(`/courses/`); + window.scrollTo({ + top: 0, + behavior: "smooth", + }); + } }} />
diff --git a/apps/web/src/app/main/layout/MainLayout.tsx b/apps/web/src/app/main/layout/MainLayout.tsx index 09f5670..0a0074b 100755 --- a/apps/web/src/app/main/layout/MainLayout.tsx +++ b/apps/web/src/app/main/layout/MainLayout.tsx @@ -1,19 +1,21 @@ -import { Layout } from 'antd'; -import { Outlet } from 'react-router-dom'; -import { MainHeader } from './MainHeader'; -import { MainFooter } from './MainFooter'; +import { Layout } from "antd"; +import { Outlet } from "react-router-dom"; +import { MainHeader } from "./MainHeader"; +import { MainFooter } from "./MainFooter"; +import { MainProvider } from "./MainProvider"; const { Content } = Layout; export function MainLayout() { - return ( - - - - - - - - - ); -} \ No newline at end of file + return ( + + + + + + + + + + ); +} diff --git a/apps/web/src/app/main/layout/MainProvider.tsx b/apps/web/src/app/main/layout/MainProvider.tsx new file mode 100644 index 0000000..d503c39 --- /dev/null +++ b/apps/web/src/app/main/layout/MainProvider.tsx @@ -0,0 +1,31 @@ +import React, { createContext, ReactNode, useContext, useState } from "react"; + +interface MainContextType { + searchValue?: string; + setSearchValue?: React.Dispatch>; +} + +const MainContext = createContext(null); +interface MainProviderProps { + children: ReactNode; +} + +export function MainProvider({ children }: MainProviderProps) { + const [searchValue, setSearchValue] = useState(""); + return ( + + {children} + + ); +} +export const useMainContext = () => { + const context = useContext(MainContext); + if (!context) { + throw new Error("useMainContext must be used within MainProvider"); + } + return context; +}; diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx index 70f60a8..07c7c9c 100755 --- a/apps/web/src/routes/index.tsx +++ b/apps/web/src/routes/index.tsx @@ -8,8 +8,6 @@ import { import ErrorPage from "../app/error"; import WithAuth from "../components/utils/with-auth"; import LoginPage from "../app/login"; -import StudentCoursesPage from "../app/main/courses/student/page"; -import InstructorCoursesPage from "../app/main/courses/instructor/page"; import HomePage from "../app/main/home/page"; import { CourseDetailPage } from "../app/main/course/detail/page"; import { CourseBasicForm } from "../components/models/course/editor/form/CourseBasicForm"; @@ -41,7 +39,6 @@ export type CustomRouteObject = | CustomIndexRouteObject | CustomNonIndexRouteObject; export const routes: CustomRouteObject[] = [ - { path: "/", errorElement: , @@ -66,39 +63,16 @@ export const routes: CustomRouteObject[] = [ path: "courses", element: , }, - { - path: "my-courses", - }, + { path: "profiles", }, - { - path: "courses", - children: [ - { - path: "student", - element: ( - - - - ), - }, - { - path: "instructor", - element: ( - - - - ), - }, - ], - }, + // 课程预览页面 { path: "coursePreview/:id?", - element: - } - + element: , + }, ], }, { @@ -106,20 +80,27 @@ export const routes: CustomRouteObject[] = [ children: [ { path: ":id?/editor", - element: , + element: ( + + + + ), children: [ { index: true, - element: , + element: ( + + + + ), }, - // { - // path: "goal", - // element: , - // }, + { path: "content", element: ( - + + + ), }, // { @@ -146,5 +127,4 @@ export const routes: CustomRouteObject[] = [ }, ]; - export const router = createBrowserRouter(routes);