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>