mirror of
https://github.com/anatolykopyl/vk-bingo.git
synced 2026-03-26 21:04:26 +00:00
Added sse and a new screen
This commit is contained in:
@@ -1,154 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="card" v-if="card !== null" v-on:click="nextCard()" v-bind:class="{clickable: showResult}">
|
||||
<img class="meme" v-bind:src="card.image">
|
||||
<h2>Кто скинул этот мем?</h2>
|
||||
<div class="interactive">
|
||||
<transition name="fade-answers">
|
||||
<List v-if="selectedAnswer === null"
|
||||
:options="options" @selectedAnswer="selectAnswer" />
|
||||
</transition>
|
||||
<transition name="spin-result">
|
||||
<Result v-if="showResult"
|
||||
:name="card.name" :selectedName="selectedAnswer" :date="card.date" :correct="correctAnswer" />
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<Score v-if="card !== null" :score="score" />
|
||||
<square-loader v-if="card === null" :color="'#f3f3f3'" class="loader" />
|
||||
<Stats />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import List from './List.vue'
|
||||
import Result from './Result.vue'
|
||||
import Score from './Score.vue'
|
||||
import Stats from './Stats.vue'
|
||||
|
||||
import SquareLoader from 'vue-spinner/src/SquareLoader.vue'
|
||||
|
||||
export default {
|
||||
name: 'Game',
|
||||
components: {
|
||||
List,
|
||||
Result,
|
||||
Score,
|
||||
Stats,
|
||||
SquareLoader
|
||||
},
|
||||
props: {
|
||||
score: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: null,
|
||||
card: null,
|
||||
correctAnswer: null, // True or False
|
||||
selectedAnswer: null, // Чье-то имя
|
||||
showResult: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCard: function() {
|
||||
this.correctAnswer = null
|
||||
this.selectedAnswer = null
|
||||
this.showResult = false
|
||||
axios
|
||||
.get(process.env.VUE_APP_BACKEND + '/card')
|
||||
.then(response => {
|
||||
this.card = response.data
|
||||
})
|
||||
},
|
||||
nextCard: function() {
|
||||
if (this.showResult) {
|
||||
this.card = null
|
||||
this.getCard()
|
||||
}
|
||||
},
|
||||
selectAnswer: function(selection) {
|
||||
this.selectedAnswer = selection
|
||||
let innerThis = this
|
||||
setTimeout(function() {
|
||||
innerThis.showResult = true
|
||||
if (innerThis.correctAnswer) {
|
||||
innerThis.score.right++
|
||||
} else {
|
||||
innerThis.score.wrong++
|
||||
}
|
||||
}, 805)
|
||||
axios
|
||||
.post(process.env.VUE_APP_BACKEND + '/answer', {
|
||||
'data': {
|
||||
'id': this.card._id,
|
||||
'name': this.selectedAnswer
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
this.correctAnswer = response.data.correct
|
||||
this.card = response.data.card
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCard()
|
||||
axios
|
||||
.get(process.env.VUE_APP_BACKEND + '/options')
|
||||
.then(response => (this.options = response.data))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.card {
|
||||
width: 450px;
|
||||
padding: 18px;
|
||||
border-radius: 17px;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
|
||||
background-color: #121212;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.meme {
|
||||
width: 100%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.interactive {
|
||||
position: relative;
|
||||
-webkit-perspective: 900000px;
|
||||
perspective: 900000px;
|
||||
}
|
||||
|
||||
.fade-answers-leave-active {
|
||||
transition: all 0.8s ease;
|
||||
}
|
||||
.fade-answers-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.3);
|
||||
}
|
||||
|
||||
.spin-result-enter-active {
|
||||
transition: all 2s ease;
|
||||
}
|
||||
.spin-result-enter-from {
|
||||
transform: scale(0.2);
|
||||
transform: rotateY(120deg);
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 520px) {
|
||||
.card {
|
||||
width: 94%;
|
||||
padding: 3%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,41 +0,0 @@
|
||||
<template>
|
||||
<div class="answers">
|
||||
<span class="option" v-for="name in options" :key="name" v-on:click="selectAnswer(name)">
|
||||
{{ name }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'List',
|
||||
props: {
|
||||
options: Array
|
||||
},
|
||||
methods: {
|
||||
selectAnswer: function(selection) {
|
||||
this.$emit('selectedAnswer', selection)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.answers {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.option {
|
||||
background-color: #5a5a5a;
|
||||
border-radius: 6px;
|
||||
margin: 3px;
|
||||
padding: 5px 9px;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.option:hover {
|
||||
transform: scale(1.06);
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -1,80 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Авторизация:</h1>
|
||||
<p>{{ question }}</p>
|
||||
<input v-model="answer"><br>
|
||||
<button v-on:click="login" v-bind:class="{wrong: loggedIn === false}">Ввод</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
axios.defaults.withCredentials = true
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
data() {
|
||||
return {
|
||||
question: null,
|
||||
answer: null,
|
||||
loggedIn: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
login: function() {
|
||||
axios
|
||||
.post(process.env.VUE_APP_BACKEND + '/auth', {
|
||||
"pass": this.answer,
|
||||
})
|
||||
.then(response => {
|
||||
this.loggedIn = response.status == "200"
|
||||
this.$emit('loggedIn', this.loggedIn)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.question = process.env.VUE_APP_QUESTION
|
||||
this.login()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
background-color: #121212;
|
||||
width: 400px;
|
||||
margin: auto;
|
||||
border-radius: 18px;
|
||||
padding: 40px 10px;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
padding: 5px 8px;
|
||||
margin-bottom: 1em;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
width: 20ch;
|
||||
}
|
||||
|
||||
button {
|
||||
color: white;
|
||||
font-size: 1em;
|
||||
box-sizing: content-box;
|
||||
background-color: #5a5a5a;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
width: 20ch;
|
||||
padding: 5px 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 520px) {
|
||||
div {
|
||||
width: 100%;
|
||||
padding: 40px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<span v-show="!correct" class="wrong">Нет, это был не {{ selectedName }} 😢</span>
|
||||
<div class="result" v-bind:class="{correct: correct}">
|
||||
{{ name }} {{ date }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Result",
|
||||
props: {
|
||||
name: String,
|
||||
selectedName: String,
|
||||
date: String,
|
||||
correct: Boolean
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.result {
|
||||
padding: 30px 40px;
|
||||
border-radius: 8px;
|
||||
background-color: #5a5a5a;
|
||||
}
|
||||
|
||||
.correct {
|
||||
color: #121212;
|
||||
background-color: rgb(124, 230, 124);
|
||||
}
|
||||
|
||||
.wrong {
|
||||
color: rgb(255, 71, 71);
|
||||
}
|
||||
</style>
|
||||
@@ -1,51 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<span class="score-right">{{ score.right }}</span>
|
||||
<span class="score-wrong">{{ score.wrong }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Score",
|
||||
props: {
|
||||
score: Object
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
width: 350px;
|
||||
border-radius: 0 0 17px 17px;
|
||||
background-color: #f3f3f3;
|
||||
margin: auto;
|
||||
padding: 0.4em 18px;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.score-right {
|
||||
color: rgb(124, 230, 124);
|
||||
}
|
||||
|
||||
.score-wrong {
|
||||
color: rgb(255, 71, 71);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 520px) {
|
||||
div {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
padding: 0.4em 0;
|
||||
bottom: 0;
|
||||
border-radius: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,80 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<span>🎭 <small>Самый непредсказуемый:</small> <b>{{ mostOriginal }}</b> 🎭</span><br>
|
||||
<span>🪂 <small>Самый стабильный:</small> <b>{{ mostPredictable }}</b> 🪂</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Stats',
|
||||
data() {
|
||||
return {
|
||||
stats: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mostOriginal: function() {
|
||||
let value = 1
|
||||
let returnName
|
||||
|
||||
for (const name in this.stats) {
|
||||
if (this.stats[name] < value) {
|
||||
value = this.stats[name]
|
||||
returnName = name
|
||||
}
|
||||
}
|
||||
|
||||
return returnName
|
||||
},
|
||||
mostPredictable: function() {
|
||||
let value = 0
|
||||
let returnName
|
||||
|
||||
for (const name in this.stats) {
|
||||
if (this.stats[name] > value) {
|
||||
value = this.stats[name]
|
||||
returnName = name
|
||||
}
|
||||
}
|
||||
|
||||
return returnName
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
axios
|
||||
.get(process.env.VUE_APP_BACKEND + '/stats')
|
||||
.then(response => {
|
||||
response.data.forEach(element => {
|
||||
this.stats[element._id] = element.correct / element.wrong
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
div {
|
||||
width: auto;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 2em;
|
||||
padding: 1em;
|
||||
background-color: #121212;
|
||||
border-radius: 7px;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 520px) {
|
||||
div {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 1em 0;
|
||||
margin: 1em 0 0 0;
|
||||
border-radius: 17px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user