feat: add delete functionality for playlists with confirmation and error handling
This commit is contained in:
@@ -5,16 +5,17 @@ import type { Playlist } from '@/lib/api/services/playlists'
|
|||||||
import { formatDateDistanceToNow } from '@/utils/format-date'
|
import { formatDateDistanceToNow } from '@/utils/format-date'
|
||||||
import { formatDuration } from '@/utils/format-duration'
|
import { formatDuration } from '@/utils/format-duration'
|
||||||
import { cn } from '@/lib/utils'
|
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 {
|
interface PlaylistRowProps {
|
||||||
playlist: Playlist
|
playlist: Playlist
|
||||||
onEdit: (playlist: Playlist) => void
|
onEdit: (playlist: Playlist) => void
|
||||||
onSetCurrent: (playlist: Playlist) => void
|
onSetCurrent: (playlist: Playlist) => void
|
||||||
onFavoriteToggle?: (playlistId: number, isFavorited: boolean) => 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 = () => {
|
const handleFavoriteToggle = () => {
|
||||||
if (onFavoriteToggle) {
|
if (onFavoriteToggle) {
|
||||||
onFavoriteToggle(playlist.id, !playlist.is_favorited)
|
onFavoriteToggle(playlist.id, !playlist.is_favorited)
|
||||||
@@ -121,6 +122,17 @@ export function PlaylistRow({ playlist, onEdit, onSetCurrent, onFavoriteToggle }
|
|||||||
<Play className="h-4 w-4" />
|
<Play className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{onDelete && !playlist.is_main && playlist.is_deletable && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => onDelete(playlist)}
|
||||||
|
className="h-8 w-8 p-0 text-destructive hover:text-destructive"
|
||||||
|
title={`Delete "${playlist.name}"`}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ interface PlaylistTableProps {
|
|||||||
onEdit: (playlist: Playlist) => void
|
onEdit: (playlist: Playlist) => void
|
||||||
onSetCurrent: (playlist: Playlist) => void
|
onSetCurrent: (playlist: Playlist) => void
|
||||||
onFavoriteToggle?: (playlistId: number, isFavorited: boolean) => 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 (
|
return (
|
||||||
<div className="rounded-md border">
|
<div className="rounded-md border">
|
||||||
<Table>
|
<Table>
|
||||||
@@ -39,6 +40,7 @@ export function PlaylistTable({ playlists, onEdit, onSetCurrent, onFavoriteToggl
|
|||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
onSetCurrent={onSetCurrent}
|
onSetCurrent={onSetCurrent}
|
||||||
onFavoriteToggle={onFavoriteToggle}
|
onFavoriteToggle={onFavoriteToggle}
|
||||||
|
onDelete={onDelete}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
|||||||
@@ -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 = () => {
|
const renderContent = () => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <PlaylistsLoading />
|
return <PlaylistsLoading />
|
||||||
@@ -209,6 +256,7 @@ export function PlaylistsPage() {
|
|||||||
onEdit={handleEditPlaylist}
|
onEdit={handleEditPlaylist}
|
||||||
onSetCurrent={handleSetCurrent}
|
onSetCurrent={handleSetCurrent}
|
||||||
onFavoriteToggle={handleFavoriteToggle}
|
onFavoriteToggle={handleFavoriteToggle}
|
||||||
|
onDelete={handleDeletePlaylist}
|
||||||
/>
|
/>
|
||||||
<AppPagination
|
<AppPagination
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
|
|||||||
Reference in New Issue
Block a user