funkwhale/front/src/components/album/Widget.vue

123 lines
2.5 KiB
Vue

<script setup lang="ts">
import type { Album } from '~/types'
import { reactive, ref, watch } from 'vue'
import { useStore } from '~/store'
import { useI18n } from 'vue-i18n'
import axios from 'axios'
import AlbumCard from '~/components/album/Card.vue'
import Button from '~/components/ui/Button.vue'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Loader from '~/components/ui/Loader.vue'
import useErrorHandler from '~/composables/useErrorHandler'
const { t } = useI18n()
interface Props {
filters: Record<string, string | boolean>
showCount?: boolean
search?: boolean
limit?: number
}
const props = withDefaults(defineProps<Props>(), {
showCount: false,
search: false,
limit: 12
})
const store = useStore()
const query = ref('')
const albums = reactive([] as Album[])
const count = ref(0)
const nextPage = ref()
const isLoading = ref(false)
const fetchData = async (url = 'albums/') => {
isLoading.value = true
try {
const params = {
q: query.value,
...props.filters,
page_size: props.limit
}
const response = await axios.get(url, { params })
nextPage.value = response.data.next
count.value = response.data.count
albums.push(...response.data.results)
} catch (error) {
useErrorHandler(error as Error)
}
isLoading.value = false
}
const performSearch = () => {
albums.length = 0
fetchData()
}
watch(
() => store.state.moderation.lastUpdate,
() => fetchData(),
{ immediate: true }
)
</script>
<template>
<div class="album-widget">
<h2
v-if="!!$slots.title"
>
<slot name="title" />
<span
v-if="showCount"
class="ui tiny circular label"
>{{ count }}</span>
</h2>
<slot />
<inline-search-bar
v-if="search"
v-model="query"
@search="performSearch"
/>
<Loader v-if="isLoading" />
<template v-if="!isLoading && albums.length > 0">
<Layout flex>
<album-card
v-for="album in albums"
:key="album.id"
:album="album"
/>
</Layout>
</template>
<slot
v-if="!isLoading && albums.length === 0"
name="empty-state"
>
<empty-state
:refresh="true"
@refresh="fetchData"
/>
</slot>
<template v-if="nextPage">
<Spacer />
<Button
v-if="nextPage"
primary
@click="fetchData(nextPage)"
>
{{ t('components.audio.album.Widget.button.more') }}
</Button>
</template>
</div>
</template>