LeagueStats/client/src/components/Summoner/Champions/ChampionsTable.vue

342 lines
10 KiB
Vue
Raw Normal View History

2019-12-21 16:56:31 +00:00
<template>
<table class="w-full leading-none text-center bg-blue-800 rounded-lg table-fixed">
2019-12-21 16:56:31 +00:00
<thead>
<tr class="text-sm rounded-t-lg select-none heading">
2019-12-21 16:56:31 +00:00
<th
@click="sortBy('index')"
:class="sortedClasses('index')"
class="relative px-2 py-4 font-normal rounded-tl-lg cursor-pointer hover:bg-blue-700"
2019-12-21 16:56:31 +00:00
>rank</th>
<th
v-for="(heading, index) in headings"
:key="`champHeading-${index}`"
@click="sortBy(heading.props)"
v-html="heading.name"
:class="[
{'rounded-tr-lg': index === headings.length - 1, 'w-name': heading.name === 'Name'},
sortedClasses(heading.props)
]"
2019-12-21 16:56:31 +00:00
class="relative px-2 py-4 font-normal cursor-pointer hover:bg-blue-700"
></th>
</tr>
</thead>
<tbody v-if="champions.length" class="bg-blue-760">
2019-12-21 16:56:31 +00:00
<tr
v-for="(champion, index) in championsToDisplay"
2019-12-21 16:56:31 +00:00
:key="champion._id"
:class="{'rounded-b-lg': index === championsToDisplay.length - 1}"
2019-12-21 16:56:31 +00:00
>
<td
:class="{'rounded-bl-lg': index === championsToDisplay.length - 1}"
class="relative px-2 py-3 text-sm text-white bg-blue-800 border-t-table"
2019-12-21 16:56:31 +00:00
>{{ champion.index + 1 }}</td>
<td class="relative px-2 py-3 text-sm text-white bg-blue-800 border-t-table">
2019-12-21 16:56:31 +00:00
<div class="flex items-center">
<div
:style="{backgroundImage: `url('${champion.champion.icon}')`}"
class="flex-shrink-0 w-6 h-6 bg-center bg-cover rounded-full bg-blue-1000"
2019-12-21 16:56:31 +00:00
></div>
<div class="ml-2">{{ champion.champion.name }}</div>
</div>
</td>
<td
:style="bgColor(champion, 'winrate')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.winrate|percent }}</td>
<td
:style="bgColor(champion, 'playrate')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.playrate|percent }}</td>
<td
:style="bgColor(champion, 'wins')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.wins }}</td>
<td
:style="bgColor(champion, 'count')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.count }}</td>
<td :style="bgColor(champion, 'kda')" class="px-2 py-3 text-sm text-white">
<div>{{ champion.kda|round }}</div>
<div class="mt-1 text-blue-200 text-xxs">
{{ champion.kills/champion.count|round(1) }}
/
{{ champion.deaths/champion.count|round(1) }}
/
{{ champion.assists/champion.count|round(1) }}
</div>
</td>
2019-12-21 16:56:31 +00:00
<td
:style="bgColor(champion, 'kp')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.kp|percent }}</td>
<td
:style="bgColor(champion, 'minions')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.minions|round(0) }}</td>
<td
:style="bgColor(champion, 'gold')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.gold|kilo }}</td>
<td
:style="bgColor(champion, 'dmgChamp')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.dmgChamp|kilo }}</td>
<td
:style="bgColor(champion, 'dmgTaken')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.dmgTaken|kilo }}</td>
<td
:style="bgColor(champion, 'gameLength')"
class="px-2 py-3 text-sm text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.gameLength|secToTime }}</td>
<td
:class="{'rounded-br-lg': index === championsToDisplay.length - 1}"
class="px-2 py-3 text-xs text-white"
2019-12-21 16:56:31 +00:00
>{{ champion.lastPlayed }}</td>
</tr>
</tbody>
<tbody v-else>
<tr v-for="index in 11" :key="index">
<td colspan="14">
<content-loader
:height="50"
:width="1200"
:speed="2"
primary-color="#17314f"
secondary-color="#2b6cb0"
>
<rect x="31" y="16" rx="3" ry="3" width="20" height="20" />
<circle cx="101" cy="26" r="12" />
<rect x="119" y="16" rx="3" ry="3" width="50" height="20" />
<rect x="234.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="316.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="398.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="480.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="565" y="14" rx="3" ry="3" width="40" height="10" />
<rect x="558" y="30" rx="3" ry="3" width="55" height="10" />
<rect x="644.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="726.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="808.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="890.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="972.5" y="16" rx="3" ry="3" width="45" height="20" />
<rect x="1052" y="16" rx="3" ry="3" width="50" height="20" />
<rect x="1129" y="16" rx="3" ry="3" width="60" height="20" />
</content-loader>
</td>
</tr>
</tbody>
2019-12-21 16:56:31 +00:00
</table>
</template>
<script>
import { colors } from '@/data/data.js'
import { ContentLoader } from 'vue-content-loader'
2019-12-21 16:56:31 +00:00
import { timeDifference } from '@/helpers/functions.js'
export default {
components: {
ContentLoader,
},
2019-12-21 16:56:31 +00:00
props: {
champions: {
type: Array,
required: true
},
search: {
type: String,
default: ''
2019-12-21 16:56:31 +00:00
}
},
data() {
return {
headings: [
{
name: 'Name',
2019-12-21 16:56:31 +00:00
props: 'champion.name'
},
{
name: 'Win <br> rate',
2019-12-21 16:56:31 +00:00
props: 'winrate'
},
{
name: 'Play <br> rate',
2019-12-21 16:56:31 +00:00
props: 'playrate'
},
{
name: 'Wins',
2019-12-21 16:56:31 +00:00
props: 'wins'
},
{
name: 'Plays',
2019-12-21 16:56:31 +00:00
props: 'count'
},
{
name: 'KDA',
2019-12-21 16:56:31 +00:00
props: 'kda'
},
{
name: 'KP',
2019-12-21 16:56:31 +00:00
props: 'kp'
},
{
name: 'Minions',
2019-12-21 16:56:31 +00:00
props: 'minions'
},
{
name: 'Gold',
2019-12-21 16:56:31 +00:00
props: 'gold'
},
{
name: 'Dmg <br> champ',
2019-12-21 16:56:31 +00:00
props: 'dmgChamp'
},
{
name: 'Dmg <br> taken',
2019-12-21 16:56:31 +00:00
props: 'dmgTaken'
},
{
name: 'Game <br> length',
2019-12-21 16:56:31 +00:00
props: 'gameLength'
},
{
name: 'Last <br> played',
2019-12-21 16:56:31 +00:00
props: 'date'
}
],
championsFull: [],
sortProps: 'index',
order: -1
}
},
computed: {
championsToDisplay() {
return this.championsFull.filter(c => {
return c.champion.name.toLowerCase().includes(this.search.toLowerCase())
})
},
2019-12-21 16:56:31 +00:00
totalGames() {
return this.champions.reduce((agg, champ) => agg + champ.count, 0)
}
},
watch: {
champions() {
this.updateChampionsList()
}
},
created() {
this.updateChampionsList()
2019-12-21 16:56:31 +00:00
},
methods: {
bgColor(champion, stats) {
const biggestValue = Math.max(
...this.championsToDisplay
.filter(c => c[stats] !== Infinity)
.map(c => parseFloat(c[stats]))
, 0)
// Take the second biggest Value if it's an Infinity KDA
const value = champion[stats] === Infinity ? biggestValue : parseFloat(champion[stats])
2019-12-21 16:56:31 +00:00
const opacity = (value / biggestValue).toFixed(2)
return {
backgroundColor: `rgba(${colors[stats]}, ${opacity})`
2019-12-21 16:56:31 +00:00
}
},
sortBy(props) {
// Change order of the sort
if (props === this.sortProps) {
this.order *= -1
} else {
this.order = -1
}
this.championsToDisplay.sort((a, b) => {
2019-12-21 16:56:31 +00:00
const aProp = props.split('.').reduce((p, c) => p && p[c] || null, a)
const bProp = props.split('.').reduce((p, c) => p && p[c] || null, b)
let order = aProp > bProp ? this.order : this.order * -1
// Revert order for rank and champion name
if (props === 'index' || props === 'champion.name') {
order *= -1
}
return order
})
this.sortProps = props
},
sortedClasses(props) {
return {
'sorted': this.sortProps === props,
'sorted-asc': this.sortProps === props && this.order === 1,
'sorted-desc': this.sortProps === props && this.order === -1,
}
},
updateChampionsList() {
this.championsFull = this.champions.map((champ, index) => {
2020-03-17 12:34:39 +00:00
let kda = champ.kills === 0 && champ.assists === 0 && champ.deaths === 0 ? 0 : (champ.kills + champ.assists) / champ.deaths
return {
...champ,
winrate: champ.wins * 100 / champ.count,
playrate: champ.count * 100 / this.totalGames,
2020-03-17 12:34:39 +00:00
kda,
index,
lastPlayed: timeDifference(champ.date),
show: true
}
})
2019-12-21 16:56:31 +00:00
}
}
}
</script>
<style scoped>
.heading {
box-shadow: none;
}
.border-t-table::after {
content: "";
position: absolute;
right: 0;
top: 0;
width: 100%;
height: 2px;
background-color: rgba(190, 227, 248, 0.2);
}
.sorted::after {
content: "";
position: absolute;
top: -15px;
left: 0;
height: 24px;
width: 100%;
background-color: rgb(34, 92, 135);
background-repeat: no-repeat;
background-position: center;
background-size: 16px 16px;
border-radius: 0.5rem 0.5rem 0 0;
}
.sorted-asc::after {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='white' 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'%3E%3C/path%3E%3C/svg%3E");
}
.sorted-desc::after {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath fill='white' 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' /%3E%3C/svg %3E");
}
.sorted:hover::after {
background-color: #2b6cb0;
}
.w-name {
width: 135px;
}
2019-12-21 16:56:31 +00:00
</style>