89 lines
3.8 KiB
Vue
89 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import PlaylistsNotFound from '@/components/internal/playlists/select/PlaylistsNotFound.vue';
|
|
import { usePlaylists } from '@/composeables/api/playlist-controller/playlist-controller';
|
|
import { ChevronsUpDown, Music4, Plus } from 'lucide-vue-next';
|
|
import PlaylistCreateDialog from './playlists/select/PlaylistCreateDialog.vue';
|
|
import { useCurrentPlaylistStore } from '~/stores/use-current-playlist-store';
|
|
import { useSidebar } from '../ui/sidebar';
|
|
|
|
const {
|
|
open: sidebarOpen,
|
|
} = useSidebar()
|
|
|
|
const { isLoading, isError, error, data } = usePlaylists();
|
|
|
|
const currentPlaylistStore = useCurrentPlaylistStore();
|
|
|
|
watch(data, (value) => {
|
|
const newValue = value?.data[0];
|
|
if (currentPlaylistStore.id === -1 && newValue) {
|
|
currentPlaylistStore.load(newValue);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Select v-model="currentPlaylistStore.id">
|
|
<div v-if="sidebarOpen" class="hover:bg-sidebar-muted cursor-pointer rounded-md select-none">
|
|
<SelectCustomTrigger class="w-full flex p-2 gap-2 items-center">
|
|
<Frame borderRadius="round" background="primary" padding="dense" margin="none">
|
|
<Music4 class="text-primary-foreground" :size="24" />
|
|
</Frame>
|
|
<div class="overflow-hidden text-start">
|
|
<Skeleton v-if="isLoading" class="w-32 h-5 rounded-full" />
|
|
<h4 v-else-if="data" class="text-xl font-semibold tracking-tight truncate">
|
|
<!-- TODO: i18n -->
|
|
{{data.data.find(playlist => playlist.id === currentPlaylistStore.id)?.title ||
|
|
'No playlist selected'}}
|
|
</h4>
|
|
<p class="text-sm text-muted-foreground">
|
|
<!-- TODO: Actual track count -->
|
|
11 track(s)
|
|
</p>
|
|
</div>
|
|
<div class="ml-auto">
|
|
<ChevronsUpDown />
|
|
</div>
|
|
</SelectCustomTrigger>
|
|
</div>
|
|
<div v-if="!sidebarOpen">
|
|
<div class="flex items-center">
|
|
<SelectCustomTrigger as-child>
|
|
<Frame borderRadius="round" background="primary" padding="dense" margin="none">
|
|
<Music4 class="text-primary-foreground" :size="24" />
|
|
</Frame>
|
|
</SelectCustomTrigger>
|
|
</div>
|
|
</div>
|
|
<SelectContent align="start" side="right" :sideOffset="4">
|
|
<div class="w-full">
|
|
<div v-if="isLoading">
|
|
<Spinner />
|
|
</div>
|
|
<div v-else-if="isError">
|
|
<SelectLabel>{{ error }}</SelectLabel>
|
|
</div>
|
|
<div v-else-if="data" class="w-full">
|
|
<SelectLabel>Playlists</SelectLabel>
|
|
<SelectSeparator />
|
|
<SelectGroup>
|
|
<SelectItem v-for="item in data.data" :key="item.id" :value="item.id || -1">
|
|
<span>{{ item.title }}</span>
|
|
</SelectItem>
|
|
<PlaylistsNotFound v-if="data.data.length === 0" />
|
|
</SelectGroup>
|
|
<SelectSeparator v-if="data.data.length > 0" />
|
|
<PlaylistCreateDialog v-if="data.data.length > 0">
|
|
<template #trigger>
|
|
<Button variant="outline" size="icon" class="w-full">
|
|
<Plus />
|
|
Create playlist
|
|
</Button>
|
|
</template>
|
|
</PlaylistCreateDialog>
|
|
</div>
|
|
</div>
|
|
</SelectContent>
|
|
</Select>
|
|
</template>
|