mirror of
https://github.com/vkaelin/LeagueStats.git
synced 2026-03-25 12:57:28 +00:00
Add Vuex and create Notifications Component
This commit is contained in:
parent
4b98a83b78
commit
84eae5380f
10 changed files with 184 additions and 32 deletions
16
client/package-lock.json
generated
16
client/package-lock.json
generated
|
|
@ -4522,10 +4522,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-utils": {
|
"eslint-utils": {
|
||||||
"version": "1.3.1",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
|
||||||
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
|
"integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"eslint-visitor-keys": "^1.0.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"eslint-visitor-keys": {
|
"eslint-visitor-keys": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|
@ -11232,6 +11235,11 @@
|
||||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"vuex": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-ER5moSbLZuNSMBFnEBVGhQ1uCBNJslH9W/Dw2W7GZN23UQA69uapP5GTT9Vm8Trc0PzBSVt6LzF3hGjmv41xcg=="
|
||||||
|
},
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
"axios": "^0.18.1",
|
"axios": "^0.18.1",
|
||||||
"vue": "^2.6.6",
|
"vue": "^2.6.6",
|
||||||
"vue-axios": "^2.1.4",
|
"vue-axios": "^2.1.4",
|
||||||
"vue-router": "^3.0.6"
|
"vue-router": "^3.0.6",
|
||||||
|
"vuex": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fullhuman/postcss-purgecss": "^1.2.0",
|
"@fullhuman/postcss-purgecss": "^1.2.0",
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app" class="font-sans bg-gray-200 antialiased">
|
<div id="app" class="font-sans bg-gray-200 antialiased min-h-screen">
|
||||||
|
|
||||||
|
<NotificationsContainer/>
|
||||||
<!-- <div class="nav">
|
|
||||||
<router-link to="/">Accueil</router-link> |
|
|
||||||
<router-link :to="`/summoner/euw/${summoner}`">
|
|
||||||
{{ linkText }}
|
|
||||||
</router-link>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<router-view/>
|
<router-view/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
#app {
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import NotificationsContainer from '@/components/NotificationsContainer.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
components: {
|
||||||
return {
|
NotificationsContainer
|
||||||
linkText: 'Test link',
|
|
||||||
summoner: 'Kalane'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,14 @@
|
||||||
.fade-enter, .fade-leave-to {
|
.fade-enter, .fade-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slide-fade-enter-active,
|
||||||
|
.slide-fade-leave-active {
|
||||||
|
transition: all 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-fade-enter,
|
||||||
|
.slide-fade-leave-to {
|
||||||
|
transform: translateX(400px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
24
client/src/components/NotificationsContainer.vue
Normal file
24
client/src/components/NotificationsContainer.vue
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<template>
|
||||||
|
<div class="pr-2 pb-2 fixed bottom-0 right-0 z-50">
|
||||||
|
<PopupNotification
|
||||||
|
v-for="notification in notifications"
|
||||||
|
:key="notification.id"
|
||||||
|
:notification="notification"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import PopupNotification from '@/components/PopupNotification.vue';
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
PopupNotification
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapState('notification', ['notifications'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
69
client/src/components/PopupNotification.vue
Normal file
69
client/src/components/PopupNotification.vue
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
<template>
|
||||||
|
<transition name="slide-fade">
|
||||||
|
<div
|
||||||
|
:class="{
|
||||||
|
'bg-red-500': notification.type === 'error',
|
||||||
|
'bg-green-500': notification.type === 'success'
|
||||||
|
}"
|
||||||
|
class="mt-2 relative rounded-lg shadow-md p-6 pr-10 text-white"
|
||||||
|
style="min-width: 240px"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
@click="deleteNotification"
|
||||||
|
class="cursor-pointer block absolute top-0 right-0 border border-transparent rounded-full py-1 px-1 my-1 mx-1 focus:outline-none hover:border-white"
|
||||||
|
>
|
||||||
|
<svg class="fill-current w-3 h-3" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div class="flex items-center text-white">
|
||||||
|
<svg v-if="notification.type === 'success'" class="w-6 fill-current" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32zM6.7 9.29L9 11.6l4.3-4.3 1.4 1.42L9 14.4l-3.7-3.7 1.4-1.42z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<svg v-if="notification.type === 'error'" class="w-6 fill-current" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="ml-3">{{ notification.message }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapActions } from 'vuex'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
notification: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
timeout: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
deleteNotification() {
|
||||||
|
this.remove(this.notification)
|
||||||
|
},
|
||||||
|
...mapActions('notification', ['remove'])
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.timeout = setTimeout(() => this.deleteNotification(), 3000)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -85,8 +85,16 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
formSubmit() {
|
formSubmit() {
|
||||||
console.log('form submit child');
|
const regexNames = new RegExp('^[0-9\\p{L} _\\.]+$', 'u');
|
||||||
this.$emit('formSubmit', this.summoner.split(' ').join(''), this.selectedRegion.toLowerCase());
|
|
||||||
|
if(regexNames.exec(this.summoner)) {
|
||||||
|
this.$emit('formSubmit', this.summoner.split(' ').join(''), this.selectedRegion.toLowerCase());
|
||||||
|
} else {
|
||||||
|
this.$store.dispatch('notification/add', {
|
||||||
|
type: 'error',
|
||||||
|
message: 'Summoner Name entered is incorrect.'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,19 +5,24 @@ import DotLoader from 'vue-spinner/src/DotLoader.vue'
|
||||||
|
|
||||||
import '@/assets/css/main.css'
|
import '@/assets/css/main.css'
|
||||||
import 'vue-awesome/icons'
|
import 'vue-awesome/icons'
|
||||||
|
import Icon from 'vue-awesome/components/Icon'
|
||||||
|
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import Icon from 'vue-awesome/components/Icon'
|
import store from './store'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
Vue.use(VueAxios, axios)
|
Vue.use(VueAxios, axios)
|
||||||
|
|
||||||
Vue.component('v-icon', Icon)
|
Vue.component('v-icon', Icon)
|
||||||
Vue.component('dot-loader', DotLoader)
|
Vue.component('dot-loader', DotLoader)
|
||||||
|
|
||||||
Vue.prototype.$patch = '9.16.1'
|
Vue.prototype.$patch = '9.16.1'
|
||||||
|
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
router,
|
router,
|
||||||
|
store,
|
||||||
render: h => h(App),
|
render: h => h(App),
|
||||||
}).$mount('#app')
|
}).$mount('#app')
|
||||||
|
|
|
||||||
14
client/src/store/index.js
Normal file
14
client/src/store/index.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import * as notification from '@/store/modules/notification'
|
||||||
|
|
||||||
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
const debug = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
|
export default new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
notification,
|
||||||
|
},
|
||||||
|
strict: debug
|
||||||
|
})
|
||||||
30
client/src/store/modules/notification.js
Normal file
30
client/src/store/modules/notification.js
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
export const namespaced = true
|
||||||
|
|
||||||
|
export const state = {
|
||||||
|
notifications: []
|
||||||
|
}
|
||||||
|
|
||||||
|
let nextId = 1
|
||||||
|
|
||||||
|
export const mutations = {
|
||||||
|
PUSH(state, notification) {
|
||||||
|
state.notifications.push({
|
||||||
|
...notification,
|
||||||
|
id: nextId++
|
||||||
|
})
|
||||||
|
},
|
||||||
|
DELETE(state, notificationToRemove) {
|
||||||
|
state.notifications = state.notifications.filter(
|
||||||
|
notification => notification.id !== notificationToRemove.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
add({ commit }, notification) {
|
||||||
|
commit('PUSH', notification)
|
||||||
|
},
|
||||||
|
remove({ commit }, notificationToRemove) {
|
||||||
|
commit('DELETE', notificationToRemove)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue