chore(front): [WIP] new toplevel channels page

This commit is contained in:
ArneBo 2025-02-17 11:25:44 +01:00
parent 4a9f2f99ae
commit b1ac6612fd
3 changed files with 202 additions and 1 deletions

View File

@ -145,7 +145,7 @@ const logoUrl = computed(() => store.state.auth.authenticated ? 'library.index'
{{ t('components.Sidebar.link.artists') }}
</Link>
<Link to="/subscriptions"
<Link to="/channels"
ghost
full
align-text="left"

View File

@ -124,6 +124,12 @@ export default [
}
]
},
{
path: 'channels',
name: 'channels',
component: () => import('~/views/channels/List.vue'),
props: route => ({ defaultQuery: route.query.q })
},
{
path: 'subscriptions',
name: 'subscriptions',

View File

@ -0,0 +1,195 @@
<script setup lang="ts">
import type { Channel } from '~/types'
import { useI18n } from 'vue-i18n'
import { ref, computed } from 'vue'
import axios from 'axios'
import ChannelsWidget from '~/components/audio/ChannelsWidget.vue'
import RemoteSearchForm from '~/components/RemoteSearchForm.vue'
import Layout from '~/components/ui/Layout.vue'
import Header from '~/components/ui/Header.vue'
import Modal from '~/components/ui/Modal.vue'
import Button from '~/components/ui/Button.vue'
import useErrorHandler from '~/composables/useErrorHandler'
interface Props {
defaultQuery?: string
}
const props = withDefaults(defineProps<Props>(), {
defaultQuery: ''
})
const query = ref(props.defaultQuery)
const widgetKey = ref(new Date().toLocaleString())
const { t } = useI18n()
const labels = computed(() => ({
searchPlaceholder: t('views.channels.SubscriptionsList.placeholder.search')
}))
const previousPage = ref()
const nextPage = ref()
const channels = ref([] as Channel[])
const count = ref(0)
const isLoading = ref(false)
const fetchData = async () => {
isLoading.value = true
try {
const response = await axios.get('channels/', { params: { q: query.value } })
previousPage.value = response.data.previous
nextPage.value = response.data.next
channels.value.push(...response.data.results)
count.value = response.data.count
} catch (error) {
useErrorHandler(error as Error)
}
isLoading.value = false
}
fetchData()
const reloadWidget = () => (widgetKey.value = new Date().toLocaleString())
const showSubscribeModal = ref(false)
const showCreateModal = ref(false)
</script>
<template>
<Layout stack main
>
<Header
:h1="t('views.channels.SubscriptionsList.title')"
:action="{
text: t('views.channels.SubscriptionsList.link.addNew'),
onClick: ()=> showSubscribeModal = true
}"
icon="bi-plus"
primary
/>
<Modal
v-model="showSubscribeModal"
:title="t('views.channels.SubscriptionsList.modal.subscription.header')"
class="tiny"
>
<div
ref="modalContent"
class="scrolling content"
>
<remote-search-form
initial-type="both"
:show-submit="false"
:standalone="false"
:redirect="true"
@subscribed="showSubscribeModal = false; reloadWidget()"
/>
</div>
<template #actions>
<Button
secondary
@click="showSubscribeModal = false"
>
{{ t('views.channels.SubscriptionsList.button.cancel') }}
</Button>
<Button
form="remote-search"
type="submit"
icon="bi-bookmark-check-fill"
primary
>
{{ t('views.channels.SubscriptionsList.button.subscribe') }}
</Button>
</template>
</Modal>
<inline-search-bar
v-model="query"
:placeholder="labels.searchPlaceholder"
@search="reloadWidget"
/>
<channels-widget
:key="widgetKey"
:limit="50"
:show-modification-date="true"
:filters="{q: query, ordering: '-name'}"
/>
<!-- TODO: Translations -->
<Header
:h1="t('views.auth.ProfileOverview.header.channels')"
:action="{
text: t('views.channels.SubscriptionsList.link.addNew'),
onClick: ()=> showCreateModal = true
}"
icon="bi-plus"
primary
/>
<channels-widget
:show-modification-date="true"
:limit="12"
:filters="{ordering: '-creation_date', external: 'true'}"
>
<template #title>
{{ t('components.library.Home.header.newChannels') }}
</template>
</channels-widget>
</Layout>
<Modal v-model="showCreateModal"
:title="t(`views.auth.ProfileOverview.modal.createChannel.${
step === 1 ?
'header' :
category === 'podcast' ?
'podcast.header'
:
'artist.header'
}`)"
>
<div
ref="modalContent"
class="scrolling content"
>
<channel-form
ref="createForm"
:object="null"
:step="step"
@loading="loading = $event"
@submittable="submittable = $event"
@category="category = $event"
@errored="modalContent.scrollTop = 0"
@created="router.push({name: 'channels.detail', params: {id: $event.actor.preferred_username}})"
/>
</div>
<template #actions>
<Button secondary
v-if="step === 1"
autofocus
>
{{ t('views.auth.ProfileOverview.button.cancel') }}
</Button>
<Button secondary
v-if="step > 1"
@click.stop.prevent="step -= 1"
>
{{ t('views.auth.ProfileOverview.button.previous') }}
</Button>
<Button primary
v-if="step === 1"
@click.stop.prevent="step += 1"
>
{{ t('views.auth.ProfileOverview.button.next') }}
</Button>
<Button primary
v-if="step === 2"
type="submit"
:disabled="!submittable && !loading"
:isLoading="loading"
@click.prevent.stop="createForm.submit"
>
{{ t('views.auth.ProfileOverview.button.createChannel') }}
</Button>
</template>
</Modal>
</template>