Uppdating typescript tuff to allow it t build
This commit is contained in:
@@ -8,8 +8,6 @@ import { addCharacterApis } from './characterservice'
|
|||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
const jsonParser = json()
|
const jsonParser = json()
|
||||||
const fp = new FilterParser()
|
|
||||||
const obp = new OrderByParser()
|
|
||||||
const port = 3001
|
const port = 3001
|
||||||
|
|
||||||
app.get('/', (req, res) => {
|
app.get('/', (req, res) => {
|
||||||
|
|||||||
29
frontend/dist/assets/index-BJnL3x4A.js
vendored
29
frontend/dist/assets/index-BJnL3x4A.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
47
frontend/dist/assets/index-a76aODRT.js
vendored
Normal file
47
frontend/dist/assets/index-a76aODRT.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
frontend/dist/index.html
vendored
4
frontend/dist/index.html
vendored
@@ -13,8 +13,8 @@
|
|||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Welcome to Vuetify 3</title>
|
<title>Welcome to Vuetify 3</title>
|
||||||
<script type="module" crossorigin src="/assets/index-BJnL3x4A.js"></script>
|
<script type="module" crossorigin src="/assets/index-a76aODRT.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-Iv1C9NNg.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-CouD1jr_.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
// Plugins
|
// Plugins
|
||||||
import vuetify from './vuetify'
|
import vuetify from './vuetify'
|
||||||
import pinia from '../store'
|
|
||||||
import router from '../router'
|
import router from '../router'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import type { App } from 'vue'
|
import type { App } from 'vue'
|
||||||
|
|
||||||
export function registerPlugins(app: App) {
|
export function registerPlugins(app: App) {
|
||||||
app.use(vuetify).use(router).use(pinia)
|
app.use(vuetify).use(router)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# Store
|
|
||||||
|
|
||||||
Pinia stores are used to store reactive state and expose actions to mutate it.
|
|
||||||
|
|
||||||
Full documentation for this feature can be found in the Official [Pinia](https://pinia.esm.dev/) repository.
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Utilities
|
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useAppStore = defineStore('app', {
|
|
||||||
state: () => ({
|
|
||||||
//
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export enum CharacterStatus {
|
|
||||||
Active = 'Active',
|
|
||||||
Inactive = 'Inactive',
|
|
||||||
Dead = 'Dead',
|
|
||||||
Retired = 'Retired'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Character = {
|
|
||||||
status: CharacterStatus
|
|
||||||
playerName: string
|
|
||||||
characterName: string
|
|
||||||
role: String
|
|
||||||
approvalDate: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGameStore = defineStore('characters', {
|
|
||||||
state: () => {
|
|
||||||
return {
|
|
||||||
games: [{} as Character, {} as Character, {} as Character]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {}
|
|
||||||
})
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export enum GameStatus {
|
|
||||||
Complete = 'Complete',
|
|
||||||
Postponed = 'Postponed',
|
|
||||||
Pending = 'Pending'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Game = {
|
|
||||||
potato: string
|
|
||||||
alsoPotato: string
|
|
||||||
title: string
|
|
||||||
status: GameStatus
|
|
||||||
fix: boolean
|
|
||||||
datePosted: Date
|
|
||||||
dateRun: Date
|
|
||||||
gmPlayerName: string
|
|
||||||
charactersPicked: []
|
|
||||||
charactersApplied: []
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useGameStore = defineStore('games', {
|
|
||||||
state: () => {
|
|
||||||
return {
|
|
||||||
count: 0,
|
|
||||||
games: [
|
|
||||||
{ potato: 'potato', alsoPotato: 'potato' } as Game,
|
|
||||||
{ potato: 'potato', alsoPotato: 'potato' } as Game,
|
|
||||||
{ potato: 'potato', alsoPotato: 'potato' } as Game
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
increment() {
|
|
||||||
this.count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Utilities
|
|
||||||
import { createPinia } from 'pinia'
|
|
||||||
|
|
||||||
export default createPinia()
|
|
||||||
61
frontend/src/types.ts
Normal file
61
frontend/src/types.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
export interface Game {
|
||||||
|
id: number
|
||||||
|
title: string
|
||||||
|
gamemaster: string
|
||||||
|
payoutEB: number
|
||||||
|
payoutIP: number
|
||||||
|
payoutLoot: string
|
||||||
|
status: string
|
||||||
|
postdate: number
|
||||||
|
pickedCharacter?: Character[]
|
||||||
|
appliedCharacter?: Character[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Character {
|
||||||
|
id: number
|
||||||
|
characterName: string
|
||||||
|
playerName: string
|
||||||
|
role: string
|
||||||
|
status: string
|
||||||
|
lastGame: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GameStats {
|
||||||
|
Complete: number
|
||||||
|
Postponed: number
|
||||||
|
Pending: number
|
||||||
|
Fixes: number
|
||||||
|
Events: number
|
||||||
|
AverageIP: number
|
||||||
|
AverageEB: number
|
||||||
|
TotalIP: number,
|
||||||
|
TotalEB: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GameCounts {
|
||||||
|
apps: number
|
||||||
|
picks: number
|
||||||
|
active: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GameCharacter {
|
||||||
|
characterId: number
|
||||||
|
characterName: string
|
||||||
|
gameId: number
|
||||||
|
gameTite: string
|
||||||
|
pickedCharacter?:Character
|
||||||
|
appliedCharacter?: Character
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoleStats {
|
||||||
|
Fixer: GameCounts
|
||||||
|
Tech: GameCounts
|
||||||
|
Medtech: GameCounts
|
||||||
|
Media: GameCounts
|
||||||
|
Netrunner: GameCounts
|
||||||
|
Solo: GameCounts
|
||||||
|
Nomad: GameCounts
|
||||||
|
Exec: GameCounts
|
||||||
|
Lawman: GameCounts
|
||||||
|
Rocker: GameCounts
|
||||||
|
}
|
||||||
@@ -33,22 +33,30 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Character, Game } from '../types'
|
||||||
import GameTable from './GameTable.vue'
|
import GameTable from './GameTable.vue'
|
||||||
import { onMounted, watch, ref } from 'vue'
|
import { onMounted, watch, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
interface GameList {
|
||||||
|
played: Game[]
|
||||||
|
applied: Game[]
|
||||||
|
}
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const characterId = ref(route.params.characterId)
|
const characterId = ref(route.params.characterId)
|
||||||
const character = ref({})
|
const character = ref<Character>({
|
||||||
const games = ref({})
|
id: 0, characterName: "", playerName: "", role: "", status: "", lastGame: 0
|
||||||
|
})
|
||||||
|
const games = ref<GameList>({played:[], applied: []})
|
||||||
const earnedEB = ref(0)
|
const earnedEB = ref(0)
|
||||||
const earnedIP = ref(0)
|
const earnedIP = ref(0)
|
||||||
const gamesPlayedCount = ref(0)
|
const gamesPlayedCount = ref(0)
|
||||||
const gamesAppliedCount = ref(0)
|
const gamesAppliedCount = ref(0)
|
||||||
const pickRate = ref(0)
|
const pickRate = ref(0)
|
||||||
const lastPlayedPostDate = ref({ played: [], applied: [] })
|
const lastPlayedPostDate = ref()
|
||||||
|
|
||||||
async function loadCharacterDetails() {
|
async function loadCharacterDetails() {
|
||||||
const characterResponse = await axios.get(`/api/character/${characterId.value}`)
|
const characterResponse = await axios.get(`/api/character/${characterId.value}`)
|
||||||
@@ -61,7 +69,7 @@ async function loadCharacterDetails() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateDerivedEarnings(gamesPlayedList) {
|
function calculateDerivedEarnings(gamesPlayedList: Game[]) {
|
||||||
let runningEarnedEb = 0
|
let runningEarnedEb = 0
|
||||||
let runningEarnedIp = 0
|
let runningEarnedIp = 0
|
||||||
for (let game in gamesPlayedList) {
|
for (let game in gamesPlayedList) {
|
||||||
@@ -72,13 +80,13 @@ function calculateDerivedEarnings(gamesPlayedList) {
|
|||||||
earnedIP.value = runningEarnedIp
|
earnedIP.value = runningEarnedIp
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateDerivedGameStats(gamesPlayedList, gamesAppliedList) {
|
function calculateDerivedGameStats(gamesPlayedList: Game[], gamesAppliedList: Game[]) {
|
||||||
gamesPlayedCount.value = gamesPlayedList.length
|
gamesPlayedCount.value = gamesPlayedList.length
|
||||||
gamesAppliedCount.value = gamesAppliedList.length
|
gamesAppliedCount.value = gamesAppliedList.length
|
||||||
pickRate.value = (gamesPlayedList.length / gamesAppliedList.length) * 100
|
pickRate.value = (gamesPlayedList.length / gamesAppliedList.length) * 100
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateDerivedLastPlayedPostDate(gamesPlayedList) {
|
function calculateDerivedLastPlayedPostDate(gamesPlayedList: Game[]) {
|
||||||
if (gamesPlayedList.length === 0) {
|
if (gamesPlayedList.length === 0) {
|
||||||
lastPlayedPostDate.value = 'N/A'
|
lastPlayedPostDate.value = 'N/A'
|
||||||
} else {
|
} else {
|
||||||
@@ -88,7 +96,7 @@ function calculateDerivedLastPlayedPostDate(gamesPlayedList) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(games, (newValue, oldValue) => {
|
watch(games, (newValue: GameList, oldValue: GameList) => {
|
||||||
calculateDerivedLastPlayedPostDate(newValue.played)
|
calculateDerivedLastPlayedPostDate(newValue.played)
|
||||||
calculateDerivedEarnings(newValue.played)
|
calculateDerivedEarnings(newValue.played)
|
||||||
calculateDerivedGameStats(newValue.played, newValue.applied)
|
calculateDerivedGameStats(newValue.played, newValue.applied)
|
||||||
|
|||||||
@@ -43,13 +43,15 @@
|
|||||||
<style type="text/css"></style>
|
<style type="text/css"></style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onCreated, ref } from 'vue'
|
import { Character } from '../types'
|
||||||
|
import { onMounted, ref, watch } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const characters = ref({})
|
const characters = ref<Character[]>([])
|
||||||
const pageCount = ref(1)
|
const pageCount = ref(1)
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
|
|
||||||
@@ -84,9 +86,9 @@ watch(route, (newValue, oldValue) => {
|
|||||||
loadData()
|
loadData()
|
||||||
})
|
})
|
||||||
|
|
||||||
let debounce = null
|
let debounce: ReturnType<typeof setTimeout>
|
||||||
watch(filtervalue, (newFilter, oldFilter) => {
|
watch(filtervalue, (newFilter: string, oldFilter: string) => {
|
||||||
debounce = clearTimeout(debounce)
|
clearTimeout(debounce)
|
||||||
debounce = setTimeout(() => {
|
debounce = setTimeout(() => {
|
||||||
router.replace({ query: { page: route.query.page, filter: newFilter } })
|
router.replace({ query: { page: route.query.page, filter: newFilter } })
|
||||||
}, 500)
|
}, 500)
|
||||||
@@ -100,7 +102,7 @@ onMounted(async () => {
|
|||||||
page.value = Number(route.query.page)
|
page.value = Number(route.query.page)
|
||||||
}
|
}
|
||||||
if (route.query.filter) {
|
if (route.query.filter) {
|
||||||
filtervalue.value = route.query.filter
|
filtervalue.value = route.query.filter.toString()
|
||||||
}
|
}
|
||||||
loadData()
|
loadData()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="game-title-box">
|
<v-container>
|
||||||
<h1>#{{ game.id }} - {{ game.title }}</h1>
|
<h1>#{{ game.id }} - {{ game.title }}</h1>
|
||||||
</div>
|
|
||||||
<div class="gm-title-box">
|
|
||||||
<h2>GameMaster: {{ game.gamemaster }}</h2>
|
<h2>GameMaster: {{ game.gamemaster }}</h2>
|
||||||
</div>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="d-flex flex-row">
|
<div class="d-flex flex-row">
|
||||||
<div class="result-box">
|
<div class="result-box">
|
||||||
<h3>Picks</h3>
|
<h3>Picks</h3>
|
||||||
<div v-for="pick in picks">
|
<div v-for="pick in picks">
|
||||||
{{ pick.pickedCharacter.playerName }} as {{ pick.characterName }}
|
{{ pick.pickedCharacter!.playerName }} as {{ pick.characterName }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="result-box">
|
<div class="result-box">
|
||||||
<h3>Payout</h3>
|
<h3>Payout</h3>
|
||||||
<div>{{ game.payoutEB }} eb</div>
|
<div>{{ game.payoutEB }} EB</div>
|
||||||
<div>{{ game.payoutIP }} IP</div>
|
<div>{{ game.payoutIP }} IP</div>
|
||||||
<div>{{ game.payoutLoot }}</div>
|
<div>{{ game.payoutLoot }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +44,8 @@
|
|||||||
</v-data-table-virtual>
|
</v-data-table-virtual>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div></v-container
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -75,20 +73,24 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Game, Character, GameCharacter } from '../types'
|
||||||
import { watch, ref } from 'vue'
|
import { watch, ref } from 'vue'
|
||||||
|
import { VDataTable } from 'vuetify/components'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
type ReadonlyHeaders = VDataTable['$props']['headers']
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const pickHeaders = [
|
const pickHeaders: ReadonlyHeaders = [
|
||||||
{ title: 'ID', align: 'start', key: 'characterId' },
|
{ title: 'ID', align: 'start', key: 'characterId' },
|
||||||
{ title: 'Character', align: 'start', key: 'characterName' },
|
{ title: 'Character', align: 'start', key: 'characterName' },
|
||||||
{ title: 'Status', align: 'start', key: 'pickedCharacter.status' },
|
{ title: 'Status', align: 'start', key: 'pickedCharacter.status' },
|
||||||
{ title: 'Player', align: 'start', key: 'pickedCharacter.playerName' }
|
{ title: 'Player', align: 'start', key: 'pickedCharacter.playerName' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const appHeaders = [
|
const appHeaders: ReadonlyHeaders = [
|
||||||
{ title: 'ID', align: 'start', key: 'characterId' },
|
{ title: 'ID', align: 'start', key: 'characterId' },
|
||||||
{ title: 'Character', align: 'start', key: 'characterName' },
|
{ title: 'Character', align: 'start', key: 'characterName' },
|
||||||
{ title: 'Status', align: 'start', key: 'appliedCharacter.status' },
|
{ title: 'Status', align: 'start', key: 'appliedCharacter.status' },
|
||||||
@@ -96,9 +98,18 @@ const appHeaders = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const gameId = ref(route.params.gameId)
|
const gameId = ref(route.params.gameId)
|
||||||
const game = ref({})
|
const game = ref<Game>({
|
||||||
const picks = ref([])
|
id: 0,
|
||||||
const apps = ref([])
|
title: "",
|
||||||
|
gamemaster: "",
|
||||||
|
payoutEB: 0,
|
||||||
|
payoutIP: 0,
|
||||||
|
payoutLoot: "",
|
||||||
|
status: "",
|
||||||
|
postdate: 0
|
||||||
|
})
|
||||||
|
const picks = ref<GameCharacter[]>([])
|
||||||
|
const apps = ref<GameCharacter[]>([])
|
||||||
|
|
||||||
loadGameDetails()
|
loadGameDetails()
|
||||||
|
|
||||||
|
|||||||
@@ -47,20 +47,22 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Game } from '../types'
|
||||||
import GameTable from './GameTable.vue'
|
import GameTable from './GameTable.vue'
|
||||||
import { onMounted, watch, ref } from 'vue'
|
import { onMounted, watch, ref } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const games = ref({})
|
const games = ref<Game[]>([])
|
||||||
let page = ref(1)
|
let page = ref(1)
|
||||||
const pageCount = ref(1)
|
const pageCount = ref(1)
|
||||||
|
|
||||||
let count = 10
|
let count = 10
|
||||||
|
|
||||||
const filtervalue = ref('')
|
const filtervalue = ref<string>('')
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
const response = await axios.post('/api/game', {
|
const response = await axios.post('/api/game', {
|
||||||
@@ -87,14 +89,14 @@ watch(route, (newValue, oldValue) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (route.query.filter) {
|
if (route.query.filter) {
|
||||||
filtervalue.value = route.query.filter
|
filtervalue.value = route.query.filter.toString()
|
||||||
}
|
}
|
||||||
loadData()
|
loadData()
|
||||||
})
|
})
|
||||||
|
|
||||||
let debounce = null
|
let debounce: ReturnType<typeof setTimeout>
|
||||||
watch(filtervalue, (newFilter, oldFilter) => {
|
watch(filtervalue, (newFilter: string, oldFilter: string) => {
|
||||||
debounce = clearTimeout(debounce)
|
clearTimeout(debounce)
|
||||||
debounce = setTimeout(() => {
|
debounce = setTimeout(() => {
|
||||||
router.replace({ query: { page: route.query.page, filter: newFilter } })
|
router.replace({ query: { page: route.query.page, filter: newFilter } })
|
||||||
}, 500)
|
}, 500)
|
||||||
@@ -108,7 +110,7 @@ onMounted(async () => {
|
|||||||
page.value = Number(route.query.page)
|
page.value = Number(route.query.page)
|
||||||
}
|
}
|
||||||
if (route.query.filter) {
|
if (route.query.filter) {
|
||||||
filtervalue.value = route.query.filter
|
filtervalue.value = route.query.filter.toString()
|
||||||
}
|
}
|
||||||
loadData()
|
loadData()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,12 +15,22 @@
|
|||||||
<style></style>
|
<style></style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const props = defineProps(['gameList'])
|
import { Game } from '../types'
|
||||||
|
import { defineProps } from 'vue'
|
||||||
|
import { VDataTable } from 'vuetify/components'
|
||||||
|
|
||||||
const headers = [
|
type ReadonlyHeaders = VDataTable['$props']['headers']
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
gameList: Game[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const headers: ReadonlyHeaders = [
|
||||||
{ title: 'ID', align: 'start', key: 'id' },
|
{ title: 'ID', align: 'start', key: 'id' },
|
||||||
{ title: 'Title', align: 'start', key: 'title' },
|
{ title: 'Title', align: 'start', key: 'title' },
|
||||||
{ title: 'Status', aligasdfn: 'start', key: 'status' },
|
{ title: 'Status', align: 'start', key: 'status' },
|
||||||
{ title: 'Post Date', align: 'start', key: 'postdate' }
|
{ title: 'Post Date', align: 'start', key: 'postdate' }
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -92,31 +92,91 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { GameStats, RoleStats } from '../types'
|
||||||
import { onMounted, watch, ref } from 'vue'
|
import { onMounted, watch, ref } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import Chart from 'chart.js/auto'
|
import Chart from 'chart.js/auto'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
type ChartType = 'gametypes' | 'apps' | 'picks' | 'active'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const dateSelect = ref(-1)
|
const dateSelect = ref(-1)
|
||||||
|
|
||||||
const dateItems = buildDateItems()
|
const dateItems = buildDateItems()
|
||||||
|
const chartSelect = ref<ChartType>('active')
|
||||||
const chartSelect = ref('active')
|
|
||||||
|
|
||||||
const chartItems = [
|
const chartItems = [
|
||||||
{ title: 'Game Types', value: 'gametypes' },
|
{ title: 'Game Types', value: 'gametypes' },
|
||||||
{ title: 'Active Characters', value: 'active' },
|
{ title: 'Active Characters', value: 'active' },
|
||||||
{ title: 'Role Picks', value: 'picks' },
|
{ title: 'Role Picks', value: 'picks' },
|
||||||
{ title: 'Role Applications', value: 'apps' }
|
{ title: 'Role Applications', value: 'apps' }
|
||||||
]
|
]
|
||||||
|
const gameStats = ref<GameStats>({
|
||||||
|
Complete: 0,
|
||||||
|
Postponed: 0,
|
||||||
|
Pending: 0,
|
||||||
|
Fixes: 0,
|
||||||
|
Events: 0,
|
||||||
|
AverageIP: 0,
|
||||||
|
AverageEB: 0,
|
||||||
|
TotalIP: 0,
|
||||||
|
TotalEB: 0
|
||||||
|
})
|
||||||
|
const roleStats = ref<RoleStats>({
|
||||||
|
Fixer: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Tech: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Medtech: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Media: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Netrunner: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Solo: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Nomad: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Exec: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Lawman: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
},
|
||||||
|
Rocker: {
|
||||||
|
apps: 0,
|
||||||
|
picks: 0,
|
||||||
|
active: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const gameStats = ref({})
|
let chart: Chart<'pie', number[], string>
|
||||||
|
|
||||||
const roleStats = ref({})
|
|
||||||
|
|
||||||
let chart
|
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
const gameStatsResponse = await axios.post('/api/serverstats/gamestats', {
|
const gameStatsResponse = await axios.post('/api/serverstats/gamestats', {
|
||||||
@@ -155,7 +215,7 @@ function dateToMonthId(date: Date) {
|
|||||||
return (date.getUTCFullYear() - 2023) * 12 + date.getUTCMonth()
|
return (date.getUTCFullYear() - 2023) * 12 + date.getUTCMonth()
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateChart(stats, tag) {
|
function updateChart(stats: RoleStats, tag: ChartType) {
|
||||||
if (tag === 'gametypes') {
|
if (tag === 'gametypes') {
|
||||||
chart.data = {
|
chart.data = {
|
||||||
labels: ['Standard', 'Postponed', 'Pending', 'Event', 'Fix'],
|
labels: ['Standard', 'Postponed', 'Pending', 'Event', 'Fix'],
|
||||||
@@ -195,7 +255,7 @@ watch(roleStats, async (newValue, oldValue) => {
|
|||||||
updateChart(newValue, chartSelect.value)
|
updateChart(newValue, chartSelect.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(chartSelect, async (newValue, oldValue) => {
|
watch(chartSelect, async (newValue: ChartType, oldValue: ChartType) => {
|
||||||
updateChart(roleStats.value, newValue)
|
updateChart(roleStats.value, newValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -207,7 +267,7 @@ onMounted(async () => {
|
|||||||
dateSelect.value = Number(route.query.monthId)
|
dateSelect.value = Number(route.query.monthId)
|
||||||
}
|
}
|
||||||
loadData()
|
loadData()
|
||||||
chart = new Chart(document.getElementById('piechart'), {
|
chart = new Chart(document.getElementById('piechart')! as HTMLCanvasElement, {
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
data: {
|
data: {
|
||||||
labels: [],
|
labels: [],
|
||||||
|
|||||||
Reference in New Issue
Block a user