1+ 'use client' ;
2+ import { useEffect , useState } from 'react' ;
3+ import { ChevronDown } from 'lucide-react' ;
4+ import Link from 'next/link' ;
5+
6+ interface BookmarkItem {
7+ id : string ;
8+ title : string ;
9+ subject : string ;
10+ url ?: string ;
11+ module ?: number ;
12+ topic ?: string ;
13+ }
14+
15+ type BookmarkType = 'modules' | 'topics' | 'videos' ;
16+
17+ export default function BookmarksPage ( ) {
18+ const [ bookmarks , setBookmarks ] = useState < BookmarkItem [ ] > ( [ ] ) ;
19+ const [ activeTab , setActiveTab ] = useState < BookmarkType > ( 'modules' ) ;
20+ const [ activeBookmarkId , setActiveBookmarkId ] = useState < string | null > ( null ) ;
21+
22+ const toggleActive = ( id : string ) => {
23+ setActiveBookmarkId ( prev => ( prev === id ? null : id ) ) ;
24+ } ;
25+
26+ useEffect ( ( ) => {
27+ const stored = JSON . parse ( localStorage . getItem ( 'bookmarks' ) || '[]' ) ;
28+ setBookmarks ( stored ) ;
29+ } , [ ] ) ;
30+
31+ const removeBookmark = ( id : string ) => {
32+ const updated = bookmarks . filter ( b => b . id !== id ) ;
33+ localStorage . setItem ( 'bookmarks' , JSON . stringify ( updated ) ) ;
34+ setBookmarks ( updated ) ;
35+ } ;
36+
37+ const filteredBookmarks = bookmarks . filter ( bookmark => {
38+ if ( activeTab === 'modules' ) return ! bookmark . id . includes ( 'topic' ) && ! bookmark . id . includes ( 'video' ) ;
39+ if ( activeTab === 'topics' ) return bookmark . id . includes ( 'topic' ) ;
40+ if ( activeTab === 'videos' ) return bookmark . id . includes ( 'video' ) ;
41+ return true ;
42+ } ) ;
43+
44+ return (
45+ < div className = "h-screen max-w-4xl mx-auto px-4 py-8" >
46+ < h1 className = "text-2xl font-bold mb-6 dark:text-white" > Your Bookmarks</ h1 >
47+
48+ < div className = "flex border-b border-gray-200 dark:border-gray-700 mb-6" >
49+ < button
50+ onClick = { ( ) => setActiveTab ( 'modules' ) }
51+ className = { `px-4 py-2 font-medium text-sm ${ activeTab === 'modules' ? 'text-primary border-b-2 border-primary' : 'text-gray-500 dark:text-gray-400' } ` }
52+ >
53+ Modules
54+ </ button >
55+ < button
56+ onClick = { ( ) => setActiveTab ( 'topics' ) }
57+ className = { `px-4 py-2 font-medium text-sm ${ activeTab === 'topics' ? 'text-primary border-b-2 border-primary' : 'text-gray-500 dark:text-gray-400' } ` }
58+ >
59+ Topics
60+ </ button >
61+ < button
62+ onClick = { ( ) => setActiveTab ( 'videos' ) }
63+ className = { `px-4 py-2 font-medium text-sm ${ activeTab === 'videos' ? 'text-primary border-b-2 border-primary' : 'text-gray-500 dark:text-gray-400' } ` }
64+ >
65+ Videos
66+ </ button >
67+ </ div >
68+
69+ { filteredBookmarks . length === 0 ? (
70+ < p className = "text-gray-600 dark:text-gray-400" >
71+ No { activeTab } bookmarked yet
72+ </ p >
73+ ) : (
74+ < div className = "space-y-4" >
75+ { filteredBookmarks . map ( ( item ) => (
76+ < div
77+ key = { item . id }
78+ className = "p-4 border rounded-lg hover:bg-[#585859] hover:text-white dark:border-gray-700 transition-colors"
79+ >
80+ < div className = "flex justify-between items-center" >
81+ < div >
82+ < Link href = "/" className = "block" >
83+ < h3 className = "font-medium dark:text-white hover:underline" >
84+ { item . title }
85+ </ h3 >
86+ </ Link >
87+ < p className = "text-sm text-gray-400 dark:text-gray-400" >
88+ { item . subject } { item . module && `• Module ${ item . module } ` }
89+ </ p >
90+ { activeTab === 'videos' && (
91+ < p className = "text-xs text-gray-400 mt-1" > Video</ p >
92+ ) }
93+ </ div >
94+ < div className = "flex items-center gap-2" >
95+ { activeTab === 'videos' && (
96+ < ChevronDown
97+ onClick = { ( ) => toggleActive ( item . id ) }
98+ className = { `w-4 h-4 text-gray-500 dark:text-gray-400 transition-transform duration-200 cursor-pointer ${
99+ activeBookmarkId === item . id ? 'rotate-180' : ''
100+ } `}
101+ />
102+ ) }
103+ < button
104+ onClick = { ( ) => removeBookmark ( item . id ) }
105+ className = "text-red-500 hover:text-red-700 dark:hover:text-red-400 p-1"
106+ >
107+ Remove
108+ </ button >
109+ </ div >
110+ </ div >
111+
112+ { activeTab === 'videos' && activeBookmarkId === item . id && item . url && (
113+ < div className = "mt-3" >
114+ < div className = "aspect-video" >
115+ < iframe
116+ width = "100%"
117+ height = "100%"
118+ src = { `${ item . url } ?enablejsapi=1` }
119+ title = { item . title }
120+ allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
121+ allowFullScreen
122+ className = "rounded-lg"
123+ > </ iframe >
124+ </ div >
125+ </ div >
126+ ) }
127+ </ div >
128+ ) ) }
129+ </ div >
130+ ) }
131+ </ div >
132+ ) ;
133+ }
0 commit comments