fix(front): [WIP] favourites page

This commit is contained in:
ArneBo 2025-01-06 18:06:40 +01:00 committed by upsiflu
parent 13af438026
commit 404b6f5f7a
4 changed files with 107 additions and 108 deletions

View File

@ -12,6 +12,8 @@ import axios from 'axios'
import TrackMobileRow from '~/components/audio/track/MobileRow.vue'
import Pagination from '~/components/vui/Pagination.vue'
import TrackRow from '~/components/audio/track/Row.vue'
import Input from '~/components/ui/Input.vue'
import Spacer from '~/components/ui/layout/Spacer.vue'
import useErrorHandler from '~/composables/useErrorHandler'
@ -91,7 +93,8 @@ const store = useStore()
const labels = computed(() => ({
title: t('components.audio.track.Table.table.header.title'),
album: t('components.audio.track.Table.table.header.album'),
artist: t('components.audio.track.Table.table.header.artist')
artist: t('components.audio.track.Table.table.header.artist'),
searchPlaceholder: t('components.library.Podcasts.placeholder.search'),
}))
const isLoading = ref(false)
@ -144,11 +147,14 @@ const updatePage = (page: number) => {
<template>
<div>
<!-- Show the search bar if search is true -->
<inline-search-bar
<Input search
v-if="search"
v-model="query"
@search="performSearch"
autofocus
:placeholder="labels.searchPlaceholder"
/>
<Spacer v-if="search" />
<!-- Add a header if needed -->

View File

@ -2,6 +2,7 @@
import { useI18n } from 'vue-i18n'
import Button from '~/components/ui/Button.vue'
import Alert from '~/components/ui/Alert.vue'
interface Events {
(e: 'refresh'): void
@ -20,11 +21,11 @@ withDefaults(defineProps<Props>(), {
</script>
<template>
<div class="ui small placeholder segment component-placeholder component-empty-state">
<Alert blue style="text-align: center;">
<h4 class="ui header">
<div class="content">
<slot name="title">
<i class="search icon" />
<i class="bi bi-search" style="margin-right: 8px;" />
{{ t('components.common.EmptyState.header.noResults') }}
</slot>
</div>
@ -32,11 +33,12 @@ withDefaults(defineProps<Props>(), {
<div class="inline center aligned text">
<slot />
<Button
primary
v-if="refresh"
@click="emit('refresh')"
>
{{ t('components.common.EmptyState.button.refresh') }}
</Button>
</div>
</div>
</Alert>
</template>

View File

@ -10,11 +10,17 @@ import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store'
import axios from 'axios'
import $ from 'jquery'
import TrackTable from '~/components/audio/track/Table.vue'
import RadioButton from '~/components/radios/Button.vue'
import Pagination from '~/components/vui/Pagination.vue'
import Pagination from '~/components/ui/Pagination.vue'
import Layout from '~/components/ui/Layout.vue'
import Section from '~/components/ui/layout/Section.vue'
import Spacer from '~/components/ui/layout/Spacer.vue'
import Button from '~/components/ui/Button.vue'
import Link from '~/components/ui/Link.vue'
import Alert from '~/components/ui/Alert.vue'
import Loader from '~/components/ui/Loader.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'
@ -94,8 +100,6 @@ onOrderingUpdate(() => {
fetchFavorites()
})
onMounted(() => $('.ui.dropdown').dropdown())
const { t } = useI18n()
const labels = computed(() => ({
title: t('components.favorites.List.title')
@ -105,119 +109,105 @@ const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value]
</script>
<template>
<main
<Layout main stack
v-title="labels.title"
class="main"
>
<section class="ui vertical center aligned stripe segment">
<div :class="['ui', { 'active': isLoading }, 'inverted', 'dimmer']">
<div class="ui text loader">
{{ t('components.favorites.List.loader.loading') }}
</div>
</div>
<h2
v-if="results"
class="ui center aligned icon header"
>
<i class="circular inverted heart pink icon" />
{{ t('components.favorites.List.header.favorites', store.state.favorites.count) }}
</h2>
<radio-button
<Section
v-if="results"
:h1="t('components.favorites.List.title', store.state.favorites.count)"
>
<RadioButton
v-if="store.state.favorites.count > 0"
type="favorites"
/>
</section>
<section
v-if="store.state.favorites.count > 0"
class="ui vertical stripe segment"
>
<div :class="['ui', { 'loading': isLoading }, 'form']">
<div class="fields">
<div class="field">
<label for="favorites-ordering">
{{ t('components.favorites.List.ordering.label') }}
</label>
<select
id="favorites-ordering"
v-model="ordering"
class="ui dropdown"
>
<option
v-for="option in orderingOptions"
:key="option[0]"
:value="option[0]"
>
{{ sharedLabels.filters[option[1]] }}
</option>
</select>
</div>
<div class="field">
<label for="favorites-ordering-direction">
{{ t('components.favorites.List.ordering.direction.label') }}
</label>
<select
id="favorites-ordering-direction"
v-model="orderingDirection"
class="ui dropdown"
>
<option value="+">
{{ t('components.favorites.List.ordering.direction.ascending') }}
</option>
<option value="-">
{{ t('components.favorites.List.ordering.direction.descending') }}
</option>
</select>
</div>
<div class="field">
<label for="favorites-results">
{{ t('components.favorites.List.pagination.results') }}
</label>
<select
id="favorites-results"
v-model="paginateBy"
class="ui dropdown"
>
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</div>
</Section>
<section class="center">
<div :class="['ui', { 'active': isLoading }, 'inverted', 'dimmer']">
<div v-if="isLoading" class="ui text loader">
{{ t('components.favorites.List.loader.loading') }}
</div>
<Loader v-if="isLoading"/>
</div>
<track-table
</section>
<Layout
v-if="store.state.favorites.count > 0"
form
stack
:class="['ui', { 'loading': isLoading }, 'form']"
>
<Layout flex style="justify-content: flex-end;">
<select
id="favorites-ordering"
v-model="ordering"
:label="t('components.favorites.List.ordering.label')"
class="dropdown"
>
<option
v-for="option in orderingOptions"
:key="option[0]"
:value="option[0]"
>
{{ sharedLabels.filters[option[1]] }}
</option>
</select>
<select
id="favorites-ordering-direction"
:label="t('components.favorites.List.ordering.direction.label')"
v-model="orderingDirection"
class="dropdown"
>
<option value="+">
{{ t('components.favorites.List.ordering.direction.ascending') }}
</option>
<option value="-">
{{ t('components.favorites.List.ordering.direction.descending') }}
</option>
</select>
<select
id="favorites-results"
v-model="paginateBy"
:label="t('components.favorites.List.pagination.results')"
class="dropdown"
>
<option
v-for="opt in paginateOptions"
:key="opt"
:value="opt"
>
{{ opt }}
</option>
</select>
</Layout>
<TrackTable
v-if="results"
:search="true"
:show-artist="true"
:show-album="true"
:tracks="results"
/>
<div class="ui center aligned basic segment">
<pagination
v-if="results && count > paginateBy"
v-model:current="page"
:paginate-by="paginateBy"
:total="count"
/>
</div>
</section>
<div
<Spacer grow />
<Pagination
v-if="result && result.count > paginateBy"
:page="page"
:pages="Math.ceil((result?.results.length || 0)/paginateBy)"
/>
</Layout>
<Alert blue style="text-align: center;"
v-else
class="ui placeholder segment"
>
<div class="ui icon header">
<i class="broken heart icon" />
{{ t('components.favorites.List.empty.noFavorites') }}
</div>
<router-link
:to="'/library'"
class="ui success labeled icon button"
<i class="bi bi-heartbreak-fill" style="font-size: 100px;" />
<Spacer />
{{ t('components.favorites.List.empty.noFavorites') }}
<Spacer size="40"/>
<Link
to="/library"
solid
primary
icon="bi-headphones"
align-self="center"
>
<i class="headphones icon" />
{{ t('components.favorites.List.link.library') }}
</router-link>
</div>
</main>
</Link>
</Alert>
</Layout>
</template>

View File

@ -25,6 +25,7 @@ import Input from '~/components/ui/Input.vue'
import Alert from '~/components/ui/Alert.vue'
import Spacer from '~/components/ui/layout/Spacer.vue'
import Pills from '~/components/ui/Pills.vue'
import Loader from '~/components/ui/Loader.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels'
import useOrdering from '~/composables/navigation/useOrdering'