336 lines
12 KiB
Vue
336 lines
12 KiB
Vue
<template>
|
|
<div class="team-view centerDiv">
|
|
<div class="row">
|
|
<div class="col-sm">
|
|
<h1 id="team-record">{{ teamName }} {{ teamRecord }}</h1>
|
|
<h2 id="standings"></h2>
|
|
<h2 id="streak">Last 8: {{ lastEight }} / Streak: {{ streak }}</h2>
|
|
</div>
|
|
|
|
<div class="col-sm">
|
|
<h2 id="manager">
|
|
Manager{{ hasMultipleManagers ? 's' : '' }}:
|
|
<RouterLink v-if="manager1Name" :to="{ name: 'manager', params: { managerName: manager1Name } }">
|
|
{{ manager1Name }}
|
|
</RouterLink>
|
|
{{ hasMultipleManagers ? ' & ' : '' }}
|
|
<RouterLink v-if="hasMultipleManagers && manager2Name"
|
|
:to="{ name: 'manager', params: { managerName: manager2Name } }">
|
|
{{ manager2Name }}
|
|
</RouterLink>
|
|
</h2>
|
|
<h2 id="abbrev">Abbrev: {{ teamAbbreviation }}</h2>
|
|
</div>
|
|
|
|
<div class="col-sm-1">
|
|
<!-- TODO move thumbnail to computed and fallback on default pic? -->
|
|
<img id="thumbnail" height="125" style="float:right; vertical-align:middle" :src=team?.thumbnail>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Team Rosters -->
|
|
<div class="row">
|
|
<!-- Left Column -->
|
|
<div class="col-sm-6">
|
|
<h3 id="active-roster-count">({{ rosterCount }}/26) Active Roster ({{ swarTotal(players).toFixed(2) }})</h3>
|
|
<div class="table-responsive-xl">
|
|
<table class="table table-sm table-striped" id="table-active-roster">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Pos</th>
|
|
<th>Name</th>
|
|
<th>sWAR</th>
|
|
<th>Injury</th>
|
|
<th>Positions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="active-roster">
|
|
<tr v-for="player in sortedPlayers(players)" :key="player.id">
|
|
<td>{{ player.pos_1 }}</td>
|
|
<td :title="player.il_return ? `Injured until ${player.il_return}` : ''">
|
|
{{ player.il_return ? '🏥' : '' }}
|
|
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
|
|
{{ player.name }}
|
|
</RouterLink>
|
|
{{ player.il_return ? '🏥' : '' }}
|
|
</td>
|
|
<td>{{ player.wara.toFixed(2) }}</td>
|
|
<td>{{ player.injury_rating }}</td>
|
|
<td>{{ allPositions(player) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<th>Pos</th>
|
|
<th>Name</th>
|
|
<th>sWAR</th>
|
|
<th>Injury</th>
|
|
<th>Positions</th>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column -->
|
|
<div v-if="!isFreeAgentTeam" class="col-sm-6">
|
|
|
|
<h3 id="minors-header">({{ minorsRosterCount }}/6) {{ minorsTeamName }} ({{ swarTotal(playersMinors).toFixed(2)
|
|
}})</h3>
|
|
<div class="table-responsive-xl">
|
|
<table class="table table-sm table-striped" id="table-minors-roster">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Pos</th>
|
|
<th>Name</th>
|
|
<th>sWAR</th>
|
|
<th>Inj Return</th>
|
|
<th>Positions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="minors-roster">
|
|
<tr v-for="player in sortedPlayers(playersMinors)" :key="player.id">
|
|
<td>{{ player.pos_1 }}</td>
|
|
<td>
|
|
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
|
|
{{ player.name }}
|
|
</RouterLink>
|
|
</td>
|
|
<td>{{ player.wara.toFixed(2) }}</td>
|
|
<td>{{ player.il_return }}</td>
|
|
<td>{{ allPositions(player) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<h3 id="short-il-header">Injured List ({{ swarTotal(playersInjuredList).toFixed(2) }})</h3>
|
|
<div class="table-responsive-xl">
|
|
<table class="table table-sm table-striped" id="table-shortil-roster">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Pos</th>
|
|
<th>Name</th>
|
|
<th>sWAR</th>
|
|
<th>Inj Return</th>
|
|
<th>Positions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="short-il-roster">
|
|
<tr v-for="player in sortedPlayers(playersInjuredList)" :key="player.id">
|
|
<td>{{ player.pos_1 }}</td>
|
|
<td>
|
|
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
|
|
{{ player.name }}
|
|
</RouterLink>
|
|
</td>
|
|
<td>{{ player.wara.toFixed(2) }}</td>
|
|
<td>{{ player.il_return }}</td>
|
|
<td>{{ allPositions(player) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<template v-if="currentSeasonNumber === seasonNumber">
|
|
<h3 id="transactions-header">Week {{ transactionsWeekNumber }} Transactions ({{ transactionsWar.toFixed(2) }})
|
|
</h3>
|
|
<div class="table-responsive-xl">
|
|
<table class="table table-sm table-striped" id="table-transactions">
|
|
<thead class="thead-dark">
|
|
<tr>
|
|
<th>Week</th>
|
|
<th>Player</th>
|
|
<th>Old Team</th>
|
|
<th>New Team</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="transactions-body"></tbody>
|
|
<tr v-for="row in transactionRows" :key="row.week">
|
|
<td>{{ row.week }}</td>
|
|
<td>{{ row.playerName }}</td>
|
|
<td>{{ row.oldTeam }}</td>
|
|
<td>{{ row.newTeam }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<BullpenTable
|
|
v-if="currentSeasonNumber === seasonNumber && weekNumber && team?.id"
|
|
:season-number="seasonNumber"
|
|
:week-number="weekNumber"
|
|
:team-id="team.id"
|
|
/>
|
|
|
|
<!-- Schedule -->
|
|
<TeamScheduleTable v-if="!isFreeAgentTeam && team" :season-number="seasonNumber" :team-id="team.id" />
|
|
|
|
<!-- Team Pitching -->
|
|
<TeamPitchingTable v-if="!isFreeAgentTeam && team" :is-regular-season="true" :season-number="seasonNumber"
|
|
:team-id="team.id" />
|
|
<TeamPitchingTable v-if="!isFreeAgentTeam && team" :is-regular-season="false" :season-number="seasonNumber"
|
|
:team-id="team.id" />
|
|
|
|
<!-- Team Batting -->
|
|
<TeamBattingTable v-if="!isFreeAgentTeam && team" :is-regular-season="true" :season-number="seasonNumber"
|
|
:team-id="team.id" />
|
|
<TeamBattingTable v-if="!isFreeAgentTeam && team" :is-regular-season="false" :season-number="seasonNumber"
|
|
:team-id="team.id" />
|
|
|
|
<!-- Team Fielding -->
|
|
<div class="row">
|
|
<TeamFieldingTable v-if="!isFreeAgentTeam && team" :is-regular-season="true" :season-number="seasonNumber"
|
|
:team-id="team.id" />
|
|
<TeamFieldingTable v-if="!isFreeAgentTeam && team" :is-regular-season="false" :season-number="seasonNumber"
|
|
:team-id="team.id" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import type { Team } from '@/services/apiResponseTypes'
|
|
import { fetchCurrentLeagueInfo, type LeagueInfo } from '@/services/currentService'
|
|
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'
|
|
import TeamPitchingTable from '@/components/TeamPitchingTable.vue'
|
|
import TeamBattingTable from '@/components/TeamBattingTable.vue'
|
|
import TeamFieldingTable from '@/components/TeamFieldingTable.vue'
|
|
import BullpenTable from '@/components/BullpenTable.vue'
|
|
|
|
export default {
|
|
name: 'TeamView',
|
|
components: {
|
|
BullpenTable,
|
|
TeamScheduleTable,
|
|
TeamPitchingTable,
|
|
TeamBattingTable,
|
|
TeamFieldingTable
|
|
},
|
|
data() {
|
|
return {
|
|
team: undefined as Team | undefined,
|
|
teamMinors: undefined as Team | undefined,
|
|
teamInjuredList: undefined as Team | undefined,
|
|
teamStanding: undefined as TeamStanding | undefined,
|
|
players: [] as Player[],
|
|
playersMinors: [] as Player[],
|
|
playersInjuredList: [] as Player[],
|
|
transactions: [] as Transaction[],
|
|
weekNumber: undefined as number | undefined,
|
|
currentSeasonNumber: undefined as number | undefined
|
|
}
|
|
},
|
|
props: {
|
|
seasonNumber: { type: Number, required: true },
|
|
teamAbbreviation: { type: String, required: true },
|
|
},
|
|
computed: {
|
|
isFreeAgentTeam(): boolean {
|
|
return this.teamAbbreviation === 'FA'
|
|
},
|
|
manager1Name(): string | undefined {
|
|
return this.team?.manager1?.name
|
|
},
|
|
manager2Name(): string | undefined {
|
|
return this.team?.manager2?.name
|
|
},
|
|
hasMultipleManagers(): boolean {
|
|
return !!(this.manager1Name && this.manager2Name)
|
|
},
|
|
teamName(): string | undefined {
|
|
return this.team?.lname
|
|
},
|
|
teamRecord(): string | undefined {
|
|
if (!this.teamStanding) return undefined
|
|
return `(${this.teamStanding?.wins}-${this.teamStanding.losses})`
|
|
},
|
|
minorsTeamName(): string | undefined {
|
|
return this.teamMinors?.sname
|
|
},
|
|
lastEight(): string | undefined {
|
|
return this.teamStanding?.last8Record
|
|
},
|
|
streak(): string | undefined {
|
|
return this.teamStanding?.streak
|
|
},
|
|
rosterCount(): number {
|
|
return this.players.length
|
|
},
|
|
minorsRosterCount(): number {
|
|
return this.playersMinors.length
|
|
},
|
|
transactionsWeekNumber(): number | undefined {
|
|
if (this.weekNumber === undefined) return undefined
|
|
return this.weekNumber + 1
|
|
},
|
|
transactionsWar(): number {
|
|
const teamsWar = this.swarTotal(this.players)
|
|
if (!this.transactions.length) return teamsWar
|
|
|
|
const playersOut = this.transactions.filter(t => t.oldteam.abbrev === this.teamAbbreviation).map(t => t.player)
|
|
const playersIn = this.transactions.filter(t => t.newteam.abbrev === this.teamAbbreviation).map(t => t.player)
|
|
|
|
const swarOut = this.swarTotal(playersOut)
|
|
const swarIn = this.swarTotal(playersIn)
|
|
|
|
return teamsWar - swarOut + swarIn
|
|
},
|
|
transactionRows(): { week: number, playerName: string, oldTeam: string, newTeam: string }[] {
|
|
return this.transactions.map(t => {
|
|
return { week: t.week, playerName: t.player.name, oldTeam: t.oldteam.sname, newTeam: t.newteam.sname }
|
|
})
|
|
}
|
|
},
|
|
created() {
|
|
this.fetchData()
|
|
},
|
|
watch: {
|
|
seasonNumber(newValue, oldValue) {
|
|
if (newValue !== oldValue)
|
|
this.fetchData()
|
|
},
|
|
teamAbbreviation(newName, oldName) {
|
|
if (newName !== oldName)
|
|
this.fetchData()
|
|
}
|
|
},
|
|
methods: {
|
|
async fetchData(): Promise<void> {
|
|
this.team = await fetchTeam(this.seasonNumber, this.teamAbbreviation)
|
|
if (!this.isFreeAgentTeam) {
|
|
this.teamMinors = await fetchTeam(this.seasonNumber, `${this.teamAbbreviation}MiL`)
|
|
this.teamInjuredList = await fetchTeam(this.seasonNumber, `${this.teamAbbreviation}IL`)
|
|
}
|
|
|
|
this.teamStanding = (await fetchStandings(this.seasonNumber)).find(ts => ts.teamName === this.team?.sname)
|
|
const leagueInfo: LeagueInfo = await fetchCurrentLeagueInfo()
|
|
this.currentSeasonNumber = leagueInfo.season
|
|
this.weekNumber = leagueInfo.week
|
|
|
|
this.players = await fetchPlayersByTeam(this.seasonNumber, this.team?.id)
|
|
if (!this.isFreeAgentTeam) {
|
|
this.playersMinors = await fetchPlayersByTeam(this.seasonNumber, this.teamMinors!.id)
|
|
this.playersInjuredList = await fetchPlayersByTeam(this.seasonNumber, this.teamInjuredList!.id)
|
|
}
|
|
|
|
this.transactions = (await fetchTransactionsByTeamAndWeek(this.seasonNumber, this.teamAbbreviation, this.transactionsWeekNumber!))
|
|
},
|
|
allPositions(player: Player): string {
|
|
let positions = []
|
|
positions.push(player.pos_1, player.pos_2, player.pos_3, player.pos_4, player.pos_5, player.pos_6, player.pos_7)
|
|
return positions.filter(p => p).join(' ')
|
|
},
|
|
swarTotal(players: Player[]): number {
|
|
return players.map(p => p.wara).reduce((prev, curr) => prev + curr, 0)
|
|
},
|
|
sortedPlayers(players: Player[]): Player[] {
|
|
return players.sort((a, b) => b.wara - a.wara)
|
|
}
|
|
}
|
|
}
|
|
</script> |