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' type Route = { name: RouteRecordName params?: RouteParams } type MenuItem = { title: string route: Route requiresAdmin?: boolean } export type MenuItemCollection = { title: string items: MenuItem[] } type MenuItemCollectionGenerator = ( route: RouteLocationNormalizedLoaded, ) => 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: RouteLocationNormalizedLoaded) { 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: RouteLocationNormalizedLoaded) { if (!route.params.showId) return const showId = parseInt(route.params.showId as string) 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 }, }, { title: t('navigation.show.basicData'), route: { name: 'show-basic-data', params: route.params }, }, ], } } function useNavigationData(...menuCollectionGenerators: MenuItemCollectionGenerator[]) { const route = useRoute() const menuItemCollections = ref<MenuItemCollection[]>([]) watch( [route, () => route.params, () => route.name], async () => { const result: MenuItemCollection[] = [] for (const generator of menuCollectionGenerators) { try { for await (const collection of generator(route)) { result.push(collection) } } catch (e) { // pass } } menuItemCollections.value = result }, { immediate: true }, ) return shallowReadonly(menuItemCollections) } export function useMainNavigationData() { return useNavigationData(getMainNavigation, getEpisodeContextMenu, getShowContextMenu) }