mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
feat: add loading animation on load more matches button
This commit is contained in:
parent
e09c7d59b5
commit
a7561a82b8
4 changed files with 136 additions and 5 deletions
117
client/src/components/LoadingButton.vue
Normal file
117
client/src/components/LoadingButton.vue
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<template>
|
||||
<button
|
||||
@click="btnClicked"
|
||||
:class="[btnClass, {'loading': loading}, {'pr-12': loading}]"
|
||||
:disabled="loading"
|
||||
class="relative"
|
||||
type="button"
|
||||
>
|
||||
<slot>Send</slot>
|
||||
<span class="spinner absolute opacity-0 left-auto">
|
||||
<span
|
||||
class="inline-block absolute right-0 w-4 h-4 opacity-100 border-3 border-white rounded-full"
|
||||
></span>
|
||||
<span
|
||||
class="inline-block absolute right-0 w-4 h-4 opacity-100 border-3 border-white rounded-full"
|
||||
></span>
|
||||
<span
|
||||
class="inline-block absolute right-0 w-4 h-4 opacity-100 border-3 border-white rounded-full"
|
||||
></span>
|
||||
<span
|
||||
class="inline-block absolute right-0 w-4 h-4 opacity-100 border-3 border-white rounded-full"
|
||||
></span>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
btnClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
btnClicked() {
|
||||
this.$emit('clicked')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
button {
|
||||
transition: all 0.2s;
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
top: 50%;
|
||||
right: 1.7rem;
|
||||
margin: -0.5rem;
|
||||
transition-property: padding, opacity;
|
||||
transition-duration: 0.2s, 0.2s;
|
||||
transition-timing-function: ease-in, ease;
|
||||
transition-delay: 0s, 0.2s;
|
||||
}
|
||||
|
||||
.spinner span {
|
||||
animation: spinner 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
border-color: #fff transparent transparent transparent;
|
||||
}
|
||||
|
||||
.spinner span:nth-child(1) {
|
||||
animation-delay: 0.45s;
|
||||
}
|
||||
|
||||
.spinner span:nth-child(2) {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.spinner span:nth-child(3) {
|
||||
animation-delay: 0.15s;
|
||||
}
|
||||
|
||||
.loading .spinner {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
button:not(:disabled) .spinner span {
|
||||
box-shadow: 0 0 0 0.2rem #4fd1c5 inset;
|
||||
border: 7.4px solid transparent;
|
||||
transition: all 0.4s;
|
||||
}
|
||||
|
||||
button:not(:disabled) .spinner span:nth-child(1) {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
button:not(:disabled) .spinner span:nth-child(2) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
button:not(:disabled) .spinner span:nth-child(3) {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
button:not(:disabled) .spinner span:nth-child(4) {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -11,11 +11,17 @@ export const state = {
|
|||
matches: [],
|
||||
soloQ: {}
|
||||
},
|
||||
matchesLoading: false,
|
||||
status: '',
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
MATCHES_LOADING(state) {
|
||||
state.matchesLoading = true
|
||||
},
|
||||
MATCHES_FOUND(state, newMatches) {
|
||||
state.matchesLoading = false
|
||||
|
||||
state.infos.matches = [...state.infos.matches, ...newMatches]
|
||||
|
||||
state.infos.matchIndex += newMatches.length
|
||||
|
|
@ -38,6 +44,8 @@ export const mutations = {
|
|||
|
||||
export const actions = {
|
||||
async moreMatches({ commit }) {
|
||||
commit('MATCHES_LOADING')
|
||||
|
||||
const account = state.infos.account
|
||||
const gameIds = state.infos.matchList.slice(state.infos.matchIndex, state.infos.matchIndex + 10).map(({ gameId }) => gameId)
|
||||
|
||||
|
|
@ -69,6 +77,7 @@ export const actions = {
|
|||
}
|
||||
|
||||
export const getters = {
|
||||
matchesLoading: state => state.matchesLoading,
|
||||
moreMatchesToFetch: state => state.infos.matchIndex < state.infos.matchList.length,
|
||||
summonerFound: state => state.status === 'found',
|
||||
summonerNotFound: state => state.status === 'error',
|
||||
|
|
|
|||
|
|
@ -87,11 +87,13 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<button
|
||||
<LoadingButton
|
||||
v-if="moreMatchesToFetch"
|
||||
@click="moreMatches"
|
||||
class="mt-4 block mx-auto bg-blue-800 px-4 py-2 rounded-md font-semibold hover:bg-blue-1000 shadow-lg"
|
||||
>More matches</button>
|
||||
@clicked="moreMatches"
|
||||
:loading="matchesLoading"
|
||||
btn-class="mt-4 block mx-auto bg-blue-800 px-4 py-2 rounded-md font-semibold hover:bg-blue-1000 shadow-lg"
|
||||
>More matches</LoadingButton>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -113,6 +115,7 @@
|
|||
<script>
|
||||
import { mapState, mapActions, mapGetters } from 'vuex'
|
||||
import LazyBackground from '@/components/LazyBackgroundImage.vue'
|
||||
import LoadingButton from '@/components/LoadingButton.vue'
|
||||
import RecentActivity from '@/components/RecentActivity.vue'
|
||||
import Match from '@/components/Match.vue'
|
||||
import SearchForm from '@/components/SearchForm.vue'
|
||||
|
|
@ -120,6 +123,7 @@ import SearchForm from '@/components/SearchForm.vue'
|
|||
export default {
|
||||
components: {
|
||||
LazyBackground,
|
||||
LoadingButton,
|
||||
Match,
|
||||
RecentActivity,
|
||||
SearchForm
|
||||
|
|
@ -138,7 +142,7 @@ export default {
|
|||
...mapState({
|
||||
summonerInfos: state => state.summoner.infos
|
||||
}),
|
||||
...mapGetters('summoner', ['moreMatchesToFetch', 'summonerFound', 'summonerNotFound', 'summonerLoading'])
|
||||
...mapGetters('summoner', ['matchesLoading', 'moreMatchesToFetch', 'summonerFound', 'summonerNotFound', 'summonerLoading'])
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ module.exports = {
|
|||
default: '1px',
|
||||
'0': '0',
|
||||
'2': '2px',
|
||||
'3': '3px',
|
||||
'4': '4px',
|
||||
'8': '8px',
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue