Replace vue-dnd-code with vue-draggable-next
This commit is contained in:
@ -1,16 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { Search } from 'lucide-vue-next'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { InputWithIcon } from '@/components/ui/input'
|
||||
import { Outline } from '@/components/ui/outline'
|
||||
import { SidebarTrigger } from '@/components/ui/sidebar'
|
||||
import MusicCard from '~/components/internal/musiccard/MusicCard.vue'
|
||||
import { DnDOperations, useDroppable } from '@vue-dnd-kit/core'
|
||||
import Draggable from '~/components/action/Draggable.vue'
|
||||
import { useCurrentPlaylistStore } from '~/stores/use-current-playlist-store'
|
||||
import { bulkReorder, getGetPlaylistTracksQueryKey } from '~/composeables/api/track-controller/track-controller'
|
||||
import { useGetPlaylistTracks } from '~/composeables/api/track-controller/track-controller'
|
||||
import { useMutation, useQueryClient } from '@tanstack/vue-query'
|
||||
import { Search } from 'lucide-vue-next'
|
||||
import { VueDraggableNext } from 'vue-draggable-next'
|
||||
import MusicCard from '~/components/internal/musiccard/MusicCard.vue'
|
||||
import type { TrackResponse } from '~/composeables/api/models'
|
||||
import { bulkReorder, getGetPlaylistTracksQueryKey, useGetPlaylistTracks } from '~/composeables/api/track-controller/track-controller'
|
||||
import { useCurrentPlaylistStore } from '~/stores/use-current-playlist-store'
|
||||
|
||||
const searchValue = ref('')
|
||||
|
||||
@ -56,23 +55,33 @@ const { mutate: reorderTracks } = useMutation({
|
||||
},
|
||||
});
|
||||
|
||||
interface MappedTrack {
|
||||
id: number;
|
||||
title: string;
|
||||
author: string;
|
||||
authorLabel: string;
|
||||
badges: string[];
|
||||
imageUrl: string | undefined;
|
||||
date: string;
|
||||
}
|
||||
|
||||
const trackCount = computed(() => playlistTracks.value?.data.length || 0)
|
||||
const mappedTracks = ref<MappedTrack[]>([])
|
||||
|
||||
const mappedTracks = computed(() => {
|
||||
watchEffect(() => {
|
||||
if (!playlistTracks.value) return []
|
||||
const tracks = playlistTracks.value.data
|
||||
|
||||
return tracks.map((track: any, index: number) => ({
|
||||
id: track.trackId || track.id,
|
||||
title: track.track?.title || track.title || 'Unknown Track',
|
||||
author: track.track?.artist?.name || track.artist || 'Unknown Artist',
|
||||
authorLabel: "Artist",
|
||||
badges: track.track?.format ? [track.track.format] : ['mp3'],
|
||||
imageUrl: track.track?.coverUrl || track.coverUrl || getDefaultImage(index),
|
||||
date: formatDate(track.addedDate || track.createdAt),
|
||||
selected: false
|
||||
}))
|
||||
const result = tracks
|
||||
.map((track: TrackResponse, index: number) => ({
|
||||
id: track.trackId!,
|
||||
title: track.title || 'Unknown Track',
|
||||
author: track.artist || 'Unknown Artist',
|
||||
authorLabel: "Artist",
|
||||
badges: ['mp3'], // TODO: badges
|
||||
imageUrl: getDefaultImage(index), // TODO: imageUrl
|
||||
date: formatDate(''), // TODO: createdAt
|
||||
}));
|
||||
mappedTracks.value = result;
|
||||
})
|
||||
|
||||
const getDefaultImage = (index: number) => {
|
||||
@ -108,34 +117,16 @@ const filteredTracks = computed(() => {
|
||||
track.author.toLowerCase().includes(searchValue.value.toLowerCase()) ||
|
||||
track.badges.some(badge => badge.toLowerCase().includes(searchValue.value.toLowerCase()))
|
||||
)
|
||||
})
|
||||
|
||||
const selectTrack = (trackId: number) => {
|
||||
mappedTracks.value.forEach(track => {
|
||||
track.selected = track.id === trackId
|
||||
})
|
||||
}
|
||||
|
||||
const { elementRef: tracksRef } = useDroppable({
|
||||
data: {
|
||||
source: mappedTracks.value,
|
||||
},
|
||||
events: {
|
||||
onDrop: (store, payload) => {
|
||||
DnDOperations.applyTransfer(store);
|
||||
if (currentPlaylistStore.id === -1) return;
|
||||
if (mappedTracks.value.length !== trackCount.value) return;
|
||||
if (mappedTracks.value.some(t => !t)) return;
|
||||
|
||||
const trackIds = mappedTracks.value?.map(t => t.id);
|
||||
reorderTracks({
|
||||
playlistId: currentPlaylistStore.id,
|
||||
trackIds,
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function onTrackOrderChange() {
|
||||
const trackIds = mappedTracks.value?.map(t => t.id);
|
||||
reorderTracks({
|
||||
playlistId: currentPlaylistStore.id,
|
||||
trackIds,
|
||||
});
|
||||
}
|
||||
|
||||
watch(() => currentPlaylistStore.id, (newId) => {
|
||||
if (newId !== -1) {
|
||||
refetch()
|
||||
@ -178,14 +169,14 @@ watch(() => currentPlaylistStore.id, (newId) => {
|
||||
</div>
|
||||
|
||||
<div v-else ref="tracksRef" class="space-y-2">
|
||||
<TransitionGroup name="list" ref="tracksRef">
|
||||
<Draggable v-for="(track, index) in filteredTracks" :key="track.id" :index="index"
|
||||
:source="mappedTracks">
|
||||
<VueDraggableNext v-model="mappedTracks" group="tracks" @change="onTrackOrderChange"
|
||||
item-key="id">
|
||||
<div v-for="track in mappedTracks" :key="track.id">
|
||||
<MusicCard :key="track.id" :title="track.title" :author="track.author"
|
||||
:authorLabel="track.authorLabel" :badges="track.badges" :imageUrl="track.imageUrl"
|
||||
:date="track.date" :selected="track.selected" @click="selectTrack(track.id)" />
|
||||
</Draggable>
|
||||
</TransitionGroup>
|
||||
:date="track.date" />
|
||||
</div>
|
||||
</VueDraggableNext>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user