Add Schedule to TeamView

This commit is contained in:
Peter 2023-09-19 10:25:06 -04:00
parent f564733e14
commit 0ca9a9e8b3
5 changed files with 203 additions and 0 deletions

1
components.d.ts vendored
View File

@ -26,5 +26,6 @@ declare module '@vue/runtime-core' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
StandingsTable: typeof import('./src/components/StandingsTable.vue')['default']
TeamScheduleTable: typeof import('./src/components/TeamScheduleTable.vue')['default']
}
}

View File

@ -0,0 +1,175 @@
<template>
<div v-if="schedule.length" class="team-schedule-table">
<div class="row">
<div class="col-sm-12">
<h3>Season Schedule</h3>
</div>
<!-- First Half -->
<div class="col-sm-6">
<div class="table-responsive-xl">
<table class="table table-sm table-striped" id="schedule-first">
<thead class="thead-dark">
<tr id="schedule-first-header">
<th style="width: 4rem">Week</th>
<th style="width: 8rem">Away</th>
<th style="width: 2rem"></th>
<th style="width: 8rem">Home</th>
<th style="width: 8rem">Game 1</th>
<th style="width: 8rem">Game 2</th>
<th style="width: 8rem">Game 3</th>
<th style="width: 8rem">Game 4</th>
</tr>
</thead>
<tbody>
<tr v-for="row in firstHalfRows">
<td>{{ row.week }}</td>
<td>
<RouterLink
:to="{ name: 'team', params: { seasonNumber: seasonNumber, teamAbbreviation: row.awayTeam.abbrev } }">
{{ row.awayTeam.sname }}
</RouterLink>
</td>
<td>@</td>
<td>
<RouterLink
:to="{ name: 'team', params: { seasonNumber: seasonNumber, teamAbbreviation: row.homeTeam.abbrev } }">
{{ row.homeTeam.sname }}
</RouterLink>
</td>
<td>{{ makeGameScore(row.game1) }}</td>
<td>{{ makeGameScore(row.game2) }}</td>
<td>{{ makeGameScore(row.game3) }}</td>
<td>{{ makeGameScore(row.game4) }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Second Half -->
<div class="col-sm-6">
<div class="table-responsive-xl">
<table class="table table-sm table-striped" id="schedule-second">
<thead class="thead-dark">
<tr id="schedule-second-header">
<th style="width: 4rem">Week</th>
<th style="width: 8rem">Away</th>
<th style="width: 2rem"></th>
<th style="width: 8rem">Home</th>
<th style="width: 8rem">Game 1</th>
<th style="width: 8rem">Game 2</th>
<th style="width: 8rem">Game 3</th>
<th style="width: 8rem">Game 4</th>
</tr>
</thead>
<tbody>
<tr v-for="row in secondHalfRows">
<td>{{ row.week }}</td>
<td>
<RouterLink
:to="{ name: 'team', params: { seasonNumber: seasonNumber, teamAbbreviation: row.awayTeam.abbrev } }">
{{ row.awayTeam.sname }}
</RouterLink>
</td>
<td>@</td>
<td>
<RouterLink
:to="{ name: 'team', params: { seasonNumber: seasonNumber, teamAbbreviation: row.homeTeam.abbrev } }">
{{ row.homeTeam.sname }}
</RouterLink>
</td>
<td>{{ makeGameScore(row.game1) }}</td>
<td>{{ makeGameScore(row.game2) }}</td>
<td>{{ makeGameScore(row.game3) }}</td>
<td>{{ makeGameScore(row.game4) }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import type { Game, Team } from '@/services/apiResponseTypes'
import { fetchGamesBySeasonAndTeamId } from '@/services/gameService'
import { GAMES_PER_SEASON } from '@/services/utilities'
interface ScheduleRow {
week: number
awayTeam: Team
homeTeam: Team
game1: Game | undefined
game2: Game | undefined
game3: Game | undefined
game4: Game | undefined
}
export default {
name: "TeamScheduleTable",
data() {
return {
schedule: [] as Game[]
}
},
props: {
seasonNumber: { type: Number, required: true },
teamId: { type: Number, required: true }
},
computed: {
midSeasonWeekNumber(): number {
const gamesPerWeek = 4
return (GAMES_PER_SEASON / gamesPerWeek) / 2
},
firstHalfRows(): ScheduleRow[] {
const games = this.schedule.filter(g => g.week <= this.midSeasonWeekNumber)
return this.makeScheduleRowsFromGames(games)
},
secondHalfRows(): ScheduleRow[] {
const games = this.schedule.filter(g => g.week > this.midSeasonWeekNumber)
return this.makeScheduleRowsFromGames(games)
}
},
created() {
this.fetchData()
},
methods: {
makeScheduleRowsFromGames(games: Game[]): ScheduleRow[] {
const gamesByWeekAndHomeTeam = this.groupByWeekAndHomeTeam(games)
console.log(Object.values(gamesByWeekAndHomeTeam))
return Object.values(gamesByWeekAndHomeTeam).sort((games1, games2) => games1[0].id - games2[0].id).map(games => {
return {
week: games[0].week,
awayTeam: games[0].away_team,
homeTeam: games[0].home_team,
game1: games.find(g => g.game_num === 1),
game2: games.find(g => g.game_num === 2),
game3: games.find(g => g.game_num === 3),
game4: games.find(g => g.game_num === 4)
}
})
},
groupByWeekAndHomeTeam(games: Game[]): { [key: string]: Game[] } {
return games.reduce((storage, game) => {
const key = `${game.week}-${game.home_team.abbrev}`
if (storage[key]) {
storage[key].push(game)
} else {
storage[key] = [game]
}
return storage
}, {} as { [key: string]: Game[] })
},
makeGameScore(game: Game | undefined): string {
if (!game || (!game.away_score && !game.home_score)) return '-'
return `${game.away_team.abbrev} ${game.away_score}-${game.home_score} ${game.home_team.abbrev}`
},
async fetchData(): Promise<void> {
this.schedule = await fetchGamesBySeasonAndTeamId(this.seasonNumber, this.teamId)
}
}
}
</script>

View File

@ -0,0 +1,18 @@
import type { Game } from './apiResponseTypes'
import { MODERN_STAT_ERA_START, SITE_URL } from './utilities'
export async function fetchGamesBySeasonAndTeamId(seasonNumber: number, teamId: number): Promise<Game[]> {
if (seasonNumber < MODERN_STAT_ERA_START) {
console.warn(`Cannot use games endpoint to fetch stats before season 8`)
return []
}
const response = await fetch(`${SITE_URL}/api/v3/games?season=${seasonNumber}&team1_id=${teamId}&team2_id=${teamId}`)
const gamesResponse: {
count: number
games: Game[]
} = await response.json()
return gamesResponse.games
}

View File

@ -4,6 +4,8 @@ export const CURRENT_SEASON = 8
export const MODERN_STAT_ERA_START = 8
export const GAMES_PER_SEASON = 72
// a type guard to tell typescript that undefined has been filtered and to only consider an array
// of the expected types (no undefineds) after filtering
export const isNotUndefined = <S>(value: S | undefined): value is S => value != undefined

View File

@ -154,6 +154,9 @@
</div>
</div>
</div>
<!-- Schedule -->
<TeamScheduleTable v-if="!isFreeAgentTeam && team" :season-number="seasonNumber" :team-id="team.id" />
</div>
</template>
@ -164,9 +167,13 @@ import { fetchPlayersByTeam, type Player } from '@/services/playersService'
import { fetchStandings, type TeamStanding } from '@/services/standingsService'
import { fetchTeam } from '@/services/teamsService'
import { fetchTransactionsByTeamAndWeek, type Transaction } from '@/services/transactionsService'
import TeamScheduleTable from '@/components/TeamScheduleTable.vue'
export default {
name: "TeamView",
components: {
TeamScheduleTable
},
data() {
return {
team: undefined as Team | undefined,