Skip to content
Snippets Groups Projects
nav.ts 3.86 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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 selectedShow = useSelectedShow()
    
      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)
    }