feat: start vuejs layout system to add tabs in summoner profiles

This commit is contained in:
Valentin Kaelin 2019-12-03 21:57:52 +01:00
parent a5ab09a2a8
commit 3d60937996
9 changed files with 285 additions and 208 deletions

View file

@ -1,24 +1,34 @@
<template> <template>
<div id="app" class="font-sans bg-blue-900 antialiased min-h-screen"> <div id="app" class="font-sans bg-blue-900 antialiased min-h-screen">
<SVGContainer /> <SVGContainer />
<NotificationsContainer /> <NotificationsContainer />
<component :is="layout">
<router-view /> <router-view />
</component>
</div> </div>
</template> </template>
<script> <script>
import { mapActions } from 'vuex' import { mapActions } from 'vuex'
import Default from '@/layouts/Default.vue'
import Home from '@/layouts/Home.vue'
import NotificationsContainer from '@/components/NotificationsContainer.vue' import NotificationsContainer from '@/components/NotificationsContainer.vue'
import SVGContainer from '@/components/SVGContainer.vue' import SVGContainer from '@/components/SVGContainer.vue'
export default { export default {
components: { components: {
Default,
Home,
NotificationsContainer, NotificationsContainer,
SVGContainer SVGContainer
}, },
computed: {
layout() {
return (this.$route.meta.layout || 'Default')
}
},
created() { created() {
this.updatePercent() this.updatePercent()
}, },

View file

@ -0,0 +1,223 @@
<template>
<div class="bg-blue-900 overflow-hidden min-h-screen flex flex-col">
<LazyBackground
:image-source="require('@/assets/img/bg-homepage-1.jpg')"
image-class="absolute w-full h-200 z-0"
more-backgrounds="linear-gradient(180deg, rgba(42, 67, 101, 0) 0%, #2A4365 50%),"
transition-name="fade"
></LazyBackground>
<div class="relative page-wrapper mx-auto z-10 flex-grow">
<header class="text-teal-100">
<div class="flex justify-between items-center">
<router-link to="/">
<img class="h-24" src="@/assets/img/Logo.svg" alt="LeagueStats logo" />
</router-link>
<SearchForm @formSubmit="redirect" size="small" />
</div>
</header>
<template v-if="summonerFound">
<div class="text-white pb-12">
<div class="flex justify-between items-center">
<div>
<div class="flex items-center">
<h1 class="text-4xl font-extrabold uppercase">
<span class="text-5xl">{{ summonerInfos.account.name[0] }}</span>
<span>{{ summonerInfos.account.name.substring(1) }}</span>
</h1>
<div
v-if="playing"
class="ml-4 mt-2 flex items-center px-3 py-1 rounded-full bg-teal-800 border border-teal-400"
>
<div class="playing-dot bg-teal-flashy w-2 h-2 rounded-full"></div>
<span class="ml-2 text-teal-flashy font-semibold text-sm">In Game</span>
</div>
</div>
<div class="flex">
<div :class="{'playing': playing}" class="relative w-24 h-24">
<div
:class="{'border-2': !playing}"
class="relative z-10 w-24 h-24 rounded-full bg-blue-1000 bg-center bg-cover border-teal-400"
:style="{backgroundImage: `url('https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/profile-icons/${summonerInfos.account.profileIconId}.jpg')`}"
>
<div
class="absolute left-0 bottom-0 w-8 h-8 flex items-center justify-center bg-blue-900 rounded-full text-xs text-teal-500 font-extrabold border-2 border-teal-400"
>{{ summonerInfos.account.summonerLevel }}</div>
</div>
</div>
<SummonerRanked
v-if="Object.entries(summonerInfos.ranked).length !== 0"
:ranked="summonerInfos.ranked"
/>
</div>
</div>
<div>
<RecentActivity :matches="summonerInfos.matchList" />
</div>
</div>
<!-- NAVIGATION -->
<router-link
:to="{ name: 'summoner', params: { region: $route.params.region, name: $route.params.name }}"
class="pb-2 border-b-2 border-transparent text-blue-300 cursor-pointer hover:text-blue-100"
exact
>overview</router-link>
<router-link
:to="{ name: 'summonerChampions', params: { region: $route.params.region, name: $route.params.name }}"
class="ml-4 pb-2 border-b-2 border-transparent text-blue-300 cursor-pointer hover:text-blue-100"
exact
>champions</router-link>
<transition
enter-active-class="transition-all transition-fast ease-out-quad"
enter-class="opacity-0 scale-90"
enter-to-class="opacity-100 scale-100"
>
<slot></slot>
</transition>
</div>
</template>
<template v-else-if="summonerLoading">
<SummonerLoader />
</template>
<template v-else-if="summonerNotFound">
<div class="mt-16 flex justify-center">
<div class="bg-gradient px-4 py-3 rounded-lg text-center text-lg text-blue-100 font-bold">
<div>Player can't be found.</div>
<div>😕</div>
</div>
</div>
</template>
</div>
<MainFooter />
</div>
</template>
<script>
import { mapState, mapActions, mapGetters } from 'vuex'
import LazyBackground from '@/components/LazyBackgroundImage.vue'
import MainFooter from '@/components/MainFooter.vue'
import RecentActivity from '@/components/Summoner/RecentActivity.vue'
import SearchForm from '@/components/SearchForm.vue'
import SummonerLoader from '@/components/Summoner/SummonerLoader.vue'
import SummonerRanked from '@/components/Summoner/SummonerRanked.vue'
export default {
components: {
LazyBackground,
MainFooter,
RecentActivity,
SearchForm,
SummonerLoader,
SummonerRanked,
},
computed: {
summoner() {
return this.$route.params.name
},
region() {
return this.$route.params.region
},
uri() {
return `${this.summoner}|${this.region}`
},
...mapState({
summonerInfos: state => state.summoner.infos
}),
...mapGetters('summoner', ['playing', 'summonerFound', 'summonerNotFound', 'summonerLoading'])
},
watch: {
uri() {
console.log('route changed')
this.updateCurrentRegion(this.region)
this.apiCall()
}
},
mounted() {
this.updateCurrentRegion(this.region)
this.apiCall()
},
methods: {
apiCall() {
this.summonerRequest({ summoner: this.summoner, region: this.region })
},
redirect(summoner, region) {
this.$router.push(`/summoner/${region}/${summoner}`)
},
...mapActions(['updateCurrentRegion']),
...mapActions('summoner', ['summonerRequest']),
}
}
</script>
<style scoped>
.router-link-active {
color: #fff;
border-color: #fff;
}
.playing::before {
z-index: 0;
background: rgba(137, 160, 181, 0.2);
}
.playing::before,
.playing::after {
content: "";
position: absolute;
height: 100px;
width: 100px;
top: -2px;
left: -2px;
right: 0;
bottom: 0;
border-radius: 50%;
}
.playing::after {
z-index: 0;
background: linear-gradient(
to top,
rgba(0, 0, 0, 0) 30%,
rgb(36, 232, 204) 100%
);
animation: 0.75s linear 0s infinite normal none running rotate;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
.playing-dot {
box-shadow: 0 0 0 0 rgba(0, 0, 0, 1);
transform: scale(1);
animation: 2.5s ease-in-out 0s infinite normal none running pulse;
}
@keyframes pulse {
0% {
transform: scale(0.95);
box-shadow: 0 0 0 0 rgba(36, 232, 204, 0.7);
}
70% {
transform: scale(1);
box-shadow: 0 0 0 8px rgba(0, 0, 0, 0);
}
100% {
transform: scale(0.95);
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
}
}
</style>

View file

@ -0,0 +1,5 @@
<template>
<div>
<slot />
</div>
</template>

View file

@ -3,6 +3,7 @@ import Router from 'vue-router'
import Home from '@/views/Home.vue' import Home from '@/views/Home.vue'
import Summoner from '@/views/Summoner.vue' import Summoner from '@/views/Summoner.vue'
import SummonerChampions from '@/views/SummonerChampions.vue'
Vue.use(Router) Vue.use(Router)
@ -13,12 +14,20 @@ export default new Router({
{ {
path: '/', path: '/',
name: 'home', name: 'home',
component: Home component: Home,
meta: {
layout: 'Home'
}
}, },
{ {
path: '/summoner/:region/:name', path: '/summoner/:region/:name',
name: 'summoner', name: 'summoner',
component: Summoner component: Summoner
} },
{
path: '/summoner/:region/:name/champions',
name: 'summonerChampions',
component: SummonerChampions
},
] ]
}) })

View file

@ -1,66 +1,5 @@
<template> <template>
<div class="bg-blue-900 overflow-hidden min-h-screen flex flex-col"> <div class="mt-3 flex">
<LazyBackground
:image-source="require('@/assets/img/bg-homepage-1.jpg')"
image-class="absolute w-full h-200 z-0"
more-backgrounds="linear-gradient(180deg, rgba(42, 67, 101, 0) 0%, #2A4365 50%),"
transition-name="fade"
></LazyBackground>
<div class="relative page-wrapper mx-auto z-10 flex-grow">
<header class="text-teal-100">
<div class="flex justify-between items-center">
<router-link to="/">
<img class="h-24" src="@/assets/img/Logo.svg" alt="LeagueStats logo" />
</router-link>
<SearchForm @formSubmit="redirect" size="small" />
</div>
</header>
<template v-if="summonerFound">
<div class="text-white pb-12">
<div class="flex justify-between items-center">
<div>
<div class="flex items-center">
<h1 class="text-4xl font-extrabold uppercase">
<span class="text-5xl">{{ summonerInfos.account.name[0] }}</span>
<span>{{ summonerInfos.account.name.substring(1) }}</span>
</h1>
<div
v-if="playing"
class="ml-4 mt-2 flex items-center px-3 py-1 rounded-full bg-teal-800 border border-teal-400"
>
<div class="playing-dot bg-teal-flashy w-2 h-2 rounded-full"></div>
<span class="ml-2 text-teal-flashy font-semibold text-sm">In Game</span>
</div>
</div>
<div class="flex">
<div :class="{'playing': playing}" class="relative w-24 h-24">
<div
:class="{'border-2': !playing}"
class="relative z-10 w-24 h-24 rounded-full bg-blue-1000 bg-center bg-cover border-teal-400"
:style="{backgroundImage: `url('https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/profile-icons/${summonerInfos.account.profileIconId}.jpg')`}"
>
<div
class="absolute left-0 bottom-0 w-8 h-8 flex items-center justify-center bg-blue-900 rounded-full text-xs text-teal-500 font-extrabold border-2 border-teal-400"
>{{ summonerInfos.account.summonerLevel }}</div>
</div>
</div>
<SummonerRanked
v-if="Object.entries(summonerInfos.ranked).length !== 0"
:ranked="summonerInfos.ranked"
/>
</div>
</div>
<div>
<RecentActivity :matches="summonerInfos.matchList" />
</div>
</div>
<div class="mt-3 text-center flex">
<div class="mt-4 w-3/12"> <div class="mt-4 w-3/12">
<SummonerChampions /> <SummonerChampions />
<SummonerStats /> <SummonerStats />
@ -82,151 +21,35 @@
>More matches</LoadingButton> >More matches</LoadingButton>
</div> </div>
</div> </div>
</div>
</template> </template>
<template v-else-if="summonerLoading">
<SummonerLoader />
</template>
<template v-else-if="summonerNotFound">
<div class="mt-16 flex justify-center">
<div class="bg-gradient px-4 py-3 rounded-lg text-center text-lg text-blue-100 font-bold">
<div>Player can't be found.</div>
<div>😕</div>
</div>
</div>
</template>
</div>
<MainFooter />
</div>
</template>
<script> <script>
import { mapState, mapActions, mapGetters } from 'vuex' import { mapState, mapActions, mapGetters } from 'vuex'
import LazyBackground from '@/components/LazyBackgroundImage.vue'
import LoadingButton from '@/components/LoadingButton.vue' import LoadingButton from '@/components/LoadingButton.vue'
import MainFooter from '@/components/MainFooter.vue'
import Match from '@/components/Match/Match.vue' import Match from '@/components/Match/Match.vue'
import RecentActivity from '@/components/Summoner/RecentActivity.vue' import SummonerChampions from '@/components/Summoner/Overview/SummonerChampions.vue'
import SearchForm from '@/components/SearchForm.vue' import SummonerMates from '@/components/Summoner/Overview/SummonerMates.vue'
import SummonerChampions from '@/components/Summoner/SummonerChampions.vue' import SummonerStats from '@/components/Summoner/Overview/SummonerStats.vue'
import SummonerLoader from '@/components/Summoner/SummonerLoader.vue'
import SummonerMates from '@/components/Summoner/SummonerMates.vue'
import SummonerRanked from '@/components/Summoner/SummonerRanked.vue'
import SummonerStats from '@/components/Summoner/SummonerStats.vue'
export default { export default {
components: { components: {
LazyBackground,
LoadingButton, LoadingButton,
MainFooter,
Match, Match,
RecentActivity,
SearchForm,
SummonerChampions, SummonerChampions,
SummonerLoader,
SummonerMates, SummonerMates,
SummonerRanked,
SummonerStats, SummonerStats,
}, },
computed: { computed: {
summoner() {
return this.$route.params.name
},
region() {
return this.$route.params.region
},
...mapState({ ...mapState({
summonerInfos: state => state.summoner.infos summonerInfos: state => state.summoner.infos
}), }),
...mapGetters('ddragon', ['version']), ...mapGetters('summoner', ['matchesLoading', 'moreMatchesToFetch'])
...mapGetters('summoner', ['matchesLoading', 'moreMatchesToFetch', 'playing', 'summonerFound', 'summonerNotFound', 'summonerLoading'])
},
watch: {
$route() {
console.log('route changed')
this.updateCurrentRegion(this.region)
this.apiCall()
}
},
mounted() {
this.updateCurrentRegion(this.region)
this.apiCall()
}, },
methods: { methods: {
apiCall() { ...mapActions('summoner', ['moreMatches']),
this.summonerRequest({ summoner: this.summoner, region: this.region })
},
redirect(summoner, region) {
this.$router.push(`/summoner/${region}/${summoner}`)
},
...mapActions(['updateCurrentRegion']),
...mapActions('summoner', ['summonerRequest', 'moreMatches']),
} }
} }
</script> </script>
<style scoped>
.playing::before {
z-index: 0;
background: rgba(137, 160, 181, 0.2);
}
.playing::before,
.playing::after {
content: "";
position: absolute;
height: 100px;
width: 100px;
top: -2px;
left: -2px;
right: 0;
bottom: 0;
border-radius: 50%;
}
.playing::after {
z-index: 0;
background: linear-gradient(
to top,
rgba(0, 0, 0, 0) 30%,
rgb(36, 232, 204) 100%
);
animation: 0.75s linear 0s infinite normal none running rotate;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
.playing-dot {
box-shadow: 0 0 0 0 rgba(0, 0, 0, 1);
transform: scale(1);
animation: 2.5s ease-in-out 0s infinite normal none running pulse;
}
@keyframes pulse {
0% {
transform: scale(0.95);
box-shadow: 0 0 0 0 rgba(36, 232, 204, 0.7);
}
70% {
transform: scale(1);
box-shadow: 0 0 0 8px rgba(0, 0, 0, 0);
}
100% {
transform: scale(0.95);
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
}
}
</style>

View file

@ -0,0 +1,7 @@
<template>
<div>
<div class="mt-3 min-h-screen">
<div class="mt-16 text-center">Coming soon...😉</div>
</div>
</div>
</template>