From dc1124dff640a2c4ca0b418c27fab99066f60020 Mon Sep 17 00:00:00 2001 From: JSC Date: Sun, 21 Sep 2025 18:32:33 +0200 Subject: [PATCH] feat: add delete functionality for playlists with confirmation and error handling --- src/components/playlists/PlaylistRow.tsx | 16 ++++++- src/components/playlists/PlaylistTable.tsx | 4 +- src/pages/PlaylistsPage.tsx | 54 ++++++++++++++++++++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/components/playlists/PlaylistRow.tsx b/src/components/playlists/PlaylistRow.tsx index ea0511f..0913d96 100644 --- a/src/components/playlists/PlaylistRow.tsx +++ b/src/components/playlists/PlaylistRow.tsx @@ -5,16 +5,17 @@ import type { Playlist } from '@/lib/api/services/playlists' import { formatDateDistanceToNow } from '@/utils/format-date' import { formatDuration } from '@/utils/format-duration' import { cn } from '@/lib/utils' -import { Calendar, Clock, Edit, Heart, Music, Play, User } from 'lucide-react' +import { Calendar, Clock, Edit, Heart, Music, Play, Trash2, User } from 'lucide-react' interface PlaylistRowProps { playlist: Playlist onEdit: (playlist: Playlist) => void onSetCurrent: (playlist: Playlist) => void onFavoriteToggle?: (playlistId: number, isFavorited: boolean) => void + onDelete?: (playlist: Playlist) => void } -export function PlaylistRow({ playlist, onEdit, onSetCurrent, onFavoriteToggle }: PlaylistRowProps) { +export function PlaylistRow({ playlist, onEdit, onSetCurrent, onFavoriteToggle, onDelete }: PlaylistRowProps) { const handleFavoriteToggle = () => { if (onFavoriteToggle) { onFavoriteToggle(playlist.id, !playlist.is_favorited) @@ -121,6 +122,17 @@ export function PlaylistRow({ playlist, onEdit, onSetCurrent, onFavoriteToggle } )} + {onDelete && !playlist.is_main && playlist.is_deletable && ( + + )} diff --git a/src/components/playlists/PlaylistTable.tsx b/src/components/playlists/PlaylistTable.tsx index 234c317..dd9e440 100644 --- a/src/components/playlists/PlaylistTable.tsx +++ b/src/components/playlists/PlaylistTable.tsx @@ -13,9 +13,10 @@ interface PlaylistTableProps { onEdit: (playlist: Playlist) => void onSetCurrent: (playlist: Playlist) => void onFavoriteToggle?: (playlistId: number, isFavorited: boolean) => void + onDelete?: (playlist: Playlist) => void } -export function PlaylistTable({ playlists, onEdit, onSetCurrent, onFavoriteToggle }: PlaylistTableProps) { +export function PlaylistTable({ playlists, onEdit, onSetCurrent, onFavoriteToggle, onDelete }: PlaylistTableProps) { return (
@@ -39,6 +40,7 @@ export function PlaylistTable({ playlists, onEdit, onSetCurrent, onFavoriteToggl onEdit={onEdit} onSetCurrent={onSetCurrent} onFavoriteToggle={onFavoriteToggle} + onDelete={onDelete} /> ))} diff --git a/src/pages/PlaylistsPage.tsx b/src/pages/PlaylistsPage.tsx index 9b21757..61c68a4 100644 --- a/src/pages/PlaylistsPage.tsx +++ b/src/pages/PlaylistsPage.tsx @@ -165,7 +165,7 @@ export function PlaylistsPage() { await favoritesService.removePlaylistFavorite(playlistId) toast.success('Removed from favorites') } - + // Update the playlist in the local state setPlaylists(prevPlaylists => prevPlaylists.map(playlist => @@ -173,8 +173,8 @@ export function PlaylistsPage() { ? { ...playlist, is_favorited: shouldFavorite, - favorite_count: shouldFavorite - ? playlist.favorite_count + 1 + favorite_count: shouldFavorite + ? playlist.favorite_count + 1 : Math.max(0, playlist.favorite_count - 1), } : playlist, @@ -189,6 +189,53 @@ export function PlaylistsPage() { } } + const handleDeletePlaylist = async (playlist: Playlist) => { + // Protect main playlist from deletion + if (playlist.is_main) { + toast.error('The main playlist cannot be deleted') + return + } + + // Check if playlist is deletable + if (!playlist.is_deletable) { + toast.error('This playlist cannot be deleted') + return + } + + // Confirm deletion + const confirmMessage = `Are you sure you want to delete the playlist "${playlist.name}"?${ + playlist.sound_count > 0 + ? `\n\nThis playlist contains ${playlist.sound_count} sound${playlist.sound_count !== 1 ? 's' : ''}. The sounds will not be deleted, only removed from this playlist.` + : '' + }\n\nThis action cannot be undone.` + + if (!confirm(confirmMessage)) { + return + } + + try { + await playlistsService.deletePlaylist(playlist.id) + toast.success(`Playlist "${playlist.name}" deleted successfully`) + + // Remove the deleted playlist from the local state + setPlaylists(prevPlaylists => + prevPlaylists.filter(p => p.id !== playlist.id) + ) + + // Update total count + setTotalCount(prev => prev - 1) + + // If current page is now empty and not the first page, go to previous page + const remainingOnCurrentPage = playlists.length - 1 + if (remainingOnCurrentPage === 0 && currentPage > 1) { + setCurrentPage(currentPage - 1) + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Failed to delete playlist' + toast.error(errorMessage) + } + } + const renderContent = () => { if (loading) { return @@ -209,6 +256,7 @@ export function PlaylistsPage() { onEdit={handleEditPlaylist} onSetCurrent={handleSetCurrent} onFavoriteToggle={handleFavoriteToggle} + onDelete={handleDeletePlaylist} />