feat: implement favorites functionality across playlists components

This commit is contained in:
JSC
2025-08-16 21:41:57 +02:00
parent 1027a67e37
commit ad466e2f91
6 changed files with 108 additions and 14 deletions

View File

@@ -13,6 +13,7 @@ import {
type SortOrder,
playlistsService,
} from '@/lib/api/services/playlists'
import { favoritesService } from '@/lib/api/services/favorites'
import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router'
import { toast } from 'sonner'
@@ -27,6 +28,7 @@ export function PlaylistsPage() {
const [searchQuery, setSearchQuery] = useState('')
const [sortBy, setSortBy] = useState<PlaylistSortField>('name')
const [sortOrder, setSortOrder] = useState<SortOrder>('asc')
const [showFavoritesOnly, setShowFavoritesOnly] = useState(false)
// Create playlist dialog state
const [showCreateDialog, setShowCreateDialog] = useState(false)
@@ -56,6 +58,7 @@ export function PlaylistsPage() {
search: debouncedSearchQuery.trim() || undefined,
sort_by: sortBy,
sort_order: sortOrder,
favorites_only: showFavoritesOnly,
})
setPlaylists(playlistData)
} catch (err) {
@@ -70,7 +73,7 @@ export function PlaylistsPage() {
useEffect(() => {
fetchPlaylists()
}, [debouncedSearchQuery, sortBy, sortOrder])
}, [debouncedSearchQuery, sortBy, sortOrder, showFavoritesOnly])
const handleCreatePlaylist = async () => {
if (!newPlaylist.name.trim()) {
@@ -126,6 +129,39 @@ export function PlaylistsPage() {
navigate(`/playlists/${playlist.id}/edit`)
}
const handleFavoriteToggle = async (playlistId: number, shouldFavorite: boolean) => {
try {
if (shouldFavorite) {
await favoritesService.addPlaylistFavorite(playlistId)
toast.success('Added to favorites')
} else {
await favoritesService.removePlaylistFavorite(playlistId)
toast.success('Removed from favorites')
}
// Update the playlist in the local state
setPlaylists(prevPlaylists =>
prevPlaylists.map(playlist =>
playlist.id === playlistId
? {
...playlist,
is_favorited: shouldFavorite,
favorite_count: shouldFavorite
? playlist.favorite_count + 1
: Math.max(0, playlist.favorite_count - 1),
}
: playlist,
),
)
} catch (error) {
toast.error(
`Failed to ${shouldFavorite ? 'add to' : 'remove from'} favorites: ${
error instanceof Error ? error.message : 'Unknown error'
}`,
)
}
}
const renderContent = () => {
if (loading) {
return <PlaylistsLoading />
@@ -136,7 +172,7 @@ export function PlaylistsPage() {
}
if (playlists.length === 0) {
return <PlaylistsEmpty searchQuery={searchQuery} />
return <PlaylistsEmpty searchQuery={searchQuery} showFavoritesOnly={showFavoritesOnly} />
}
return (
@@ -144,6 +180,7 @@ export function PlaylistsPage() {
playlists={playlists}
onEdit={handleEditPlaylist}
onSetCurrent={handleSetCurrent}
onFavoriteToggle={handleFavoriteToggle}
/>
)
}
@@ -167,6 +204,8 @@ export function PlaylistsPage() {
loading={loading}
error={error}
playlistCount={playlists.length}
showFavoritesOnly={showFavoritesOnly}
onFavoritesToggle={setShowFavoritesOnly}
/>
<CreatePlaylistDialog