- Timestamp:
- 03/24/26 22:13:36 (3 months ago)
- Branches:
- main
- Children:
- 7fbb91c
- Parents:
- acf690c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
chapterx-frontend/src/pages/reading-list/ReadingListPage.tsx
racf690c r73b69b2 12 12 const navigate = useNavigate() 13 13 const { currentUser } = useAuthStore() 14 const { readingLists, fetchReadingLists, createReadingList, deleteReadingList, removeStoryFromList } = useStoryStore() 14 const { readingLists, fetchUserReadingLists, createReadingList, deleteReadingList, removeStoryFromList } = useStoryStore() 15 const [fetching, setFetching] = useState(false) 16 const [confirmRemove, setConfirmRemove] = useState<{ listId: number; storyId: number; title: string } | null>(null) 15 17 16 18 useEffect(() => { 17 fetchReadingLists() 18 }, []) 19 if (!currentUser) return 20 setFetching(true) 21 fetchUserReadingLists(currentUser.user_id).finally(() => setFetching(false)) 22 }, [currentUser?.user_id]) 19 23 const { addToast } = useUIStore() 20 24 const [createOpen, setCreateOpen] = useState(false) … … 33 37 } 34 38 35 const myLists = readingLists.filter(l => l.user_id === currentUser .user_id)39 const myLists = readingLists.filter(l => l.user_id === currentUser!.user_id) 36 40 37 41 const handleCreate = async () => { … … 73 77 </div> 74 78 75 {myLists.length === 0 ? ( 79 {fetching ? ( 80 <div className="flex flex-col items-center py-20 text-slate-500"> 81 <BookOpen size={48} className="mb-4 opacity-40 animate-pulse" /> 82 <p className="text-sm">Loading your lists...</p> 83 </div> 84 ) : myLists.length === 0 ? ( 76 85 <div className="flex flex-col items-center py-20 text-slate-500"> 77 86 <BookOpen size={48} className="mb-4 opacity-40" /> … … 124 133 <div className="space-y-2"> 125 134 {list.stories.slice(0, 4).map(item => ( 126 <div key={item.item_id} className="flex items-center gap- 3 p-2 rounded-lg hover:bg-slate-700/50 group">127 <div className="flex-1 min-w-0 ">135 <div key={item.item_id} className="flex items-center gap-2 p-2 rounded-lg hover:bg-slate-700/50"> 136 <div className="flex-1 min-w-0 overflow-hidden"> 128 137 <button 129 138 onClick={() => navigate(`/story/${item.story_id}`)} 130 className="text-white text-sm font-medium hover:text-indigo-300 transition-colors truncate block text-left "139 className="text-white text-sm font-medium hover:text-indigo-300 transition-colors truncate block text-left w-full" 131 140 > 132 141 {item.story_title} 133 142 </button> 134 143 <div className="flex items-center gap-2 mt-0.5"> 135 <span className="text-slate-500 text-xs ">by {item.author_username}</span>144 <span className="text-slate-500 text-xs truncate">by {item.author_username}</span> 136 145 {item.genres.slice(0, 1).map(g => <GenreBadge key={g} genre={g} />)} 137 146 </div> 138 147 </div> 139 148 <button 140 onClick={() => removeStoryFromList(list.list_id, item.story_id)} 141 className="opacity-0 group-hover:opacity-100 text-slate-500 hover:text-rose-400 transition-all" 149 onClick={() => setConfirmRemove({ listId: list.list_id, storyId: item.story_id, title: item.story_title })} 150 className="flex-shrink-0 text-slate-500 hover:text-rose-400 hover:bg-rose-400/10 transition-all p-1.5 rounded-lg" 151 title="Remove from list" 142 152 > 143 < Xsize={14} />153 <Trash2 size={14} /> 144 154 </button> 145 155 </div> … … 165 175 )} 166 176 177 {/* Confirm remove modal */} 178 <Modal isOpen={!!confirmRemove} onClose={() => setConfirmRemove(null)} title="Remove Story"> 179 <div className="space-y-4"> 180 <p className="text-slate-300 text-sm"> 181 Are you sure you want to remove <span className="text-white font-medium">"{confirmRemove?.title}"</span> from this list? 182 </p> 183 <div className="flex gap-3"> 184 <Button variant="secondary" className="flex-1" onClick={() => setConfirmRemove(null)}>Cancel</Button> 185 <Button variant="danger" className="flex-1" onClick={async () => { 186 if (!confirmRemove) return 187 await removeStoryFromList(confirmRemove.listId, confirmRemove.storyId) 188 addToast('Story removed from list', 'info') 189 setConfirmRemove(null) 190 }}>Remove</Button> 191 </div> 192 </div> 193 </Modal> 194 167 195 {/* Create modal */} 168 196 <Modal isOpen={createOpen} onClose={() => setCreateOpen(false)} title="Create Reading List">
Note:
See TracChangeset
for help on using the changeset viewer.
