118 lines
3.7 KiB
TypeScript
118 lines
3.7 KiB
TypeScript
import { api } from '../index';
|
|
import {
|
|
toPage,
|
|
toPlaylist,
|
|
toTrack,
|
|
type RawPaged,
|
|
type RawPlaylist,
|
|
type RawTrack,
|
|
} from '../mappers';
|
|
import type { Playlist, PlaylistTrack, PaginatedResponse } from '../types';
|
|
|
|
export const playlistsApi = api.injectEndpoints({
|
|
endpoints: (build) => ({
|
|
getPlaylists: build.query<PaginatedResponse<Playlist>, void>({
|
|
query: () => '/playlists',
|
|
transformResponse: (raw: RawPaged<RawPlaylist>) =>
|
|
toPage(raw, toPlaylist),
|
|
providesTags: ['Playlist'],
|
|
}),
|
|
getPlaylist: build.query<Playlist, string>({
|
|
query: (id) => `/playlists/${id}`,
|
|
transformResponse: (raw: RawPlaylist) => toPlaylist(raw),
|
|
providesTags: (_r, _e, id) => [{ type: 'Playlist', id }],
|
|
}),
|
|
getPlaylistTracks: build.query<PlaylistTrack[], string>({
|
|
query: (id) => `/playlists/${id}/tracks`,
|
|
// The backend returns plain tracks in playlist order; position/addedAt
|
|
// aren't on TrackOut, so derive position from order and default addedAt.
|
|
transformResponse: (raw: RawPaged<RawTrack>) =>
|
|
raw.items.map((r, i) => ({
|
|
...toTrack(r),
|
|
position: i,
|
|
addedAt: r.created_at,
|
|
})),
|
|
providesTags: (_r, _e, id) => [{ type: 'Playlist', id }, 'Track'],
|
|
}),
|
|
createPlaylist: build.mutation<
|
|
Playlist,
|
|
{ name: string; description?: string }
|
|
>({
|
|
query: ({ name, description }) => ({
|
|
url: '/playlists',
|
|
method: 'POST',
|
|
body: { name, description },
|
|
}),
|
|
transformResponse: (raw: RawPlaylist) => toPlaylist(raw),
|
|
invalidatesTags: ['Playlist'],
|
|
}),
|
|
updatePlaylist: build.mutation<
|
|
Playlist,
|
|
{ id: string; name?: string; description?: string }
|
|
>({
|
|
query: ({ id, name, description }) => ({
|
|
url: `/playlists/${id}`,
|
|
method: 'PATCH',
|
|
body: { name, description },
|
|
}),
|
|
transformResponse: (raw: RawPlaylist) => toPlaylist(raw),
|
|
invalidatesTags: (_r, _e, { id }) => [{ type: 'Playlist', id }],
|
|
}),
|
|
deletePlaylist: build.mutation<void, string>({
|
|
query: (id) => ({ url: `/playlists/${id}`, method: 'DELETE' }),
|
|
invalidatesTags: ['Playlist'],
|
|
}),
|
|
addTrackToPlaylist: build.mutation<
|
|
void,
|
|
{ playlistId: string; trackId: string; position?: number }
|
|
>({
|
|
query: ({ playlistId, trackId, position }) => ({
|
|
url: `/playlists/${playlistId}/tracks`,
|
|
method: 'POST',
|
|
body: { track_id: trackId, position },
|
|
}),
|
|
invalidatesTags: (_r, _e, { playlistId }) => [
|
|
{ type: 'Playlist', id: playlistId },
|
|
],
|
|
}),
|
|
removeTrackFromPlaylist: build.mutation<
|
|
void,
|
|
{ playlistId: string; trackId: string }
|
|
>({
|
|
query: ({ playlistId, trackId }) => ({
|
|
url: `/playlists/${playlistId}/tracks/${trackId}`,
|
|
method: 'DELETE',
|
|
}),
|
|
invalidatesTags: (_r, _e, { playlistId }) => [
|
|
{ type: 'Playlist', id: playlistId },
|
|
],
|
|
}),
|
|
reorderPlaylistTracks: build.mutation<
|
|
void,
|
|
{ playlistId: string; trackIds: string[] }
|
|
>({
|
|
query: ({ playlistId, trackIds }) => ({
|
|
url: `/playlists/${playlistId}/tracks/reorder`,
|
|
method: 'PUT',
|
|
body: { track_ids: trackIds },
|
|
}),
|
|
invalidatesTags: (_r, _e, { playlistId }) => [
|
|
{ type: 'Playlist', id: playlistId },
|
|
],
|
|
}),
|
|
}),
|
|
overrideExisting: false,
|
|
});
|
|
|
|
export const {
|
|
useGetPlaylistsQuery,
|
|
useGetPlaylistQuery,
|
|
useGetPlaylistTracksQuery,
|
|
useCreatePlaylistMutation,
|
|
useUpdatePlaylistMutation,
|
|
useDeletePlaylistMutation,
|
|
useAddTrackToPlaylistMutation,
|
|
useRemoveTrackFromPlaylistMutation,
|
|
useReorderPlaylistTracksMutation,
|
|
} = playlistsApi;
|