Newer
Older
import { RouteLocationNormalizedLoaded, RouteParams, RouteRecordName, useRoute } from 'vue-router'
import { useShowStore } from '@/stores/shows'
import { useI18n } from '@/i18n'
import { useTimeSlotStore } from '@/stores/timeslots'
import { parseISO } from 'date-fns'
import { ref, shallowReadonly, watch } from 'vue'
import { useSelectedShow } from '@/util'
import { Show } from '@/types'
type Route = {
name: RouteRecordName
params?: RouteParams
}
type MenuItem = {
title: string
route: Route
requiresAdmin?: boolean
}
export type MenuItemCollection = {
title: string
items: MenuItem[]
}
type MenuItemCollectionGeneratorOptions = {
route: RouteLocationNormalizedLoaded
selectedShow: Show | null
}
type MenuItemCollectionGenerator = (
options: MenuItemCollectionGeneratorOptions,
) => AsyncGenerator<MenuItemCollection, void, unknown>
async function* getMainNavigation() {
const { t } = useI18n()
yield {
title: t('navigation'),
items: [
{
title: t('navigation.shows'),
route: { name: 'shows' },
},
{
title: t('navigation.filesPlaylists'),
route: { name: 'files' },
},
{
title: t('navigation.calendar'),
route: { name: 'calendar' },
},
],
}
}
async function* getEpisodeContextMenu({
route,
}: MenuItemCollectionGeneratorOptions): AsyncGenerator<MenuItemCollection, void, unknown> {
if (!route.params.episodeId) return
const episodeId = parseInt(route.params.episodeId as string)
const timeslotStore = useTimeSlotStore()
const timeslot = await timeslotStore.retrieve(episodeId, { useCached: true })
if (!timeslot) return
const { t } = useI18n()
const start = parseISO(timeslot.start).toLocaleString()
yield {
title: t('navigation.episode._title', { start }),
items: [
{
title: t('navigation.episode.description'),
route: { name: 'show-episode-description', params: route.params },
},
{
title: t('navigation.episode.playlist'),
route: { name: 'show-episode-playlist', params: route.params },
},
],
}
}
async function* getShowContextMenu({
route,
selectedShow,
}: MenuItemCollectionGeneratorOptions): AsyncGenerator<MenuItemCollection, void, unknown> {
if (!route.params.showId && !selectedShow) return
const showId = route.params.showId
? parseInt(route.params.showId as string)
: (selectedShow?.id as number)
const showStore = useShowStore()
const show = await showStore.retrieve(showId, { useCached: true })
if (!show) return
const { t } = useI18n()
yield {
title: show.name,
items: [
{
title: t('navigation.show.episodes'),
route: { name: 'show-episodes', params: { ...route.params, showId: showId.toString() } },
},
{
title: t('navigation.show.basicData'),
route: { name: 'show-basic-data', params: { ...route.params, showId: showId.toString() } },
},
],
}
}
function useNavigationData(...menuCollectionGenerators: MenuItemCollectionGenerator[]) {
const route = useRoute()
const menuItemCollections = ref<MenuItemCollection[]>([])
watch(
[route, () => route.params, () => route.name, selectedShow],
async () => {
const result: MenuItemCollection[] = []
for (const generator of menuCollectionGenerators) {
try {
const collections = generator({
route,
selectedShow: selectedShow.value ?? null,
})
for await (const collection of collections) {
result.push(collection)
}
} catch (e) {
// pass
}
}
menuItemCollections.value = result
},
{ immediate: true },
)
return shallowReadonly(menuItemCollections)
}
export function useMainNavigationData() {
return useNavigationData(getMainNavigation, getEpisodeContextMenu, getShowContextMenu)
}