Initial commit (ugly/incomplete)
This commit is contained in:
parent
545f4aca7e
commit
be2cf17a9e
136
.gitignore
vendored
136
.gitignore
vendored
@ -4,127 +4,25 @@ logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||
}
|
||||
27
components.d.ts
vendored
Normal file
27
components.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
FrontPage: typeof import('./src/components/FrontPage.vue')['default']
|
||||
IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
|
||||
IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']
|
||||
IconEcosystem: typeof import('./src/components/icons/IconEcosystem.vue')['default']
|
||||
IconSupport: typeof import('./src/components/icons/IconSupport.vue')['default']
|
||||
IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default']
|
||||
NavBar: typeof import('./src/components/NavBar.vue')['default']
|
||||
NButton: typeof import('naive-ui')['NButton']
|
||||
NMenu: typeof import('naive-ui')['NMenu']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
StandingsTable: typeof import('./src/components/StandingsTable.vue')['default']
|
||||
TheWelcome: typeof import('./src/components/TheWelcome.vue')['default']
|
||||
WelcomeItem: typeof import('./src/components/WelcomeItem.vue')['default']
|
||||
}
|
||||
}
|
||||
22
index.html
Normal file
22
index.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="height: 100%">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<meta property="og:title" content="SBa: Season 7" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://sombaseball.ddns.net" />
|
||||
<meta property="og:image" content="https://sombaseball.ddns.net/static/images/sba-network.png" />
|
||||
<meta property="og:description" content="The home of the Strat-o-matic Baseball Association" />
|
||||
<meta name="theme-color" content="#A6CE39">
|
||||
<title>SBa TEST</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
2730
package-lock.json
generated
Normal file
2730
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
package.json
Normal file
29
package.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "sba2",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.2.45",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.12",
|
||||
"@vicons/fluent": "0.12.0",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"naive-ui": "2.34.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"typescript": "~4.7.4",
|
||||
"unplugin-vue-components": "0.24.1",
|
||||
"vfonts": "0.0.3",
|
||||
"vite": "^4.0.0",
|
||||
"vue-tsc": "^1.0.12"
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
102
src/App.vue
Normal file
102
src/App.vue
Normal file
@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<html lang="en" style="height: 100%">
|
||||
<!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
|
||||
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/yeti/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/src/assets/oldSite.css"> -->
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta property="og:title" content="SBa: Season 8" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://sombaseball.ddns.net" />
|
||||
<meta property="og:image" content="https://sombaseball.ddns.net/static/images/sba-network.png" />
|
||||
<meta property="og:description" content="The home of the Strat-o-matic Baseball Association" />
|
||||
<meta name="theme-color" content="#A6CE39">
|
||||
<title>SBa Season {{ seasonNumber }}</title>
|
||||
</head>
|
||||
<NavBar />
|
||||
|
||||
<RouterView />
|
||||
|
||||
</html>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { RouterView } from 'vue-router'
|
||||
import NavBar from './components/NavBar.vue'
|
||||
import { CURRENT_SEASON } from '@/services/utilities'
|
||||
export default {
|
||||
name: "App",
|
||||
data() {
|
||||
return {
|
||||
seasonNumber: CURRENT_SEASON as number
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
header {
|
||||
line-height: 1.5;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: block;
|
||||
margin: 0 auto 2rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
nav a.router-link-exact-active {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
nav a.router-link-exact-active:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: inline-block;
|
||||
padding: 0 1rem;
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
nav a:first-of-type {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
header {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
padding-right: calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 0 2rem 0 0;
|
||||
}
|
||||
|
||||
header .wrapper {
|
||||
display: flex;
|
||||
place-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
nav {
|
||||
text-align: left;
|
||||
margin-left: -1rem;
|
||||
font-size: 1rem;
|
||||
|
||||
padding: 1rem 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
74
src/assets/base.css
Normal file
74
src/assets/base.css
Normal file
@ -0,0 +1,74 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
1
src/assets/logo.svg
Normal file
1
src/assets/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
|
After Width: | Height: | Size: 308 B |
35
src/assets/main.css
Normal file
35
src/assets/main.css
Normal file
@ -0,0 +1,35 @@
|
||||
@import './base.css';
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
body {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
}
|
||||
102
src/assets/oldSite.css
Normal file
102
src/assets/oldSite.css
Normal file
@ -0,0 +1,102 @@
|
||||
.centerDiv {
|
||||
width: 92%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.sticky-dark {
|
||||
position: sticky;
|
||||
left: 0em;
|
||||
background-color: #E5E5E5
|
||||
}
|
||||
|
||||
.sticky-light {
|
||||
position: sticky;
|
||||
left: 0em;
|
||||
background-color: #F4F4F4
|
||||
}
|
||||
|
||||
.col-small {
|
||||
width: 1em
|
||||
}
|
||||
|
||||
.col-med {
|
||||
width: 10em
|
||||
}
|
||||
|
||||
.col-large {
|
||||
width: 20em
|
||||
}
|
||||
|
||||
code {
|
||||
color: black
|
||||
}
|
||||
|
||||
.navbar-dark {
|
||||
background-color: black;
|
||||
color: black;
|
||||
margin-bottom: -5px
|
||||
}
|
||||
|
||||
.dark-mode {
|
||||
background-color: black;
|
||||
color: #E5E5E5;
|
||||
}
|
||||
|
||||
.dropdown-toggle.active-dropdown::after {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
background-color: black !important;
|
||||
color: #E5E5E5;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .bg-light {
|
||||
background-color: #333 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .bg-white {
|
||||
background-color: #000 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .bg-black {
|
||||
background-color: #eee !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .table td {
|
||||
color: #E5E5E5 !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .table th {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.news-preview {
|
||||
max-width: 950px;
|
||||
padding-bottom: 75px;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.news-subtitle {
|
||||
font-size: 11px;
|
||||
line-height: 10px;
|
||||
padding-bottom: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.news-article {
|
||||
max-width: 700px;
|
||||
padding-bottom: 75px;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.news-subtitle-large {
|
||||
/* font-size: 22px;
|
||||
line-height: 20px; */
|
||||
vertical-align: middle;
|
||||
padding-top: 25px;
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
270
src/components/NavBar.vue
Normal file
270
src/components/NavBar.vue
Normal file
@ -0,0 +1,270 @@
|
||||
<template>
|
||||
<div class="navbar navbar-expand-sm navbar-dark bg-primary ">
|
||||
<div class="nav-bar navbar-brand mb-0 h1">
|
||||
<RouterLink to="/">SBa Season {{ seasonNumber }}</RouterLink>
|
||||
<n-menu mode="horizontal" :options="menuOptions" />
|
||||
<li class="nav-item"> <a id="login" class="nav-link">Login with Discord</a></li>
|
||||
<li class="nav-item">
|
||||
<a id="team-login-link" href="/teams?abbrev=">
|
||||
<img id="team-login" style="max-height:35px" hidden />
|
||||
</a>
|
||||
</li>
|
||||
<form class="form-inline" action="/players">
|
||||
<input type="text" name="name" placeholder="Player Search" list="player-names" id="player-choice">
|
||||
<datalist id="player-names">
|
||||
<option v-for="name in playerNames" :value="name">{{ name }}</option>
|
||||
</datalist>
|
||||
</form>
|
||||
<ul class="navbar-nav navbar-right">
|
||||
<li class="nav-item">
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" id="darkSwitch" />
|
||||
<label class="custom-control-label" for="darkSwitch">Dark Mode</label>
|
||||
</div>
|
||||
<!-- <script src="/static/dark-mode-switch.js"></script> -->
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <nav class="container">
|
||||
<RouterLink to="/">SBa Season {{ seasonNumber }}</RouterLink>
|
||||
<RouterLink to="/schedule">Schedule</RouterLink>
|
||||
<RouterLink to="/standings">Standings</RouterLink>
|
||||
<RouterLink to="/stats">Stats & Leaders</RouterLink>
|
||||
<RouterLink to="/teams">Teams</RouterLink>
|
||||
<RouterLink to="/transactions">Transactions</RouterLink>
|
||||
<RouterLink to="/history">History</RouterLink>
|
||||
<RouterLink to="/rules">Rules Ref</RouterLink>
|
||||
<RouterLink to="/news">News</RouterLink>
|
||||
</nav> -->
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { MenuOption } from 'naive-ui'
|
||||
import { fetchPlayers, type Player } from '@/services/playersService'
|
||||
import { CURRENT_SEASON } from '@/services/utilities'
|
||||
|
||||
export default {
|
||||
name: 'NavBar',
|
||||
data() {
|
||||
return {
|
||||
playerNames: [] as string[],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.populatePlayerNames()
|
||||
},
|
||||
computed: {
|
||||
menuOptions(): MenuOption[] {
|
||||
return [
|
||||
{
|
||||
label: 'Schedule',
|
||||
key: 'Schedule'
|
||||
},
|
||||
{
|
||||
label: 'Standings',
|
||||
key: 'Standings',
|
||||
},
|
||||
{
|
||||
label: 'Stats & Leaders',
|
||||
key: 'Stats & Leaders',
|
||||
children: [
|
||||
{
|
||||
label: 'Season Leaders',
|
||||
key: 'Season Leaders',
|
||||
children: [
|
||||
{
|
||||
label: 'Batting Leaders',
|
||||
key: 'Batting Leaders'
|
||||
},
|
||||
{
|
||||
label: 'Pitching Leaders',
|
||||
key: 'Pitching Leaders'
|
||||
},
|
||||
{
|
||||
label: 'Fielding Leaders',
|
||||
key: 'Fielding Leaders'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Team Stats',
|
||||
key: 'Team Stats',
|
||||
children: [
|
||||
{
|
||||
label: 'Team Batting',
|
||||
key: 'Team Batting'
|
||||
},
|
||||
{
|
||||
label: 'Team Pitching',
|
||||
key: 'Team Pitching'
|
||||
},
|
||||
{
|
||||
label: 'Team Fielding',
|
||||
key: 'Team Fielding'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Single-Game Records',
|
||||
key: 'Single-Game Records',
|
||||
children: [
|
||||
{
|
||||
label: 'Single-Game Batting',
|
||||
key: 'Single-Game Batting'
|
||||
},
|
||||
{
|
||||
label: 'Single-Game Pitching',
|
||||
key: 'Single-Game Pitching'
|
||||
},
|
||||
{
|
||||
label: 'Single-Game Fielding',
|
||||
key: 'Single-Game Fielding'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Single-Season Stats',
|
||||
key: 'Single-Season Stats',
|
||||
children: [
|
||||
{
|
||||
label: 'Single-Season Batting',
|
||||
key: 'Single-Season Batting'
|
||||
},
|
||||
{
|
||||
label: 'Single-Season Pitching',
|
||||
key: 'Single-Season Pitching'
|
||||
},
|
||||
{
|
||||
label: 'Single-Season Fielding',
|
||||
key: 'Single-Season Fielding'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Career Leaders',
|
||||
key: 'Career Leaders',
|
||||
children: [
|
||||
{
|
||||
label: 'Career Batting',
|
||||
key: 'Career Batting'
|
||||
},
|
||||
{
|
||||
label: 'Career Pitching',
|
||||
key: 'Career Pitching'
|
||||
},
|
||||
{
|
||||
label: 'Career Fielding',
|
||||
key: 'Career Fielding'
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
{
|
||||
label: 'Teams',
|
||||
key: 'Teams',
|
||||
children: [
|
||||
{
|
||||
label: 'AL East',
|
||||
key: 'AL East',
|
||||
children: [
|
||||
{ label: 'Gators', key: 'Gators' },
|
||||
{ label: 'Honeybees', keys: 'Honeybees' },
|
||||
{ label: 'Kaiju', key: 'Kaiju' },
|
||||
{ label: 'Phantoms', key: 'Phantoms' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'AL West',
|
||||
key: 'AL West',
|
||||
children: [
|
||||
{ label: 'Cyclones', key: 'Cyclones' },
|
||||
{ label: 'Mussels', keys: 'Mussels' },
|
||||
{ label: 'Whale Sharks', key: 'Whale Sharks' },
|
||||
{ label: 'Wu Xia', key: 'Wu Xia' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'NL East',
|
||||
key: 'NL East',
|
||||
children: [
|
||||
{ label: 'Drillers', key: 'Drillers' },
|
||||
{ label: 'Macho Men', keys: 'Macho Men' },
|
||||
{ label: 'Shoebills', key: 'Shoebills' },
|
||||
{ label: 'Zephyr', key: 'Zephyr' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'NL West',
|
||||
key: 'NL West',
|
||||
children: [
|
||||
{ label: 'Angels', key: 'Angels' },
|
||||
{ label: 'Black Bears', keys: 'Black Bears' },
|
||||
{ label: 'Bovines', key: 'Bovines' },
|
||||
{ label: 'Snow Geese', key: 'Snow Geese' }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Transactions',
|
||||
key: 'Transactions',
|
||||
children: [
|
||||
{ label: 'Free Agents', key: 'Free Agents' },
|
||||
{ label: 'Transactions', key: 'Transactions' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'History',
|
||||
key: 'History',
|
||||
children: [
|
||||
{ label: 'Awards', key: 'Awards' },
|
||||
{
|
||||
label: 'Managers',
|
||||
key: 'Managers',
|
||||
// TODO figure out a way to pull active/retired into children here
|
||||
children: [{ label: 'Active', key: 'Active' }, { label: 'Retired', key: 'Retired' }]
|
||||
},
|
||||
{
|
||||
label: 'Season Recaps',
|
||||
key: 'Season Recaps',
|
||||
children: [
|
||||
{ label: 'Season 4', key: 'Season 4' },
|
||||
{ label: 'Season 3', key: 'Season 3' },
|
||||
{ label: 'Season 2', key: 'Season 2' },
|
||||
{ label: 'Season 1', key: 'Season 1' },
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{ label: 'Rules Ref', key: 'Rules Ref' },
|
||||
{ label: 'News', key: 'News' }
|
||||
]
|
||||
},
|
||||
seasonNumber(): number {
|
||||
// TODO pull this from DB?
|
||||
return CURRENT_SEASON
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async getPlayers(): Promise<Player[]> {
|
||||
return await fetchPlayers(this.seasonNumber)
|
||||
},
|
||||
async populatePlayerNames(): Promise<void> {
|
||||
const players: Player[] = await this.getPlayers()
|
||||
this.playerNames = players.sort(p => p.wara).map(p => p.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
margin: 0%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
66
src/components/StandingsTable.vue
Normal file
66
src/components/StandingsTable.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="standings-table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Team</th>
|
||||
<th>Record</th>
|
||||
<th>Win %</th>
|
||||
<th>GB</th>
|
||||
<th>E#</th>
|
||||
<th>Run Diff</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(team, index) in teams" :key="index">
|
||||
<td>
|
||||
<RouterLink
|
||||
:to="{ name: 'team', params: { seasonNumber: seasonNumber(), teamAbbreviation: team.teamAbbreviation } }">
|
||||
{{
|
||||
team.teamName }}
|
||||
</RouterLink>
|
||||
</td>
|
||||
<td>{{ record(team) }}</td>
|
||||
<td>{{ team.winPercentage }}</td>
|
||||
<td>{{ gamesBack(team) }}</td>
|
||||
<td>{{ eliminationNumber(team) }}</td>
|
||||
<td>{{ team.runDifferential }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { TeamStanding } from '@/services/standingsService'
|
||||
import { CURRENT_SEASON } from '@/services/utilities'
|
||||
|
||||
|
||||
export default {
|
||||
name: "StandingsTable",
|
||||
props: {
|
||||
teams: {
|
||||
type: Array<TeamStanding>,
|
||||
required: true,
|
||||
},
|
||||
isDivisional: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
eliminationNumber(teamStanding: TeamStanding): string {
|
||||
return this.isDivisional ? teamStanding.divisionEliminationNumber : teamStanding.wildcardEliminationNumber
|
||||
},
|
||||
gamesBack(teamStanding: TeamStanding): string {
|
||||
return this.isDivisional ? teamStanding.divisionGamesBack : teamStanding.wildcardGamesBack
|
||||
},
|
||||
record(teamStanding: TeamStanding): string {
|
||||
return `${teamStanding.wins}-${teamStanding.losses}`
|
||||
},
|
||||
seasonNumber(): number {
|
||||
return CURRENT_SEASON
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
16
src/components/TheWelcome.vue
Normal file
16
src/components/TheWelcome.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<button @click="players">Log Players</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { fetchPlayers } from '@/services/playersService'
|
||||
import { CURRENT_SEASON } from '@/services/utilities'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
async players(): Promise<void> {
|
||||
await fetchPlayers(CURRENT_SEASON)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
7
src/components/icons/IconCommunity.vue
Normal file
7
src/components/icons/IconCommunity.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
src/components/icons/IconDocumentation.vue
Normal file
7
src/components/icons/IconDocumentation.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
src/components/icons/IconEcosystem.vue
Normal file
7
src/components/icons/IconEcosystem.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
src/components/icons/IconSupport.vue
Normal file
7
src/components/icons/IconSupport.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
19
src/components/icons/IconTooling.vue
Normal file
19
src/components/icons/IconTooling.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
11
src/main.ts
Normal file
11
src/main.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
import './assets/main.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
59
src/router/index.ts
Normal file
59
src/router/index.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
|
||||
|
||||
const HomeView = () => import('../views/HomeView.vue')
|
||||
|
||||
export const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: HomeView
|
||||
},
|
||||
{
|
||||
path: '/teams/:seasonNumber/:teamAbbreviation',
|
||||
name: 'team',
|
||||
component: () => import('../views/TeamView.vue'),
|
||||
props: castTeamsRouteParams
|
||||
},
|
||||
{
|
||||
path: '/managers/:managerName',
|
||||
name: 'manager',
|
||||
component: () => import('../views/ManagerView.vue'),
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: '/players/:seasonNumber/:playerName',
|
||||
name: 'player',
|
||||
component: () => import('../views/PlayerView.vue'),
|
||||
props: castPlayersRouteParams
|
||||
}
|
||||
]
|
||||
|
||||
function castTeamsRouteParams(route: any) {
|
||||
return {
|
||||
teamAbbreviation: route.params.teamAbbreviation,
|
||||
seasonNumber: Number(route.params.seasonNumber)
|
||||
}
|
||||
}
|
||||
|
||||
function castPlayersRouteParams(route: any) {
|
||||
return {
|
||||
playerName: route.params.playerName,
|
||||
seasonNumber: Number(route.params.seasonNumber)
|
||||
}
|
||||
}
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes,
|
||||
})
|
||||
|
||||
// export function routerPush (name: AppRouteNames, params?: RouteParams): ReturnType<typeof router.push> {
|
||||
// return params !== undefined
|
||||
// ? router.push({
|
||||
// name,
|
||||
// params,
|
||||
// })
|
||||
// : router.push({ name })
|
||||
// }
|
||||
|
||||
export default router
|
||||
38
src/services/apiResponseTypes.ts
Normal file
38
src/services/apiResponseTypes.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export interface Team {
|
||||
abbrev: string
|
||||
auto_draft: any
|
||||
color: string // hex code
|
||||
dice_color: string // hex code
|
||||
division: Division
|
||||
division_legacy: any
|
||||
gmid: number
|
||||
gmid2: number
|
||||
gsheet: any
|
||||
id: number
|
||||
lname: string
|
||||
manager1: Manager
|
||||
manager2: Manager
|
||||
manager_legacy: any
|
||||
mascot: any
|
||||
season: number
|
||||
sname: string
|
||||
stadium: string
|
||||
thumbnail: string
|
||||
}
|
||||
|
||||
export interface Manager {
|
||||
id: number
|
||||
name: string
|
||||
image: string
|
||||
headline: string
|
||||
bio: string
|
||||
}
|
||||
|
||||
export interface Division {
|
||||
division_abbrev: 'W' | 'E'
|
||||
division_name: 'West' | 'East'
|
||||
id: number
|
||||
league_abbrev: 'NL' | 'AL'
|
||||
league_name: 'National League' | 'American League'
|
||||
season: number
|
||||
}
|
||||
25
src/services/currentService.ts
Normal file
25
src/services/currentService.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { SITE_URL } from './utilities'
|
||||
|
||||
export interface LeagueInfo {
|
||||
id: number,
|
||||
week: number,
|
||||
freeze: boolean,
|
||||
season: number,
|
||||
transcount: number,
|
||||
bstatcount: number,
|
||||
pstatcount: number,
|
||||
bet_week: number,
|
||||
trade_deadline: number,
|
||||
pick_trade_start: number,
|
||||
pick_trade_end: number,
|
||||
playoffs_begin: number,
|
||||
injury_count: number
|
||||
}
|
||||
|
||||
export async function fetchCurrentLeagueInfo(): Promise<LeagueInfo> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/current`)
|
||||
|
||||
const leagueInfoResponse: LeagueInfo = await response.json()
|
||||
|
||||
return leagueInfoResponse
|
||||
}
|
||||
9
src/services/newsService.ts
Normal file
9
src/services/newsService.ts
Normal file
@ -0,0 +1,9 @@
|
||||
// const api = new GhostContentAPI({
|
||||
// url: 'https://sombaseball.ddns.net/writers',
|
||||
// key: 'cfc331bb02beaebc0c62211b10',
|
||||
// version: "v3"
|
||||
// });
|
||||
|
||||
export function getPosts() {
|
||||
|
||||
}
|
||||
68
src/services/playersService.ts
Normal file
68
src/services/playersService.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import type { Team } from './apiResponseTypes'
|
||||
import { SITE_URL } from './utilities'
|
||||
|
||||
export interface Player {
|
||||
bbref_id: string
|
||||
demotion_week: number
|
||||
headshot: any
|
||||
id: number
|
||||
il_return: any
|
||||
image: string
|
||||
image2: string
|
||||
injury_rating: string //could strongly type as XpYY
|
||||
last_game: string // could strongly type as XX.X IP wXXgX
|
||||
last_game2: string
|
||||
name: string
|
||||
pitcher_injury: string
|
||||
pos_1: string
|
||||
pos_2: string
|
||||
pos_3: string
|
||||
pos_4: string
|
||||
pos_5: string
|
||||
pos_6: string
|
||||
pos_7: string
|
||||
pos_8: string
|
||||
season: number
|
||||
strat_code: string
|
||||
team: Team,
|
||||
vanity_card: string
|
||||
wara: number
|
||||
}
|
||||
|
||||
export async function fetchPlayers(seasonNumber: number): Promise<Player[]> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/players?season=${seasonNumber}`)
|
||||
|
||||
const playersResponse: {
|
||||
count: number
|
||||
players: Player[]
|
||||
} = await response.json()
|
||||
|
||||
return playersResponse.players
|
||||
}
|
||||
|
||||
// TODO should/can this use team abbrev instead of id?
|
||||
export async function fetchPlayersByTeam(seasonNumber: number, teamId: number): Promise<Player[]> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/players?season=${seasonNumber}&team_id=${teamId}`)
|
||||
|
||||
const playersResponse: {
|
||||
count: number
|
||||
players: Player[]
|
||||
} = await response.json()
|
||||
|
||||
return playersResponse.players
|
||||
}
|
||||
|
||||
export async function fetchPlayerByName(seasonNumber: number, playerName: string): Promise<Player> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/players?season=${seasonNumber}&name=${playerName}`)
|
||||
|
||||
const playersResponse: {
|
||||
count: number
|
||||
players: Player[]
|
||||
} = await response.json()
|
||||
|
||||
if (playersResponse.count !== 1) {
|
||||
throw new Error('playersServices.fetchPlayerByName - Expected one player, return contained none or many')
|
||||
}
|
||||
|
||||
return playersResponse.players[0]
|
||||
}
|
||||
101
src/services/standingsService.ts
Normal file
101
src/services/standingsService.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import type { Team } from './apiResponseTypes'
|
||||
import { SITE_URL } from './utilities'
|
||||
|
||||
interface TeamStandingRaw {
|
||||
away_losses: number
|
||||
away_wins: number
|
||||
div1_losses: number
|
||||
div1_wins: number
|
||||
div2_losses: number
|
||||
div2_wins: number
|
||||
div3_losses: number
|
||||
div3_wins: number
|
||||
div4_losses: number
|
||||
div4_wins: number
|
||||
div_e_num: number
|
||||
div_gb: number
|
||||
home_losses: number
|
||||
home_wins: number
|
||||
id: number
|
||||
last8_losses: number
|
||||
last8_wins: number
|
||||
losses: number
|
||||
one_run_losses: number
|
||||
one_run_wins: number
|
||||
pythag_losses: number
|
||||
pythag_wins: number
|
||||
run_diff: number
|
||||
streak_num: number
|
||||
streak_wl: 'w' | 'l'
|
||||
team: Team
|
||||
wc_e_num: number | null
|
||||
wc_gb: number
|
||||
wins: number
|
||||
}
|
||||
|
||||
export interface TeamStanding {
|
||||
teamName: string
|
||||
teamAbbreviation: string
|
||||
divisionAbbreviation: 'W' | 'E'
|
||||
leagueAbbreviation: 'NL' | 'AL'
|
||||
wins: number
|
||||
losses: number
|
||||
winPercentage: string,
|
||||
last8Record: string,
|
||||
streak: string
|
||||
divisionGamesBack: string
|
||||
divisionEliminationNumber: string
|
||||
wildcardGamesBack: string
|
||||
wildcardEliminationNumber: string
|
||||
runDifferential: string
|
||||
isWildcardTeam: boolean
|
||||
}
|
||||
|
||||
export async function fetchStandings(seasonNumber: number): Promise<TeamStanding[]> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/standings?season=${seasonNumber}`)//?league_abbrev=AL&division_abbrev=W`)
|
||||
|
||||
const standingsResponse: {
|
||||
count: number
|
||||
standings: TeamStandingRaw[]
|
||||
} = await response.json()
|
||||
const standings: TeamStandingRaw[] = standingsResponse.standings
|
||||
|
||||
return standings.map(normalizeStanding)
|
||||
}
|
||||
|
||||
function normalizeStanding(standing: TeamStandingRaw): TeamStanding {
|
||||
const totalGamesPlayed = standing.wins + standing.losses
|
||||
// round win percentage to 3 decimal places
|
||||
const winPercentage: string = totalGamesPlayed ? `${Math.round(standing.wins / totalGamesPlayed * 1000) / 1000}%` : '-'
|
||||
|
||||
const formattedRunDiff = `${standing.run_diff > 0 ? '+' : ''}${standing.run_diff}`
|
||||
const isWildcardTeam = standing.wc_gb !== null || standing.wc_e_num !== null
|
||||
|
||||
return {
|
||||
teamName: standing.team.sname,
|
||||
teamAbbreviation: standing.team.abbrev,
|
||||
divisionAbbreviation: standing.team.division.division_abbrev,
|
||||
leagueAbbreviation: standing.team.division.league_abbrev,
|
||||
wins: standing.wins,
|
||||
losses: standing.losses,
|
||||
winPercentage,
|
||||
last8Record: `${standing.last8_wins}-${standing.last8_losses}`,
|
||||
streak: `${standing.streak_wl.toUpperCase()}${standing.streak_num}`,
|
||||
divisionGamesBack: parseGamesBack(standing.div_gb),
|
||||
divisionEliminationNumber: parseEliminationNumber(standing.div_e_num),
|
||||
wildcardGamesBack: parseGamesBack(standing.wc_gb),
|
||||
wildcardEliminationNumber: parseEliminationNumber(standing.wc_e_num),
|
||||
runDifferential: formattedRunDiff,
|
||||
isWildcardTeam
|
||||
}
|
||||
}
|
||||
|
||||
function parseGamesBack(gamesBack: number | null): string {
|
||||
if (gamesBack == null) return '-'
|
||||
return `${gamesBack < 0 ? '+' : ''}${Math.abs(gamesBack).toFixed(1)}`
|
||||
}
|
||||
function parseEliminationNumber(eliminationNumber: number | null): string {
|
||||
if (eliminationNumber == null) return '-'
|
||||
return eliminationNumber <= 0 ? 'E' : `${eliminationNumber}`
|
||||
}
|
||||
|
||||
17
src/services/teamsService.ts
Normal file
17
src/services/teamsService.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import type { Team } from './apiResponseTypes'
|
||||
import { SITE_URL } from './utilities'
|
||||
|
||||
export async function fetchTeam(seasonNumber: number, teamAbbreviation: string): Promise<Team> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/teams/?season=${seasonNumber}&team_abbrev=${teamAbbreviation}`)
|
||||
|
||||
const teamResponse: {
|
||||
count: number
|
||||
teams: Team[]
|
||||
} = await response.json()
|
||||
|
||||
if (teamResponse.count !== 1) {
|
||||
throw new Error('teamServices.fetchTeam - Expected one team, return contained none or many')
|
||||
}
|
||||
|
||||
return teamResponse.teams[0]
|
||||
}
|
||||
43
src/services/transactionsService.ts
Normal file
43
src/services/transactionsService.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import type { Team } from './apiResponseTypes'
|
||||
import type { Player } from './playersService'
|
||||
import { SITE_URL } from './utilities'
|
||||
|
||||
export interface Transaction {
|
||||
id: number
|
||||
week: number
|
||||
player: Player
|
||||
oldteam: Team
|
||||
newteam: Team
|
||||
season: number
|
||||
moveid: number
|
||||
cancelled: boolean
|
||||
frozen: boolean
|
||||
}
|
||||
|
||||
export async function fetchTransactionsByTeamAndWeek(seasonNumber: number, teamAbbreviation: string, weekNumber: number): Promise<Transaction[]> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/transactions?season=${seasonNumber}&team_abbrev=${teamAbbreviation}&week_start=${weekNumber}`)
|
||||
|
||||
const transactionsResponse: {
|
||||
count: number
|
||||
transactions: Transaction[]
|
||||
} = await response.json()
|
||||
|
||||
console.log('fetchTransactionsByTeam', seasonNumber, teamAbbreviation, transactionsResponse)
|
||||
|
||||
return transactionsResponse.transactions
|
||||
}
|
||||
|
||||
export async function fetchPlayerByName(seasonNumber: number, playerName: string): Promise<Player> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/players?season=${seasonNumber}&name=${playerName}`)
|
||||
|
||||
const playersResponse: {
|
||||
count: number
|
||||
players: Player[]
|
||||
} = await response.json()
|
||||
|
||||
if (playersResponse.count !== 1) {
|
||||
throw new Error('playersServices.fetchPlayerByName - Expected one player, return contained none or many')
|
||||
}
|
||||
|
||||
return playersResponse.players[0]
|
||||
}
|
||||
3
src/services/utilities.ts
Normal file
3
src/services/utilities.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const SITE_URL = 'https://sba.manticorum.com'
|
||||
|
||||
export const CURRENT_SEASON = 8
|
||||
4
src/shims-vue.d.ts
vendored
Normal file
4
src/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module "*.vue" {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
||||
92
src/views/HomeView.vue
Normal file
92
src/views/HomeView.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<main class="home-view">
|
||||
<TheWelcome />
|
||||
|
||||
<h1>Season {{ seasonNumber }} Standings</h1>
|
||||
<h2 id="week-num">{{ weekNumber ? `Week ${weekNumber}` : '' }}</h2>
|
||||
|
||||
<!-- Division Standings -->
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<h2>American League</h2>
|
||||
<h3>East</h3>
|
||||
<StandingsTable :teams="alEastTeams" :is-divisional=true />
|
||||
<h3>West</h3>
|
||||
<StandingsTable :teams="alWestTeams" :is-divisional=true />
|
||||
<h3>AL Wildcard</h3>
|
||||
<StandingsTable :teams="alWildcardTeams" :is-divisional=false />
|
||||
|
||||
<h2>National League</h2>
|
||||
<h3>East</h3>
|
||||
<StandingsTable :teams="nlEastTeams" :is-divisional=true />
|
||||
<h3>West</h3>
|
||||
<StandingsTable :teams="nlWestTeams" :is-divisional=true />
|
||||
<h3>NL Wildcard</h3>
|
||||
<StandingsTable :teams="nlWildcardTeams" :is-divisional=false />
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<h3>Latest News</h3>
|
||||
<div id="news-posts"></div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import StandingsTable from '@/components/StandingsTable.vue'
|
||||
import { fetchStandings, type TeamStanding } from '@/services/standingsService'
|
||||
import { fetchCurrentLeagueInfo, type LeagueInfo } from '@/services/currentService'
|
||||
import { CURRENT_SEASON } from '@/services/utilities'
|
||||
import TheWelcome from '../components/TheWelcome.vue'
|
||||
|
||||
export default {
|
||||
name: "HomeView",
|
||||
data() {
|
||||
return {
|
||||
seasonNumber: CURRENT_SEASON as number,
|
||||
weekNumber: undefined as number | undefined,
|
||||
teamStandings: [] as TeamStanding[],
|
||||
alEastTeams: [] as TeamStanding[],
|
||||
alWestTeams: [] as TeamStanding[],
|
||||
alWildcardTeams: [] as TeamStanding[],
|
||||
nlEastTeams: [] as TeamStanding[],
|
||||
nlWestTeams: [] as TeamStanding[],
|
||||
nlWildcardTeams: [] as TeamStanding[],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
async fetchData(): Promise<void> {
|
||||
const leagueInfo: LeagueInfo = await fetchCurrentLeagueInfo()
|
||||
this.weekNumber = leagueInfo.week
|
||||
|
||||
// TODO CHANGE THIS
|
||||
this.teamStandings = await fetchStandings(CURRENT_SEASON - 1)
|
||||
this.alEastTeams = this.teamStandings.filter(ts => ts.divisionAbbreviation === 'E' && ts.leagueAbbreviation === 'AL')
|
||||
this.alWestTeams = this.teamStandings.filter(ts => ts.divisionAbbreviation === 'W' && ts.leagueAbbreviation === 'AL')
|
||||
this.nlEastTeams = this.teamStandings.filter(ts => ts.divisionAbbreviation === 'E' && ts.leagueAbbreviation === 'NL')
|
||||
this.nlWestTeams = this.teamStandings.filter(ts => ts.divisionAbbreviation === 'W' && ts.leagueAbbreviation === 'NL')
|
||||
this.alWildcardTeams = this.teamStandings.filter(ts => ts.leagueAbbreviation === 'AL' && ts.isWildcardTeam)
|
||||
this.nlWildcardTeams = this.teamStandings.filter(ts => ts.leagueAbbreviation === 'NL' && ts.isWildcardTeam)
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.column {
|
||||
flex-basis: 50%;
|
||||
/* Sets the initial width of each column to 50% */
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
/* Includes padding within the width of each column */
|
||||
}
|
||||
</style>
|
||||
118
src/views/ManagerView.vue
Normal file
118
src/views/ManagerView.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="manager-view centerDiv">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h1 id="manager-name">{{ managerName }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<h3 id="manager-record">Career Record: 294-218</h3>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<p id="manager-headline"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<h3 style="text-align: center">Teams Managed</h3>
|
||||
<div class="table-responsive-xl">
|
||||
<table style="text-align: center" class="table table-sm table-striped" id="manager-teams-table">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Season</th>
|
||||
<th>Team</th>
|
||||
<th>Record</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td><a href="/teams?abbrev=TK&season=7">Tokyo Kaiju</a></td>
|
||||
<td id="season-7-record">47-41</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td><a href="/teams?abbrev=TK&season=6">Tokyo Kaiju</a></td>
|
||||
<td id="season-6-record">51-37</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td><a href="/teams?abbrev=TK&season=5">Tokyo Kaiju</a></td>
|
||||
<td id="season-5-record">55-33</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td><a href="/teams?abbrev=TK&season=4">Tokyo Kaiju</a></td>
|
||||
<td id="season-4-record">55-33</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td><a href="/teams?abbrev=TK&season=3">Tokyo Kaiju</a></td>
|
||||
<td id="season-3-record">49-39</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td><a href="/teams?abbrev=TK&season=2">Tokyo Kaiju</a></td>
|
||||
<td id="season-2-record">37-35</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="manager-teams"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-5">
|
||||
<h3 style="text-align: center">Awards Received</h3>
|
||||
<div class="table-responsive-xl">
|
||||
<table style="text-align: center" class="table table-sm table-striped" id="manager-awards-table">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Season</th>
|
||||
<th>Award</th>
|
||||
<th>Extras</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>AL Wildcard</td>
|
||||
<td><a href="/teams?abbrev=TK&season=3">Tokyo Kaiju</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Most Hated Ballpark</td>
|
||||
<td><a href="/teams?abbrev=TK&season=2">Tokyo Kaiju</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>American League Pennant</td>
|
||||
<td><a href="/teams?abbrev=TK&season=2">Tokyo Kaiju</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>AL East Leader</td>
|
||||
<td><a href="/teams?abbrev=TK&season=2">Tokyo Kaiju</a></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="manager-awards"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<h3 style="text-align: center" id="manager-bio-header"></h3>
|
||||
<p id="manager-bio"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
export default {
|
||||
name: "ManagerView",
|
||||
props: {
|
||||
managerName: { type: String, required: true },
|
||||
}
|
||||
}
|
||||
</script>
|
||||
1231
src/views/PlayerView.vue
Normal file
1231
src/views/PlayerView.vue
Normal file
File diff suppressed because it is too large
Load Diff
263
src/views/TeamView.vue
Normal file
263
src/views/TeamView.vue
Normal file
@ -0,0 +1,263 @@
|
||||
<template>
|
||||
<div class="team-view centerDiv">
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<h1 id="team-record">{{ teamName }}</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)">
|
||||
<td>{{ player.pos_1 }}</td>
|
||||
<td>
|
||||
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
|
||||
{{ player.name }}
|
||||
</RouterLink>
|
||||
</td>
|
||||
<td>{{ player.wara }}</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 class="col-sm-6">
|
||||
|
||||
<h3 id="minors-header">{{ 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>WARa</th>
|
||||
<th>Inj Return</th>
|
||||
<th>Positions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="minors-roster">
|
||||
<tr v-for="player in sortedPlayers(playersMinors)">
|
||||
<td>{{ player.pos_1 }}</td>
|
||||
<td>
|
||||
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
|
||||
{{ player.name }}
|
||||
</RouterLink>
|
||||
</td>
|
||||
<td>{{ player.wara }}</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>WARa</th>
|
||||
<th>Inj Return</th>
|
||||
<th>Positions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="short-il-roster">
|
||||
<tr v-for="player in sortedPlayers(playersInjuredList)">
|
||||
<td>{{ player.pos_1 }}</td>
|
||||
<td>
|
||||
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
|
||||
{{ player.name }}
|
||||
</RouterLink>
|
||||
</td>
|
||||
<td>{{ player.wara }}</td>
|
||||
<td>{{ player.il_return }}</td>
|
||||
<td>{{ allPositions(player) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<td>{{ row.week }}</td>
|
||||
<td>{{ row.playerName }}</td>
|
||||
<td>{{ row.oldTeam }}</td>
|
||||
<td>{{ row.newTeam }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { Team } from '@/services/apiResponseTypes'
|
||||
import { fetchCurrentLeagueInfo } 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'
|
||||
|
||||
export default {
|
||||
name: "TeamView",
|
||||
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
|
||||
}
|
||||
},
|
||||
props: {
|
||||
seasonNumber: { type: Number, required: true },
|
||||
teamAbbreviation: { type: String, required: true },
|
||||
},
|
||||
computed: {
|
||||
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
|
||||
},
|
||||
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
|
||||
},
|
||||
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()
|
||||
},
|
||||
methods: {
|
||||
async fetchData(): Promise<void> {
|
||||
this.team = await fetchTeam(this.seasonNumber, this.teamAbbreviation)
|
||||
this.teamMinors = await fetchTeam(this.seasonNumber, `${this.teamAbbreviation}MiL`)
|
||||
this.teamInjuredList = await fetchTeam(this.seasonNumber, `${this.teamAbbreviation}IL`)
|
||||
|
||||
this.teamStanding = (await fetchStandings(this.seasonNumber - 1)).find(ts => ts.teamName === this.team?.sname)
|
||||
this.weekNumber = (await fetchCurrentLeagueInfo()).week
|
||||
|
||||
this.players = await fetchPlayersByTeam(this.seasonNumber, this.team?.id)
|
||||
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!))
|
||||
console.log(this.transactions)
|
||||
},
|
||||
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.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>
|
||||
8
tsconfig.config.json
Normal file
8
tsconfig.config.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
||||
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.config.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
20
vite.config.ts
Normal file
20
vite.config.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
Components({
|
||||
resolvers: [NaiveUiResolver()]
|
||||
})],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
}
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user