Parcel #kl5fxw0ojaab65v
Created by Anonymous
Public
Created May 7, 2025 Expires in 28 days
Loading editor...
<script setup lang="ts"> import InfoWidgetTabs from './InfoWidgetTabs.vue'; import InfoWidgetLineups from './lineup/InfoWidgetLineups.vue'; import InfoWidgetTable from './InfoWidgetTable.vue'; import InfoWidgetRound from './round/InfoWidgetRound.vue'; import InfoWidgetStats from './InfoWidgetStats.vue'; import LiveFeed from '../feed/LiveFeed.vue'; import type { Author } from '@polaris-media/polarpaw-types/polaris'; import { computed, ref, useTemplateRef, watch, nextTick, type Component, } from 'vue'; import type { RoundData, MatchSummary, MatchLineup, TableData, MatchStatistics, SportsEvent, MatchData, Statistic, } from '@polaris-media/core-utilities'; import { sportsTabs, type SportTab } from './types'; import MatchHeader from './header/MatchHeader.vue'; import { AdComponentWrapper } from '@polaris-media/polarnexus-legacy'; import { LiveForm } from '../feed/events/cnp/cnptypes'; // All values optional => v-if on tab const props = defineProps<{ matchData: MatchData | undefined; feed: (SportsEvent | AdComponentWrapper)[]; showNtbComments?: boolean; importantOnly: boolean; summary: MatchSummary | undefined; lineup: MatchLineup | undefined; statistics: MatchStatistics | undefined; round: RoundData | undefined; table: TableData | undefined; authors?: Author[]; showCnpUserForm?: boolean; cnpUserFormProps?: LiveForm; }>(); const currentTab = ref<SportTab>('feed'); const isMeaningful = (value: unknown) => value !== undefined && value !== null && value !== 0; const hasStatistics = (teamStatistic: Statistic) => { return Object.values(teamStatistic).some(isMeaningful); }; const hasAnyStatistics = computed(() => { if (!props.statistics) return false; const homeHasStats = hasStatistics(props.statistics.homeTeam); const awayHasStats = hasStatistics(props.statistics.awayTeam); return homeHasStats || awayHasStats; }); const tabs: Record<SportTab, Component | undefined> = { feed: LiveFeed as Component, lineup: InfoWidgetLineups as Component, table: InfoWidgetTable as Component, round: InfoWidgetRound as Component, statistics: hasAnyStatistics.value ? (InfoWidgetStats as Component) : undefined, }; const homeTeamName = computed(() => props.matchData?.homeTeam.name); const awayTeamName = computed(() => props.matchData?.awayTeam.name); const componentProps = computed(() => { switch (currentTab.value) { case 'feed': return { feed: props.feed, showNtbComments: props.showNtbComments, matchData: props.matchData, importantOnly: props.importantOnly, showCnpUserForm: props.showCnpUserForm, cnpUserFormProps: props.cnpUserFormProps, }; case 'lineup': return { homeTeamName, awayTeamName, lineup: props.lineup }; case 'table': return { table: props.table }; case 'round': return { currentRound: props.round }; case 'statistics': return { statistics: props.statistics }; default: return {}; } }); const liveblogContainer = useTemplateRef<HTMLDivElement>('liveblog-container'); watch(currentTab, async () => { await nextTick(); // scroll tab into view. mostly relevant when far down in the feed liveblogContainer.value?.scrollIntoView({ behavior: 'smooth', }); }); const showTab = (tabName: string) => { if (tabName === 'lineup') return false; if (tabName === 'statistics' && !hasAnyStatistics.value) return false; return true; }; const visibleTabs = computed(() => { return sportsTabs.filter((tab) => showTab(tab)); }); </script> <template> <section ref="liveblog-container"> <MatchHeader v-if="matchData && summary" :match-data :summary :authors="props.authors" /> <div class="active-tab"> <component :is="tabs[currentTab]" v-bind="componentProps" /> </div> <InfoWidgetTabs v-if="visibleTabs.length > 1" v-model="currentTab" :tabs="visibleTabs" /> </section> </template> <style scoped> .active-tab { margin-top: 1rem; max-width: min(calc(100% - calc(2 * var(--padding, 0px))), var(--width)); margin-inline: auto; } </style>