mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
feat: add select input in champions tab to change queue
This commit is contained in:
parent
a8b49a6548
commit
541d6395b1
9 changed files with 116 additions and 39 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="hidden">
|
<svg xmlns="http://www.w3.org/2000/svg" class="hidden">
|
||||||
<symbol id="caret-down" class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" /></symbol>
|
<symbol id="caret-down" class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" /></symbol>
|
||||||
<symbol id="caret-up" class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M288.662 352H31.338c-17.818 0-26.741-21.543-14.142-34.142l128.662-128.662c7.81-7.81 20.474-7.81 28.284 0l128.662 128.662c12.6 12.599 3.676 34.142-14.142 34.142z"></path></symbol>
|
<symbol id="caret-up" class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M288.662 352H31.338c-17.818 0-26.741-21.543-14.142-34.142l128.662-128.662c7.81-7.81 20.474-7.81 28.284 0l128.662 128.662c12.6 12.599 3.676 34.142-14.142 34.142z"></path></symbol>
|
||||||
|
<symbol id="chevron-down" class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"> <path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /></symbol>
|
||||||
<symbol id="layers" class="stroke-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></symbol>
|
<symbol id="layers" class="stroke-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></symbol>
|
||||||
<symbol id="people" class="stroke-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /> <circle cx="9" cy="7" r="4" /> <path d="M23 21v-2a4 4 0 0 0-3-3.87" /> <path d="M16 3.13a4 4 0 0 1 0 7.75" /> </symbol>
|
<symbol id="people" class="stroke-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /> <circle cx="9" cy="7" r="4" /> <path d="M23 21v-2a4 4 0 0 0-3-3.87" /> <path d="M16 3.13a4 4 0 0 1 0 7.75" /> </symbol>
|
||||||
<symbol id="graph" class="stroke-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="20" x2="18" y2="10" /> <line x1="12" y1="20" x2="12" y2="4" /> <line x1="6" y1="20" x2="6" y2="14" /> </symbol>
|
<symbol id="graph" class="stroke-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="20" x2="18" y2="10" /> <line x1="12" y1="20" x2="12" y2="4" /> <line x1="6" y1="20" x2="6" y2="14" /> </symbol>
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,9 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
champions() {
|
||||||
|
this.updateChampionsList()
|
||||||
|
},
|
||||||
search() {
|
search() {
|
||||||
this.championsToDisplay = this.championsFull.filter(c => {
|
this.championsToDisplay = this.championsFull.filter(c => {
|
||||||
return c.champion.name.toLowerCase().includes(this.search.toLowerCase())
|
return c.champion.name.toLowerCase().includes(this.search.toLowerCase())
|
||||||
|
|
@ -188,19 +191,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.championsFull = this.champions.map((champ, index) => {
|
this.updateChampionsList()
|
||||||
return {
|
|
||||||
...champ,
|
|
||||||
winrate: champ.wins * 100 / champ.count,
|
|
||||||
playrate: champ.count * 100 / this.totalGames,
|
|
||||||
kda: (champ.kills + champ.assists) / champ.deaths,
|
|
||||||
index,
|
|
||||||
lastPlayed: timeDifference(champ.date),
|
|
||||||
show: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.championsToDisplay = this.championsFull
|
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -240,6 +231,21 @@ export default {
|
||||||
'sorted-asc': this.sortProps === props && this.order === 1,
|
'sorted-asc': this.sortProps === props && this.order === 1,
|
||||||
'sorted-desc': this.sortProps === props && this.order === -1,
|
'sorted-desc': this.sortProps === props && this.order === -1,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
updateChampionsList() {
|
||||||
|
this.championsFull = this.champions.map((champ, index) => {
|
||||||
|
return {
|
||||||
|
...champ,
|
||||||
|
winrate: champ.wins * 100 / champ.count,
|
||||||
|
playrate: champ.count * 100 / this.totalGames,
|
||||||
|
kda: (champ.kills + champ.assists) / champ.deaths,
|
||||||
|
index,
|
||||||
|
lastPlayed: timeDifference(champ.date),
|
||||||
|
show: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.championsToDisplay = this.championsFull
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
45
client/src/components/Summoner/Champions/FilterQueue.vue
Normal file
45
client/src/components/Summoner/Champions/FilterQueue.vue
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<template>
|
||||||
|
<div class="relative inline-block text-white">
|
||||||
|
<select
|
||||||
|
v-model="queue"
|
||||||
|
@change="filterQueue"
|
||||||
|
class="block appearance-none bg-blue-800 hover:bg-blue-700 w-full px-4 py-2 pr-8 rounded-md font-semibold lowercase cursor-pointer focus:outline-none"
|
||||||
|
>
|
||||||
|
<option v-for="(key) in Object.keys(choices)" :key="key" :value="key">{{ choices[key].name }}</option>
|
||||||
|
</select>
|
||||||
|
<div
|
||||||
|
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||||
|
>
|
||||||
|
<svg class="text-white w-5 h-5">
|
||||||
|
<use xlink:href="#chevron-down" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
choices: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
queue: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
// Show all queues when loading the page
|
||||||
|
this.queue = -1
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
filterQueue() {
|
||||||
|
this.$emit('filter-queue', this.queue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -18,7 +18,10 @@
|
||||||
class="ml-2 text-teal-500 text-3xl uppercase font-extrabold"
|
class="ml-2 text-teal-500 text-3xl uppercase font-extrabold"
|
||||||
>{{ selectedLeague.fullRank }}</div>
|
>{{ selectedLeague.fullRank }}</div>
|
||||||
<div class="ml-4 text-2xl font-extrabold">{{ selectedLeague.leaguePoints }} LP</div>
|
<div class="ml-4 text-2xl font-extrabold">{{ selectedLeague.leaguePoints }} LP</div>
|
||||||
<div v-if="selectedLeague.miniSeries" class="ml-2 flex items-center p-2 bg-blue-800 rounded ">
|
<div
|
||||||
|
v-if="selectedLeague.miniSeries"
|
||||||
|
class="ml-2 flex items-center p-2 bg-blue-800 rounded"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(result, index) in bo"
|
v-for="(result, index) in bo"
|
||||||
:key="index + result"
|
:key="index + result"
|
||||||
|
|
@ -42,12 +45,8 @@
|
||||||
<div
|
<div
|
||||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||||
>
|
>
|
||||||
<svg
|
<svg class="text-white w-5 h-5">
|
||||||
class="text-white fill-current h-5 w-5"
|
<use xlink:href="#chevron-down" />
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
>
|
|
||||||
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
|
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,12 @@ export const mutations = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
async championStats({ commit }) {
|
async championStats({ commit }, queue = null) {
|
||||||
const resp = await axios(({ url: 'champions', data: { puuid: state.infos.account.puuid }, method: 'POST' })).catch(() => { })
|
if (Number(queue) === -1)
|
||||||
|
queue = null
|
||||||
|
const resp = await axios(({ url: 'champions', data: { puuid: state.infos.account.puuid, queue: queue }, method: 'POST' })).catch(() => { })
|
||||||
console.log('CHAMPIONS STATS')
|
console.log('CHAMPIONS STATS')
|
||||||
|
console.log('queue: ', queue)
|
||||||
console.log(resp.data)
|
console.log(resp.data)
|
||||||
|
|
||||||
commit('CHAMPIONS_FOUND', { champions: resp.data })
|
commit('CHAMPIONS_FOUND', { champions: resp.data })
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="mt-3 min-h-screen">
|
<div class="mt-3">
|
||||||
<ChampionsSearch @search-champions="updateSearch" class="mt-4" />
|
<template v-if="champions.length && championsLoaded">
|
||||||
<ChampionsTable
|
<div class="mt-4 flex items-center">
|
||||||
v-if="champions.length && championsLoaded"
|
<ChampionsSearch @search-champions="updateSearch" />
|
||||||
:champions="champions"
|
<FilterQueue @filter-queue="filterByQueue" :choices="queues" class="ml-4" />
|
||||||
:search="searchChampions"
|
</div>
|
||||||
class="mt-6"
|
<ChampionsTable :champions="champions" :search="searchChampions" class="mt-6" />
|
||||||
/>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapActions, mapState } from 'vuex'
|
import { mapActions, mapState } from 'vuex'
|
||||||
|
import { gameModes } from '@/data/data.js'
|
||||||
import ChampionsSearch from '@/components/Summoner/Champions/ChampionsSearch.vue'
|
import ChampionsSearch from '@/components/Summoner/Champions/ChampionsSearch.vue'
|
||||||
import ChampionsTable from '@/components/Summoner/Champions/ChampionsTable.vue'
|
import ChampionsTable from '@/components/Summoner/Champions/ChampionsTable.vue'
|
||||||
|
import FilterQueue from '@/components/Summoner/Champions/FilterQueue.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ChampionsSearch,
|
ChampionsSearch,
|
||||||
ChampionsTable,
|
ChampionsTable,
|
||||||
|
FilterQueue,
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -30,9 +33,25 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
queues() {
|
||||||
|
// Only keep the gameModes the summoner has played
|
||||||
|
const queues = Object.keys(gameModes)
|
||||||
|
.filter(gameMode =>
|
||||||
|
gameModes[gameMode].type !== 'Bot' &&
|
||||||
|
this.matchList.find(match => match.queue === Number(gameMode))
|
||||||
|
)
|
||||||
|
.reduce((obj, key) => {
|
||||||
|
return {
|
||||||
|
...obj,
|
||||||
|
[key]: gameModes[key]
|
||||||
|
}
|
||||||
|
}, {})
|
||||||
|
return { '-1': { type: 'Normal', name: 'ALL QUEUES' }, ...queues }
|
||||||
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
champions: state => state.summoner.infos.champions,
|
champions: state => state.summoner.infos.champions,
|
||||||
championsLoaded: state => state.summoner.championsLoaded
|
championsLoaded: state => state.summoner.championsLoaded,
|
||||||
|
matchList: state => state.summoner.infos.matchList
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -44,6 +63,9 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
filterByQueue(queue) {
|
||||||
|
this.championStats(queue)
|
||||||
|
},
|
||||||
updateSearch(search) {
|
updateSearch(search) {
|
||||||
this.searchChampions = search
|
this.searchChampions = search
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Jax = use('Jax')
|
const Jax = use('Jax')
|
||||||
|
const MatchRepository = make('App/Repositories/MatchRepository')
|
||||||
const MatchService = use('App/Services/MatchService')
|
const MatchService = use('App/Services/MatchService')
|
||||||
const SummonerService = use('App/Services/SummonerService')
|
const SummonerService = use('App/Services/SummonerService')
|
||||||
const StatsService = use('App/Services/StatsService')
|
const StatsService = use('App/Services/StatsService')
|
||||||
|
|
@ -75,8 +76,9 @@ class SummonerController {
|
||||||
|
|
||||||
async champions({ request, response }) {
|
async champions({ request, response }) {
|
||||||
const puuid = request.input('puuid')
|
const puuid = request.input('puuid')
|
||||||
|
const queue = request.input('queue')
|
||||||
console.time('championsRequest')
|
console.time('championsRequest')
|
||||||
const championStats = await StatsService.getChampionStats(puuid)
|
const championStats = await MatchRepository.championCompleteStats(puuid, queue)
|
||||||
console.timeEnd('championsRequest')
|
console.timeEnd('championsRequest')
|
||||||
return response.json(championStats)
|
return response.json(championStats)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,12 @@ class MatchRepository {
|
||||||
/**
|
/**
|
||||||
* Get Summoner's complete statistics for the all played champs
|
* Get Summoner's complete statistics for the all played champs
|
||||||
* @param puuid of the summoner
|
* @param puuid of the summoner
|
||||||
|
* @param queue of the matches to fetch, if null get all matches
|
||||||
*/
|
*/
|
||||||
championCompleteStats(puuid) {
|
championCompleteStats(puuid, queue) {
|
||||||
|
const matchParams = queue ? {
|
||||||
|
gamemode: { $eq: Number(queue) },
|
||||||
|
} : {}
|
||||||
const groupParams = {
|
const groupParams = {
|
||||||
time: { $sum: "$time" },
|
time: { $sum: "$time" },
|
||||||
gameLength: { $avg: "$time" },
|
gameLength: { $avg: "$time" },
|
||||||
|
|
@ -100,7 +104,7 @@ class MatchRepository {
|
||||||
const finalSteps = [
|
const finalSteps = [
|
||||||
{ $sort: { 'count': -1 } }
|
{ $sort: { 'count': -1 } }
|
||||||
]
|
]
|
||||||
return this._aggregate(puuid, {}, [], '$champion.id', groupParams, finalSteps)
|
return this._aggregate(puuid, matchParams, [], '$champion.id', groupParams, finalSteps)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,6 @@ class StatsService {
|
||||||
this.matchRepository = MatchRepository
|
this.matchRepository = MatchRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChampionStats(puuid) {
|
|
||||||
const championStats = await this.matchRepository.championCompleteStats(puuid)
|
|
||||||
return championStats
|
|
||||||
}
|
|
||||||
|
|
||||||
async getSummonerStats(account) {
|
async getSummonerStats(account) {
|
||||||
const globalStats = await this.matchRepository.globalStats(account.puuid)
|
const globalStats = await this.matchRepository.globalStats(account.puuid)
|
||||||
const gamemodeStats = await this.matchRepository.gamemodeStats(account.puuid)
|
const gamemodeStats = await this.matchRepository.gamemodeStats(account.puuid)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue