Files
csgowtf/src/views/Match.vue
2021-10-17 18:06:28 +02:00

274 lines
7.9 KiB
Vue

<template>
<img alt="" class="bg-img" src="">
<div class="">
<div class="head row m-auto text-center">
<div class="m-auto map">
<img v-if="data.matchDetails.map" :alt="data.matchDetails.map"
:src="require('@/images/map_icons/map_icon_' + data.matchDetails.map + '.svg')"
:title="data.matchDetails.map" class="map-icon">
<img v-if="!data.matchDetails.map" :src="require('../images/map_icons/map_icon_lobby_mapveto.svg')"
alt="Map icon"
class="map-icon" title="Map unknown">
</div>
<p class="text-center text-muted fs-6">
{{ FormatFullDate(data.matchDetails.date) }}
</p>
<p class="text-center fs-6">
<span class="text-muted">Match Length:</span> {{ data.matchDetails.max_rounds === 16 ? 'Short' : 'Long' }}
<svg class="bi bi-circle-fill mx-2" fill="currentColor" height="8" viewBox="0 0 16 16" width="8"
xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8"/>
</svg>
<span class="text-muted">Average Rank:</span> <img
:alt="DisplayRank(data.avgRank)[1]"
:src="DisplayRank(data.avgRank)[0]"
:title="DisplayRank(data.avgRank)[1]"
class="rank-icon"/>
</p>
</div>
</div>
<div class="nav navbar-dark navbar-expand-lg">
<button aria-controls="matchNav" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler"
data-bs-target="#matchNav" data-bs-toggle="collapse" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div id="matchNav" class="collapse navbar-collapse">
<ul class="list-unstyled d-flex m-auto">
<li :class="!data.matchDetails.parsed ? 'disabled' : ''"
:title="!data.matchDetails.parsed ? 'This demo has not been parsed' : ''"
class="list-item nav-item">
<router-link :disabled="!data.matchDetails.parsed" :to="'/match/' + data.matchDetails.match_id + '/overview'" replace
class="nav-link">Scoreboard
</router-link>
</li>
<li :class="!data.matchDetails.parsed ? 'disabled' : ''"
:title="!data.matchDetails.parsed ? 'This demo has not been parsed' : ''"
class="list-item nav-item">
<router-link :disabled="!data.matchDetails.parsed" :to="'/match/' + data.matchDetails.match_id + '/details'" replace
class="nav-link">Details
</router-link>
</li>
<li :class="!data.matchDetails.parsed ? 'disabled' : ''"
:title="!data.matchDetails.parsed ? 'This demo has not been parsed' : ''"
class="list-item nav-item">
<router-link :disabled="!data.matchDetails.parsed" :to="'/match/' + data.matchDetails.match_id + '/flashes'" replace
class="nav-link">Flashes
</router-link>
</li>
<!-- <li :class="!data.matchDetails.parsed ? 'disabled' : ''"-->
<!-- :title="!data.matchDetails.parsed ? 'This demo has not been parsed' : ''"-->
<!-- class="list-item nav-item">-->
<!-- <router-link :disabled="!data.matchDetails.parsed" :to="'/match/' + data.matchDetails.match_id + '/utility'" replace-->
<!-- class="nav-link">Utility-->
<!-- </router-link>-->
<!-- </li>-->
<li :class="!data.matchDetails.parsed ? 'disabled' : ''"
:title="!data.matchDetails.parsed ? 'This demo has not been parsed' : ''"
class="list-item nav-item">
<router-link :disabled="!data.matchDetails.parsed" :to="'/match/' + data.matchDetails.match_id + '/damage'" replace
class="nav-link">Damage
</router-link>
</li>
</ul>
</div>
</div>
<div v-if="data.score.length === 2 && data.stats" id="scoreWrapper" class="scoreboard">
<router-view name="score"/>
</div>
</template>
<script>
import {onBeforeMount, onBeforeUnmount, onMounted, reactive, watch} from "vue";
import axios from 'axios'
import {DisplayRank, FormatFullDate, GetAvgRank, GoToLink, LoadImage} from "../utils";
import {useStore} from "vuex";
import {useRoute} from 'vue-router'
export default {
name: 'Match',
props: ['match_id'],
setup(props) {
const store = useStore()
const route = useRoute()
const matchIdPattern = /^\d{19}$/
// Refs
const data = reactive({
playerName: '',
matchDetails: {},
stats: [],
score: [0],
avgRank: 0,
})
// Functions
const GetMatch = () => {
if (matchIdPattern.test(props.match_id))
axios
.get(`${process.env.VUE_APP_API_URL}/match/${props.match_id}`)
.then((response) => {
document.title = `${response.data.map} | csgoWTF`
store.commit({
type: 'changeMatchDetails',
data: response.data
})
data.matchDetails = store.state.matchDetails
data.stats = data.matchDetails.stats
data.score = data.matchDetails.score
LoadImage(data.matchDetails.map ? data.matchDetails.map : 'random')
GetAvgRank(data.stats)
console.log(data.matchDetails)
})
.catch((e) => {
console.log(e)
// TODO: needs 404
})
else {
console.log('Match not found')
// TODO: needs 404
}
}
const checkRoute = () => {
if (route.fullPath.split('/')[3]) {
const sub = route.fullPath.split('/')[3]
if (matchIdPattern.test(props.match_id))
GoToLink(`/match/${props.match_id}/${sub}`)
else {
console.log('Match not found')
// TODO: needs 404
}
} else if (route.fullPath.split('/')[3] === undefined) {
if (matchIdPattern.test(props.match_id))
GoToLink(`/match/${props.match_id}/overview`)
else {
console.log('Match not found')
// TODO: needs 404
}
}
}
// Watchers
watch(() => props.match_id, GetMatch)
// Run on create
onBeforeMount(() => {
GetMatch()
})
onMounted(() => {
checkRoute()
})
onBeforeUnmount(() => {
store.commit({
type: 'changeMatchDetails',
data: {}
})
})
return {
data, DisplayRank, FormatFullDate
}
}
}
</script>
<style lang="scss" scoped>
.bg-img {
z-index: -1;
position: fixed;
display: block;
margin-left: auto;
margin-right: auto;
width: 100%;
}
.head {
background: linear-gradient(90deg,
rgba(0, 0, 0, 0.7) 0%,
rgba(0, 0, 0, 0.95) 30%,
rgba(0, 0, 0, 0.95) 70%,
rgba(0, 0, 0, .7) 100%
);
.map img {
width: auto;
height: 100px;
margin: 10px 0;
}
.rank-icon {
width: 60px;
}
}
.nav {
max-width: 100vw;
background: rgba(0, 0, 0, 0.9);
background: linear-gradient(90deg,
rgba(0, 0, 0, 0.7) 0%,
rgba(0, 0, 0, 0.95) 30%,
rgba(0, 0, 0, 0.95) 70%,
rgba(0, 0, 0, .7) 100%
);
border-top: 1px solid rgba(255, 255, 255, .2);
border-bottom: 1px solid rgba(255, 255, 255, .2);
.nav-link {
text-decoration: none;
color: white;
&:hover {
background: var(--bs-info);
cursor: pointer;
}
}
.router-link-exact-active {
background: var(--bs-info)
}
.disabled {
color: #585858;
&:hover {
background: transparent;
cursor: default;
}
}
}
#scoreWrapper {
display: flex;
justify-content: center;
flex-wrap: wrap;
padding-left: 70px;
z-index: 1;
height: 100%;
width: 100%;
max-width: 100vw;
background: linear-gradient(90deg,
rgba(0, 0, 0, 0.6) 0%,
rgba(0, 0, 0, 0.85) 30%,
rgba(0, 0, 0, 0.85) 70%,
rgba(0, 0, 0, .6) 100%
);
}
@media screen and (max-width: 991px) {
#scoreWrapper {
overflow-x: scroll;
overflow-y: hidden;
}
}
</style>