Files
csgowtf/src/views/Player.vue

1076 lines
30 KiB
Vue

<template>
<img alt="" class="bg-img" src="">
<div class="wrapper">
<div class="container">
<div class="card mb-3 bg-transparent border-0">
<div class="row g-0">
<div class="img-container col-md-2 pt-3">
<img
:class="data.tracked ? 'tracked' : ''"
:src="constructAvatarUrl(store.state.playerDetails.avatar, 'full')"
:title="data.tracked ? 'Tracked' : ''"
alt="Player avatar"
class="img-fluid avatar">
</div>
<div class="col-md-8 d-flex">
<div class="card-body">
<h3 class="card-title"><a
:href="/^\d{17}$/.test(props.id) ? 'https://steamcommunity.com/profiles/' + props.id : 'https://steamcommunity.com/id/' + props.id"
class="text-decoration-none text-white"
target="_blank"
title="Open steam profile">{{
store.state.playerDetails.name
}}
<i class="fas fa-link"></i>
</a></h3>
<table class="table table-borderless text-center">
<tr>
<th class="wlt-win text-uppercase text-muted">Wins</th>
<th class="wlt-loss text-uppercase text-muted">Losses</th>
<th class="wlt-tie text-uppercase text-muted">Ties</th>
<th class="wlt-win-rate text-uppercase text-muted">Win-Rate</th>
<th class="wlt-tie-rate text-uppercase text-muted">Tie-Rate</th>
</tr>
<tr>
<td class="wlt-win">{{ data.match_stats.win }}</td>
<td class="wlt-loss">{{ data.match_stats.loss }}</td>
<td class="wlt-tie">{{ data.match_stats.tie }}</td>
<td class="wlt-win-rate">{{
data.match_stats.win > 0 ? (data.match_stats.win / data.match_stats.total * 100).toFixed(0) : 0
}}%
</td>
<td class="wlt-tie-rate">{{
data.match_stats.tie > 0 ? (data.match_stats.tie / data.match_stats.total * 100).toFixed(0) : 0
}}%
</td>
</tr>
</table>
<div class="badges">
<img v-if="store.state.playerDetails.vac"
:title="'VAC-Ban: ' + FormatVacDate(store.state.playerDetails.vac_date, store.state.matchDetails.date)"
alt="Vac banned"
src="../assets/images/icons/vac_banned.svg">
<img v-if="store.state.playerDetails.game_ban"
:title="'Game-Ban: ' + FormatVacDate(store.state.playerDetails.game_ban_date, store.state.matchDetails.date)"
alt="Game banned"
src="../assets/images/icons/game_banned.svg">
</div>
</div>
<div v-if="!data.tracked" class="dropdown trackme-btn">
<button
id="login-dropdown"
aria-expanded="false"
class="btn border-2 btn-outline-info"
data-bs-toggle="dropdown"
type="button"
>
Track Me!
</button>
<div v-if="data.statusErrorCode === 202" class="alert alert-success" role="alert">
{{ data.statusError }}
</div>
<div v-if="data.statusErrorCode === 418" class="alert alert-warning" role="alert">
{{ data.statusError }}
</div>
<div v-if="data.statusErrorCode !== 0 && data.statusErrorCode !== 202 && data.statusErrorCode !== 418"
class="alert alert-danger"
role="alert">
{{ data.statusError }}
</div>
<div aria-labelledby="login-dropdown" class="dropdown-menu mt-2 border-2 border-primary bg-body"
style="width: 320px">
<form class="px-4 py-3">
<!-- AuthCode input -->
<div class="form-outline mb-4">
<input id="track-authcode" v-model="data.userData.authcode" class="form-control bg-secondary"
placeholder="AuthCode*"
required type="text"/>
</div>
<!-- ShareCode input -->
<div class="form-outline mb-2">
<input id="track-sharecode" v-model="data.userData.sharecode" class="form-control bg-secondary"
placeholder="ShareCode"
type="text"/>
</div>
<div class="form-outline mb-4">
<small>You can find your AuthCode and ShareCode <a
href="https://help.steampowered.com/en/wizard/HelpWithGameIssue/?appid=730&issueid=128"
target="_blank">here</a>.</small>
</div>
<!-- Submit button -->
<button class="btn btn-outline-warning border-2" type="submit"
@click.prevent="TrackPlayer">
TrackMe
</button>
</form>
</div>
</div>
<div v-if="data.tracked" class="refresh-btn" title="Refresh Match-List" @click="RefreshData">
<i class="fas fa-sync"></i>
</div>
</div>
</div>
</div>
<div class="match-container d-flex">
<div class="matches">
<table v-if="store.state.playerDetails.matches" class="table table-borderless">
<thead class="border-bottom">
<tr>
<th class="text-center map" scope="col">Map</th>
<th class="text-center rank" scope="col">Rank</th>
<th class="text-center length" scope="col" title="Match Length">
<img alt="Match length" class="match-len" src="../assets/images/icons/timer_both.svg">
</th>
<th class="text-center score" scope="col">Score</th>
<th class="text-center kills" scope="col">K</th>
<th class="text-center assists" scope="col">A</th>
<th class="text-center deaths" scope="col">D</th>
<th class="text-center kdiff" scope="col" style="cursor: help" title="Kill-to-death ratio">+/-</th>
<th class="text-center hltv" scope="col" style="cursor: help" title="HLTV 1.0 Rating">Rating</th>
<th class="text-center duration" scope="col">Duration</th>
<th class="date" scope="col">Date</th>
</tr>
</thead>
<tbody>
<tr v-for="match in data.matches"
:key="match.match_id"
:class="GetWinLoss(match.match_result, match.stats.team_id) + (match.vac || match.game_ban ? ' ban' : '')"
:title="match.vac ? 'VAC-banned player in this game' : match.game_ban ? 'Game-banned player in this game' : ''"
class="match"
@click="GoToMatch(match.match_id)"
>
<td class="td-map text-center">
<i v-if="match.parsed" class="far fa-chart-bar parsed" style="cursor: help"
title="Demo has been parsed for additional data"></i>
<img :alt="match.map ? match.map : 'Map not found'"
:src="match.map !== '' ? require('../assets/images/map_icons/map_icon_' + match.map + '.svg') : require('../assets/images/map_icons/map_icon_lobby_mapveto.svg')"
:title="match.map"
class="map-icon">
</td>
<td class="td-rank text-center">
<img
:alt="DisplayRank(match.stats.rank?.new)[1]"
:class="match.stats.rank?.new > match.stats.rank?.old ? 'uprank' : match.stats.rank?.new < match.stats.rank?.old ? 'downrank' : ''"
:src="DisplayRank(match.stats.rank?.new)[0]"
:title="DisplayRank(match.stats.rank?.new)[1]"
class="rank-icon">
</td>
<td class="td-length text-center">
<img v-if="match.max_rounds === 30 || !match.max_rounds" alt="Match long"
class="match-len" src="../assets/images/icons/timer_long.svg">
<img v-if="match.max_rounds === 16" alt="Match short" class="match-len"
src="../assets/images/icons/timer_short.svg">
</td>
<td :class="match.stats.team_id === match.match_result ? 'text-success' : !match.match_result ? 'text-warning' : 'text-danger'"
class="td-score text-center fw-bold">
{{ match.score[0] }} - {{ match.score[1] }}
</td>
<td class="td-kills text-center">
{{ match.stats.kills ? match.stats.kills : "0" }}
</td>
<td class="td-assists text-center">
{{ match.stats.assists ? match.stats.assists : "0" }}
</td>
<td class="td-deaths text-center">
{{ match.stats.deaths ? match.stats.deaths : "0" }}
</td>
<td :class="(match.stats.kills ? match.stats.kills : 0) - (match.stats.deaths ? match.stats.deaths : 0) >= 0 ? 'text-success' : 'text-danger'"
class="td-plus text-center">
{{
(match.stats.kills ? match.stats.kills : 0) - (match.stats.deaths ? match.stats.deaths : 0)
}}
</td>
<td :class="GetHLTV_1(
match.stats.kills,
match.score[0] + match.score[1],
match.stats.deaths,
match.stats.multi_kills?.duo,
match.stats.multi_kills?.triple,
match.stats.multi_kills?.quad,
match.stats.multi_kills?.pent) >= 1 ? 'text-success' : 'text-warning'"
class="td-hltv text-center fw-bold">
{{
GetHLTV_1(
match.stats.kills,
match.score[0] + match.score[1],
match.stats.deaths,
match.stats.multi_kills?.duo,
match.stats.multi_kills?.triple,
match.stats.multi_kills?.quad,
match.stats.multi_kills?.pent)
}}
</td>
<td :title="FormatFullDuration(match.duration)" class="td-duration text-center">
{{ FormatDuration(match.duration) }}
</td>
<td :title="FormatFullDate(match.date)" class="td-date">
{{ FormatDate(match.date) }}
</td>
</tr>
</tbody>
</table>
<h5 v-else>No matches on record</h5>
</div>
<div v-if="store.state.playerDetails.matches" class="side-info">
<div v-if="data.playerMeta.most_mates" class="side-info-box most-played-with">
<div class="heading">
<h5>Most played with</h5>
</div>
<hr>
<ul v-for="mate in data.playerMeta.most_mates" :key="mate.player.steamid64" class="list-unstyled">
<li @click="GoToPlayer(mate.player.vanity_url || mate.player.steamid64)">
<span class="start">
<img :class="mate.player.tracked ? 'tracked' : ''" :src="constructAvatarUrl(mate.player.avatar)"
:title="mate.player.tracked ? 'Tracked' : ''" alt="Player avatar">
<span class="text">{{ mate.player.name }}</span>
</span>
<span class="end">
{{ mate.total }}
</span>
</li>
</ul>
</div>
<div v-if="data.playerMeta.best_mates" class="side-info-box best-mate">
<div class="heading">
<h5>Best Mate <span class="text-muted">(by winrate)</span></h5>
</div>
<hr>
<ul v-for="mate in data.playerMeta.best_mates" :key="mate.player.steamid64" class="list-unstyled">
<li @click="GoToPlayer(mate.player.vanity_url || mate.player.steamid64)">
<span class="start">
<img :class="mate.player.tracked ? 'tracked' : ''" :src="constructAvatarUrl(mate.player.avatar)"
:title="mate.player.tracked ? 'Tracked' : ''" alt="Player avatar">
<span class="text">{{ mate.player.name }}</span>
</span>
<span class="end">
{{ (mate.win_rate * 100).toFixed(0) }} %
</span>
</li>
</ul>
</div>
<div v-if="data.playerMeta.eq_map && data.playerMeta.weapon_dmg" class="side-info-box preferred-weapons">
<div class="heading">
<h5>Weapons <span class="text-muted">(by dmg)</span></h5>
</div>
<hr>
<ul v-for="(id, key) in data.best_weapons" :key="id[0]" class="list-unstyled">
<li>
<span class="start">
<span class="text">{{ id[0] }}</span>
</span>
<span :title="id[0] + ' - ' + id[1] + ' dmg'" class="end">
<span :class="'dmg-chart-' + key">
{{ id[1] }}
</span>
</span>
</li>
</ul>
{{ setDmgGraphWidth() }}
</div>
<div v-if="data.playerMeta.win_maps" class="side-info-box best-map">
<div class="heading">
<h5>Best Map <span class="text-muted">(by winrate)</span></h5>
</div>
<hr>
<ul v-for="map in data.best_maps" :key="map[0]" class="list-unstyled">
<li>
<span class="start">
<img :src="require('../assets/images/map_icons/map_icon_' + map[0] + '.svg')" alt="Player avatar">
<span class="text">{{ FixMapName(map[0]) }}</span>
</span>
<span class="end">
{{ (map[1] * 100).toFixed(0) }} %
</span>
</li>
</ul>
</div>
</div>
</div>
<div class="load-more col-lg-9 col-md-12 text-center">
<button v-if="data.match_stats.total !== data.matches.length" class="btn border-2 btn-outline-info"
@click="setMoreMatches">Load More
</button>
</div>
</div>
</div>
</template>
<script>
import {onBeforeMount, onMounted, reactive, ref, watch} from "vue";
import {useStore} from "vuex";
import {
constructAvatarUrl,
DisplayRank,
FixMapName,
FormatDate,
FormatDuration,
FormatFullDate,
FormatFullDuration,
FormatVacDate,
GetHLTV_1,
getPlayerMeta,
GetUser,
GetWinLoss,
GoToLink,
GoToMatch,
GoToPlayer,
LoadImage,
loadMoreMatches,
SaveLastVisitedToLocalStorage,
setTitle,
sortObjectValue,
TrackMe,
} from "../utils";
import {FOOTER_HEIGHT, NAV_HEIGHT} from "@/constants";
export default {
name: 'Player',
props: ['id'],
setup(props) {
// Variables
const store = useStore()
const displayCounter = 3
const data = reactive({
userData: {
authcode: '',
sharecode: ''
},
tracked: false,
matches: [],
statusError: '',
statusErrorCode: 0,
match_stats: {
loss: 0,
win: 0,
tie: 0,
total: 0
},
playerMeta: {},
best_maps: [],
best_weapons_tmp: [],
best_weapons: []
})
onBeforeMount(() => {
if (Object.entries(store.state.playerDetails).length === 0) {
GetPlayer()
} else {
console.log(store.state.playerDetails)
SetPlayerData()
}
}
)
const SetPlayerData = async () => {
data.tracked = store.state.playerDetails.tracked
if (store.state.playerDetails.matches)
data.matches = store.state.playerDetails.matches
if (store.state.playerDetails.match_stats) {
data.match_stats.loss = store.state.playerDetails.match_stats.loss || 0
data.match_stats.win = store.state.playerDetails.match_stats.win || 0
data.match_stats.tie = store.state.playerDetails.match_stats.tie || 0
data.match_stats.total = data.match_stats.loss + data.match_stats.win + data.match_stats.tie
}
store.commit({
type: 'changeId64',
id: store.state.playerDetails.steamid64
})
store.commit({
type: 'changeVanityUrl',
id: store.state.playerDetails.vanity_url || ''
})
if (store.state.playerDetails.matches)
await LoadImage(data.matches[0].map ? data.matches[0].map : 'random')
let player = {
'steamid64': store.state.playerDetails.steamid64,
'vanity_url': store.state.playerDetails.vanity_url || '',
'name': store.state.playerDetails.name,
'avatar': constructAvatarUrl(store.state.playerDetails.avatar, 'medium')
}
SaveLastVisitedToLocalStorage(player)
setTitle(store.state.playerDetails.name)
}
const GetPlayer = async () => {
if (props.id) {
const [res, resData] = await GetUser(props.id)
if (res === 200 && resData) {
if (resData.steamid64 !== store.state.playerDetails.steamid64) {
store.commit('resetPlayerDetails')
store.commit({
type: 'changePlayerDetails',
data: resData
})
}
await SetPlayerData()
console.log(store.state.playerDetails)
} else {
GoToLink('/')
// TODO: needs 404
}
} else {
GoToLink('/')
// TODO: needs 404
}
}
const setMoreMatches = async () => {
const res = await loadMoreMatches(store.state.playerDetails.steamid64, data.matches[data.matches.length - 1].date)
res.matches.forEach(e => data.matches.push(e))
console.log(store.state.playerDetails)
}
const RefreshData = async () => {
const refreshButton = document.querySelector('.refresh-btn .fas')
refreshButton.classList.add('animate')
await GetPlayer().then(() => {
setTimeout(() => {
refreshButton.classList.remove('animate')
}, 2000)
})
}
const TrackPlayer = async () => {
if (data.userData.authcode !== '') {
[data.statusErrorCode, data.statusError] = await TrackMe(store.state.playerDetails.steamid64, data.userData.authcode, data.userData.sharecode)
if (data.statusErrorCode === 202) {
data.statusErrorCode = 0
data.statusError = ''
data.tracked = true
} else {
setTimeout(() => {
data.statusError = ''
data.statusErrorCode = 0
}, 5000)
}
}
}
const mapWeaponDamage = () => {
if (data.playerMeta.eq_map && data.playerMeta.weapon_dmg) {
Object.keys(data.playerMeta.eq_map).forEach((key) => {
for (const id in data.playerMeta.weapon_dmg) {
Object.keys(data.playerMeta.weapon_dmg[id]).forEach((k) => {
if (k === 'eq') {
if (data.playerMeta.weapon_dmg[id][k] === key * 1) {
data.best_weapons_tmp.push([data.playerMeta.eq_map[key], data.playerMeta.weapon_dmg[id]['dmg']])
}
}
})
}
})
data.best_weapons_tmp.sort((a, b) => {
return b[1] - a[1]
})
data.best_weapons = data.best_weapons_tmp
data.best_weapons_tmp = []
}
}
const setDmgGraphWidth = () => {
setTimeout(() => {
let weaponsContainer
const dmg100 = ref(0)
const dmg = ref(0)
for (let i = 0; i <= 4; i++) {
weaponsContainer = document.querySelector('.dmg-chart-' + i)
if (weaponsContainer !== null) {
if (i === 0) {
dmg100.value = weaponsContainer.innerHTML * 1
weaponsContainer.style.width = '100%'
}
dmg.value = weaponsContainer.innerHTML * 1
weaponsContainer.style.width = dmg.value * 100 / dmg100.value + '%'
}
}
}, 100)
}
watch(() => props.id, async () => {
await GetPlayer()
data.playerMeta = await getPlayerMeta(props.id, displayCounter)
})
watch(() => data.playerMeta, () => {
mapWeaponDamage()
data.best_maps = sortObjectValue(data.playerMeta.win_maps, 'desc')
if (data.best_maps.length > displayCounter)
data.best_maps.splice(displayCounter, data.best_maps.length - displayCounter)
})
onMounted(async () => {
const height = window.innerHeight - NAV_HEIGHT - FOOTER_HEIGHT
const wrapper = document.querySelector('.wrapper')
wrapper.style.minHeight = height + 'px'
await GetPlayer()
data.playerMeta = await getPlayerMeta(props.id, displayCounter)
})
return {
data,
store,
props,
TrackPlayer,
RefreshData,
TrackMe,
GetWinLoss,
FormatDate,
FormatFullDate,
FormatDuration,
FormatFullDuration,
GoToMatch,
GetHLTV_1,
DisplayRank,
constructAvatarUrl,
FormatVacDate,
FixMapName,
GoToPlayer,
setMoreMatches,
setDmgGraphWidth
}
}
}
</script>
<style lang="scss" scoped>
.bg-img {
z-index: -1;
position: fixed;
width: 100%;
height: 100%;
object-fit: cover;
overflow: hidden;
}
.wrapper {
background: rgba(0, 0, 0, .7);
.load-more {
padding: 1rem 0;
}
.trackme-btn,
.refresh-btn {
position: absolute;
right: 0;
bottom: 0;
}
.refresh-btn {
cursor: pointer;
&:hover,
&:focus {
.fas {
color: var(--bs-warning);
}
}
.fas {
font-size: 1.3rem;
&.animate {
animation: refresh 2s infinite;
}
}
}
@keyframes refresh {
0% {
transform: rotate(0deg) scale(1);
}
10% {
transform: rotate(-15deg) scale(1);
}
50% {
transform: rotate(180deg) scale(1.4);
}
100% {
transform: rotate(360deg) scale(1);
}
};
}
.card {
padding-top: 10px;
.badges {
height: 30px;
img {
width: auto;
height: 100%;
margin-right: 5px;
}
}
.avatar {
border-radius: 50%;
height: 150px;
width: 150px;
box-shadow: 0 0 10px black;
&.tracked {
box-shadow: 0 0 20px 5px var(--bs-success);
}
}
.fas, .far {
font-size: .75rem;
vertical-align: top;
}
table {
max-width: 500px;
.wlt-win, .wlt-loss, .wlt-tie {
text-align: start;
max-width: 70px;
margin: 0;
padding: 0;
}
.wlt-tie-rate, .wlt-win-rate {
text-align: end;
max-width: 90px;
}
}
}
.match-container {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 1rem;
.matches {
width: 75%;
}
.side-info {
display: flex;
flex-direction: column;
gap: 1rem;
width: 25%;
height: auto;
margin-top: 30px;
.side-info-box {
width: 100%;
height: auto;
background: rgba(20, 20, 20, .8);
border: 1px solid rgba(white, .3);
border-radius: 5px;
}
.best-mate,
.preferred-weapons,
.most-played-with,
.best-map {
.heading {
display: flex;
align-items: center;
justify-content: center;
height: 30px;
h5 {
font-size: 1rem;
margin: 0;
padding: 0;
}
}
hr {
margin: 0 0 5px 0;
border-color: rgba(white, .3);
}
ul li {
line-height: 25px;
font-size: .9rem;
padding: 0 10px;
margin: 5px 0;
cursor: pointer;
display: flex;
justify-content: space-between;
gap: 1rem;
.start {
width: 50%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.tracked {
font-size: .8rem;
margin-right: 5px;
}
img {
width: 25px;
height: 25px;
border-radius: 50%;
margin-right: 5px;
margin-left: 5px;
&.tracked {
border: 2px solid var(--bs-success);
}
}
}
.end {
display: flex;
width: 45%;
justify-content: flex-end;
align-items: flex-end;
}
}
}
.preferred-weapons,
.best-map {
ul li {
cursor: default;
}
}
.preferred-weapons {
.end {
position: relative;
@for $i from 0 through 3 {
.dmg-chart-#{$i} {
position: absolute;
background: rgba(150, 50, 50, 1);
border-radius: 15px;
color: transparent;
user-select: none;
cursor: help;
&:hover {
background: rgba(220, 50, 50, 1);
}
}
}
}
}
}
}
table {
margin-bottom: 0;
tr {
th {
line-height: 1;
}
td {
line-height: 60px;
font-size: 1rem;
}
th:last-child, td:last-child {
text-align: right;
width: 150px;
}
th[title] {
text-decoration: underline dotted grey;
}
td {
vertical-align: middle;
}
.map {
padding-left: 3rem;
}
.match-len {
width: 18px;
height: 18px;
}
.td-map {
position: relative;
padding-left: 3rem;
text-align: left !important;
width: 50px;
.parsed {
position: absolute;
left: 7px;
bottom: 23px;
color: var(--bs-warning);
font-size: 1.7rem;
}
img {
width: 60px;
height: auto;
}
}
.td-rank {
.uprank {
box-shadow: 0 0 20px greenyellow;
border: 1px solid greenyellow;
border-radius: 5px;
}
.downrank {
box-shadow: 0 0 20px #ff2f2f;
border: 1px solid #ff2f2f;
border-radius: 5px;
}
img {
width: 70px;
height: auto;
.rank-icon {
height: 35px;
}
}
}
.td-score {
font-size: 1.2rem;
width: 120px;
}
.td-date, .date {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.match {
$first: rgb(0, 0, 0);
$last: rgb(0, 0, 0);
$win: false;
$loss: false;
$draw: false;
$ban: false;
&.win {
$first: rgb(0, 255, 0);
background: linear-gradient(to right,
rgba($first, 0.2) 0%,
rgba($first, 0.1) 15%,
rgba(0, 0, 0, 0.4) 30%,
rgba(0, 0, 0, 0.4) 70%,
rgba($last, 0.6) 80%,
rgba($last, 0.6) 100%
);
&:hover {
background: linear-gradient(to right,
rgba($first, 0.3) 0%,
rgba($first, 0.2) 15%,
rgba(0, 0, 0, 0.5) 30%,
rgba(0, 0, 0, 0.5) 70%,
rgba($last, 0.7) 80%,
rgba($last, 0.7) 100%
);
}
}
&.draw {
$first: rgb(255, 255, 0);
background: linear-gradient(to right,
rgba($first, 0.2) 0%,
rgba($first, 0.1) 15%,
rgba(0, 0, 0, 0.4) 30%,
rgba(0, 0, 0, 0.4) 70%,
rgba($last, 0.6) 80%,
rgba($last, 0.6) 100%
);
&:hover {
background: linear-gradient(to right,
rgba($first, 0.3) 0%,
rgba($first, 0.2) 15%,
rgba(0, 0, 0, 0.5) 30%,
rgba(0, 0, 0, 0.5) 70%,
rgba($last, 0.7) 80%,
rgba($last, 0.7) 100%
);
}
}
&.loss {
$first: rgb(255, 0, 0);
background: linear-gradient(to right,
rgba($first, 0.2) 0%,
rgba($first, 0.1) 15%,
rgba(0, 0, 0, 0.4) 30%,
rgba(0, 0, 0, 0.4) 70%,
rgba($last, 0.6) 80%,
rgba($last, 0.6) 100%
);
&:hover {
background: linear-gradient(to right,
rgba($first, 0.3) 0%,
rgba($first, 0.2) 15%,
rgba(0, 0, 0, 0.5) 30%,
rgba(0, 0, 0, 0.5) 70%,
rgba($last, 0.7) 80%,
rgba($last, 0.7) 100%
);
}
}
&.ban {
$last: rgb(93, 3, 3);
background: linear-gradient(to right,
rgba($first, 0.2) 0%,
rgba($first, 0.1) 15%,
rgba(0, 0, 0, 0.4) 30%,
rgba(0, 0, 0, 0.4) 70%,
rgba($last, 0.6) 80%,
rgba($last, 0.6) 100%
);
&:hover {
background: linear-gradient(to right,
rgba($first, 0.3) 0%,
rgba($first, 0.2) 15%,
rgba(0, 0, 0, 0.5) 30%,
rgba(0, 0, 0, 0.5) 70%,
rgba($last, 0.7) 80%,
rgba($last, 0.7) 100%
);
}
}
border-bottom: 1px solid rgba(73, 73, 73, 0.73);
&:last-child {
border: none;
}
&:hover {
cursor: pointer;
}
}
}
@media screen and (max-width: 768px) {
.card {
.avatar {
height: 75px !important;
width: 75px !important;
}
}
.trackme-btn,
.refresh-btn {
top: 25px;
}
.refresh-btn {
&:hover,
&:focus {
.fas {
color: white !important;
}
}
}
.map {
padding-left: 2.2rem !important;
}
.td-map {
position: relative;
padding-left: 2.2rem !important;
width: 35px !important;
.parsed {
position: absolute;
left: .3rem !important;
}
img {
width: 40px !important;
height: auto;
}
}
.td-rank img {
width: 50px !important;
height: auto;
max-width: 50px;
}
.td-score {
font-size: 1rem !important;
max-width: 90px;
}
.td-date {
font-size: 1rem !important;
}
.kills, .deaths, .assists, .kdiff, .duration, .hltv, .length,
.td-kills, .td-deaths, .td-assists, .td-plus, .td-duration, .td-hltv, .td-length {
display: none;
}
}
@media screen and (max-width: 991px) {
.matches {
width: 100% !important;
}
.side-info {
display: none !important;
}
.avatar {
width: 100px !important;
height: 100px !important;
}
.trackme-btn {
top: 25px;
}
}
@media screen and (max-width: 1199px) {
.td-plus, .kdiff {
display: none;
}
}
</style>