diff --git a/src/app/(main)/(pages)/bookmark/page.tsx b/src/app/(main)/(pages)/bookmark/page.tsx index a213853fc..42fe91d27 100644 --- a/src/app/(main)/(pages)/bookmark/page.tsx +++ b/src/app/(main)/(pages)/bookmark/page.tsx @@ -1,6 +1,6 @@ import { Content, CourseContent, VideoProgress } from '@prisma/client'; import BookmarkView from '@/components/bookmark/BookmarkView'; -import { getBookmarkDataWithContent } from '@/db/bookmark'; +import { getBookmarkData, getBookmarkDataWithContent } from '@/db/bookmark'; export type TWatchHistory = VideoProgress & { content: Content & { @@ -11,7 +11,7 @@ export type TWatchHistory = VideoProgress & { export default async function BookmarksPage() { const bookmarkData = await getBookmarkDataWithContent(); - + const bookmarks= await getBookmarkData(); return (
@@ -20,7 +20,7 @@ export default async function BookmarksPage() {
- +
); diff --git a/src/app/courses/[courseId]/layout.tsx b/src/app/courses/[courseId]/layout.tsx index 827af309b..4dcbd8b97 100644 --- a/src/app/courses/[courseId]/layout.tsx +++ b/src/app/courses/[courseId]/layout.tsx @@ -1,6 +1,7 @@ import { QueryParams } from '@/actions/types'; import { FilterContent } from '@/components/FilterContent'; import { Sidebar } from '@/components/Sidebar'; +import { getBookmarkData } from '@/db/bookmark'; import { getFullCourseContent } from '@/db/course'; import { authOptions } from '@/lib/auth'; import { getPurchases } from '@/utiles/appx'; @@ -12,7 +13,6 @@ type CheckAccessReturn = 'yes' | 'no' | 'error'; const checkAccess = async (courseId: string): Promise => { const session = await getServerSession(authOptions); - if (!session?.user) { return 'no'; } @@ -37,7 +37,7 @@ const Layout = async ({ }) => { const courseId = params.courseId; const hasAccess = await checkAccess(courseId); - + const bookmarks = await getBookmarkData(); if (hasAccess === 'no') { redirect('/api/auth/signin'); } @@ -51,7 +51,7 @@ const Layout = async ({
- +
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index eb6bd9824..acd8b7c1b 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -9,7 +9,7 @@ import { } from '@/components/ui/accordion'; import { Play, File, X, Menu } from 'lucide-react'; import { FullCourseContent } from '@/db/course'; -import { useRecoilState, useRecoilValue } from 'recoil'; +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; import { sidebarOpen as sidebarOpenAtom } from '@/store/atoms/sidebar'; import { useEffect, useState, useCallback, useMemo } from 'react'; import { handleMarkAsCompleted } from '@/lib/utils'; @@ -19,6 +19,8 @@ import { Button } from './ui/button'; import { AnimatePresence, motion } from 'framer-motion'; import { FilterContent } from './FilterContent'; import { selectFilter } from '@/store/atoms/filterContent'; +import { Bookmark } from '@prisma/client'; +import { bookmarksState } from '@/store/atoms/bookmark'; const sidebarVariants = { open: { width: '100%', @@ -37,9 +39,11 @@ const sidebarVariants = { export function Sidebar({ courseId, fullCourseContent, + initialBookmarks }: { fullCourseContent: FullCourseContent[]; courseId: string; + initialBookmarks:Bookmark[] }) { const pathName = usePathname(); const [sidebarOpen, setSidebarOpen] = useRecoilState(sidebarOpenAtom); @@ -52,6 +56,12 @@ export function Sidebar({ const closeSidebar = () => setSidebarOpen(false); const currentfilter = useRecoilValue(selectFilter); + const setBookmarks = useSetRecoilState(bookmarksState); + + useEffect(() => { + setBookmarks(initialBookmarks); + }, [initialBookmarks, setBookmarks]); + const findPathToContent = useCallback( ( contents: FullCourseContent[], diff --git a/src/components/bookmark/BookmarkList.tsx b/src/components/bookmark/BookmarkList.tsx index 0bbe4cec8..032f74b83 100644 --- a/src/components/bookmark/BookmarkList.tsx +++ b/src/components/bookmark/BookmarkList.tsx @@ -3,12 +3,22 @@ import { TBookmarkWithContent } from '@/actions/bookmark/types'; import { useRouter } from 'next/navigation'; import { ContentCard } from '../ContentCard'; +import { useEffect } from 'react'; +import { bookmarksState } from '@/store/atoms/bookmark'; +import { useSetRecoilState } from 'recoil'; +import { Bookmark } from '@prisma/client'; const BookmarkList = ({ bookmarkData, + initialBookmarks }: { bookmarkData: TBookmarkWithContent[] | { error: string }; + initialBookmarks: Bookmark[] }) => { + const setBookmarks = useSetRecoilState(bookmarksState); + useEffect(() => { + setBookmarks(initialBookmarks); + }, [initialBookmarks, setBookmarks]); const router = useRouter(); if ('error' in bookmarkData) { return ( diff --git a/src/components/bookmark/BookmarkView.tsx b/src/components/bookmark/BookmarkView.tsx index 6f5705016..f5d2e73c7 100644 --- a/src/components/bookmark/BookmarkView.tsx +++ b/src/components/bookmark/BookmarkView.tsx @@ -1,11 +1,14 @@ import BookmarkList from './BookmarkList'; import { TBookmarkWithContent } from '@/actions/bookmark/types'; import NoBookmark from './NoBookmark'; +import { Bookmark } from '@prisma/client'; const BookmarkView = ({ bookmarkData, + initialBookmarks }: { bookmarkData: TBookmarkWithContent[] | null | { error: string }; + initialBookmarks: Bookmark[] }) => { return ( <> @@ -14,7 +17,7 @@ const BookmarkView = ({ !bookmarkData.length ? ( ) : ( - + )} ); diff --git a/src/hooks/useBookmark.tsx b/src/hooks/useBookmark.tsx index cbbe22dd0..7b8b7fd2d 100644 --- a/src/hooks/useBookmark.tsx +++ b/src/hooks/useBookmark.tsx @@ -1,13 +1,17 @@ import { Bookmark } from '@prisma/client'; -import { MouseEvent, useState } from 'react'; +import { MouseEvent, useEffect, useState } from 'react'; import { useAction } from './useAction'; import { createBookmark, deleteBookmark } from '@/actions/bookmark'; import { toast } from 'sonner'; import Link from 'next/link'; +import { bookmarksState } from '@/store/atoms/bookmark'; +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; export const useBookmark = (bookmark: Bookmark | null, contentId: number) => { - const [addedBookmark, setAddedBookmark] = useState(bookmark); + const bookmarks = useRecoilValue(bookmarksState); + const setBookmarks = useSetRecoilState(bookmarksState); const [isDisabled, setIsDisabled] = useState(false); + const existingBookmark = bookmarks.find((b) => b.contentId === contentId) || null; const { execute: executeCreateBookmark } = useAction(createBookmark, { onSuccess: (data: Bookmark) => { toast( @@ -26,7 +30,7 @@ export const useBookmark = (bookmark: Bookmark | null, contentId: number) => {
, { duration: 3000 }, ); - setAddedBookmark(data); + setBookmarks( (prev)=>[...prev,data]) }, onError: (error) => { toast.error(error); @@ -40,6 +44,7 @@ export const useBookmark = (bookmark: Bookmark | null, contentId: number) => {
, { duration: 3000 }, ); + setBookmarks((prev) => prev.filter((b: { contentId: number; }) => b.contentId !== contentId)); // Remove from state }, onError: (error) => { toast.error(error); @@ -53,11 +58,11 @@ export const useBookmark = (bookmark: Bookmark | null, contentId: number) => { try { setIsDisabled(true); - if (addedBookmark) { + if (existingBookmark) { await executeDeleteBookmark({ - id: addedBookmark.id, + id: existingBookmark.id, }); - setAddedBookmark(null); + setBookmarks((prev) => prev.filter((b: { contentId: number; }) => b.contentId !== contentId)); // Remove from state } else { await executeCreateBookmark({ contentId, @@ -71,5 +76,5 @@ export const useBookmark = (bookmark: Bookmark | null, contentId: number) => { return false; }; - return { addedBookmark, handleBookmark, isDisabled }; + return { addedBookmark:existingBookmark, handleBookmark, isDisabled }; }; diff --git a/src/store/atoms/bookmark.ts b/src/store/atoms/bookmark.ts new file mode 100644 index 000000000..5d91e4558 --- /dev/null +++ b/src/store/atoms/bookmark.ts @@ -0,0 +1,7 @@ +import { atom } from 'recoil'; +import { Bookmark } from '@prisma/client'; + +export const bookmarksState = atom({ + key: 'bookmarksState', + default: [], +});