diff --git a/src/renderer/api/controller.ts b/src/renderer/api/controller.ts index 15ef8c87..51dbb5ea 100644 --- a/src/renderer/api/controller.ts +++ b/src/renderer/api/controller.ts @@ -213,6 +213,10 @@ const updatePlaylist = async (args: UpdatePlaylistArgs) => { return (apiController('updatePlaylist') as ControllerEndpoint['updatePlaylist'])?.(args); }; +const deletePlaylist = async (args: DeletePlaylistArgs) => { + return (apiController('deletePlaylist') as ControllerEndpoint['deletePlaylist'])?.(args); +}; + const getPlaylistDetail = async (args: PlaylistDetailArgs) => { return (apiController('getPlaylistDetail') as ControllerEndpoint['getPlaylistDetail'])?.(args); }; @@ -225,6 +229,7 @@ const getPlaylistSongList = async (args: PlaylistSongListArgs) => { export const controller = { createPlaylist, + deletePlaylist, getAlbumArtistList, getAlbumDetail, getAlbumList, diff --git a/src/renderer/api/navidrome.api.ts b/src/renderer/api/navidrome.api.ts index dd57d5a3..d9d7e280 100644 --- a/src/renderer/api/navidrome.api.ts +++ b/src/renderer/api/navidrome.api.ts @@ -325,7 +325,7 @@ const updatePlaylist = async (args: UpdatePlaylistArgs): Promise, ) => { + const navigate = useNavigate(); const { playlistId } = useParams() as { playlistId: string }; const detailQuery = usePlaylistDetail({ id: playlistId }); const handlePlayQueueAdd = usePlayQueueAdd(); @@ -37,6 +41,62 @@ export const PlaylistDetailHeader = forwardRef( }); }; + const openUpdatePlaylistModal = () => { + openModal({ + children: ( + + ), + title: 'Edit playlist', + }); + }; + + const deletePlaylistMutation = useDeletePlaylist(); + + const handleDeletePlaylist = () => { + deletePlaylistMutation.mutate( + { query: { id: playlistId } }, + { + onError: (err) => { + toast.error({ + message: err.message, + title: 'Error deleting playlist', + }); + }, + onSuccess: () => { + toast.success({ + message: `${detailQuery?.data?.name} was successfully deleted`, + title: 'Playlist deleted', + }); + closeAllModals(); + navigate(AppRoute.PLAYLISTS); + }, + }, + ); + }; + + const openDeletePlaylist = () => { + openModal({ + children: ( + + Are you sure you want to delete this playlist? + + ), + title: 'Delete playlist', + }); + }; + return ( ))} - Edit playlist + + Edit playlist + + Delete playlist diff --git a/src/renderer/features/playlists/components/update-playlist-form.tsx b/src/renderer/features/playlists/components/update-playlist-form.tsx new file mode 100644 index 00000000..58102c5c --- /dev/null +++ b/src/renderer/features/playlists/components/update-playlist-form.tsx @@ -0,0 +1,84 @@ +import { Group, Stack } from '@mantine/core'; +import { useForm } from '@mantine/form'; +import { ServerType, UpdatePlaylistBody, UpdatePlaylistQuery } from '/@/renderer/api/types'; +import { Button, Switch, TextInput, toast } from '/@/renderer/components'; +import { useUpdatePlaylist } from '/@/renderer/features/playlists/mutations/update-playlist-mutation'; +import { useCurrentServer } from '/@/renderer/store'; + +interface CreatePlaylistFormProps { + body: Partial; + onCancel: () => void; + query: UpdatePlaylistQuery; +} + +export const UpdatePlaylistForm = ({ query, body, onCancel }: CreatePlaylistFormProps) => { + const mutation = useUpdatePlaylist(); + const server = useCurrentServer(); + + const form = useForm({ + initialValues: { + comment: '', + name: '', + public: false, + rules: undefined, + ...body, + }, + }); + + const handleSubmit = form.onSubmit((values) => { + mutation.mutate( + { body: values, query }, + { + onError: (err) => { + toast.error({ message: err.message, title: 'Error updating playlist' }); + }, + onSuccess: () => { + toast.success({ message: 'Playlist updated successfully' }); + onCancel(); + }, + }, + ); + }); + + const isPublicDisplayed = server?.type === ServerType.NAVIDROME; + const isSubmitDisabled = !form.values.name || mutation.isLoading; + + return ( +
+ + + + {isPublicDisplayed && ( + + )} + + + + + +
+ ); +}; diff --git a/src/renderer/features/playlists/mutations/delete-playlist-mutation.ts b/src/renderer/features/playlists/mutations/delete-playlist-mutation.ts new file mode 100644 index 00000000..02a89343 --- /dev/null +++ b/src/renderer/features/playlists/mutations/delete-playlist-mutation.ts @@ -0,0 +1,25 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { HTTPError } from 'ky'; +import { api } from '/@/renderer/api'; +import { queryKeys } from '/@/renderer/api/query-keys'; +import { DeletePlaylistArgs, RawDeletePlaylistResponse } from '/@/renderer/api/types'; +import { MutationOptions } from '/@/renderer/lib/react-query'; +import { useCurrentServer } from '/@/renderer/store'; + +export const useDeletePlaylist = (options?: MutationOptions) => { + const queryClient = useQueryClient(); + const server = useCurrentServer(); + + return useMutation< + RawDeletePlaylistResponse, + HTTPError, + Omit, + null + >({ + mutationFn: (args) => api.controller.deletePlaylist({ ...args, server }), + onSuccess: () => { + queryClient.invalidateQueries(queryKeys.playlists.list(server?.id || '')); + }, + ...options, + }); +};