book_manage/apps/web/src/components/models/course/detail/CourseDetailContext.tsx

117 lines
2.8 KiB
TypeScript
Executable File

import { api, useVisitor } from "@nice/client";
import {
courseDetailSelect,
CourseDto,
Lecture,
lectureDetailSelect,
RolePerms,
VisitType,
} from "@nice/common";
import { useAuth } from "@web/src/providers/auth-provider";
import React, {
createContext,
ReactNode,
useEffect,
useMemo,
useState,
} from "react";
import { useNavigate, useParams } from "react-router-dom";
interface CourseDetailContextType {
editId?: string; // 添加 editId
course?: CourseDto;
lecture?: Lecture;
selectedLectureId?: string | undefined;
setSelectedLectureId?: React.Dispatch<React.SetStateAction<string>>;
isLoading?: boolean;
lectureIsLoading?: boolean;
isHeaderVisible: boolean; // 新增
setIsHeaderVisible: (visible: boolean) => void; // 新增
canEdit?: boolean;
userIsLearning?: boolean;
}
interface CourseFormProviderProps {
children: ReactNode;
editId?: string; // 添加 editId 参数
}
export const CourseDetailContext =
createContext<CourseDetailContextType | null>(null);
export function CourseDetailProvider({
children,
editId,
}: CourseFormProviderProps) {
const navigate = useNavigate();
const { read } = useVisitor();
const { user, hasSomePermissions, isAuthenticated } = useAuth();
const { lectureId } = useParams();
const { data: course, isLoading }: { data: CourseDto; isLoading: boolean } =
(api.post as any).findFirst.useQuery(
{
where: { id: editId },
select: courseDetailSelect,
},
{ enabled: Boolean(editId) }
);
const userIsLearning = useMemo(() => {
return (course?.studentIds || []).includes(user?.id);
}, [user, course, isLoading]);
const canEdit = useMemo(() => {
const isAuthor = isAuthenticated && user?.id === course?.authorId;
const isRoot = hasSomePermissions(RolePerms?.MANAGE_ANY_POST);
return isAuthor || isRoot;
}, [user, course]);
const [selectedLectureId, setSelectedLectureId] = useState<
string | undefined
>(lectureId || undefined);
const { data: lecture, isLoading: lectureIsLoading } = (
api.post as any
).findFirst.useQuery(
{
where: { id: selectedLectureId },
select: lectureDetailSelect,
},
{ enabled: Boolean(editId) }
);
useEffect(() => {
if (lecture?.id) {
read.mutateAsync({
data: {
visitorId: user?.id || null,
postId: lecture?.id,
type: VisitType.READED,
},
});
}
}, [course]);
useEffect(() => {
if (lectureId !== selectedLectureId) {
navigate(`/course/${editId}/detail/${selectedLectureId}`);
}
}, [selectedLectureId, editId]);
const [isHeaderVisible, setIsHeaderVisible] = useState(true); // 新增
return (
<CourseDetailContext.Provider
value={{
editId,
course,
lecture,
selectedLectureId,
setSelectedLectureId,
isLoading,
lectureIsLoading,
isHeaderVisible,
setIsHeaderVisible,
canEdit,
userIsLearning,
}}>
{children}
</CourseDetailContext.Provider>
);
}