added new login code and testing components
This commit is contained in:
79
src/components/Login.vue
Normal file
79
src/components/Login.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<!-- components/Login.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
<h2 class="title">Login or Register</h2>
|
||||
<p class="subtitle error-msg">{{ errorMsg }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="field">
|
||||
<label class="label is-large" for="email">Email:</label>
|
||||
<div class="control">
|
||||
<input type="email" class="input is-large" id="email" v-model="email">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label is-large" for="password">Password:</label>
|
||||
<div class="control">
|
||||
<input type="password" class="input is-large" id="password" v-model="password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control">
|
||||
<a class="button is-large is-primary" @click="authenticate">Login</a>
|
||||
<a class="button is-large is-success" @click="register">Register</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { EventBus } from '@/utils'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
email: '',
|
||||
password: '',
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
authenticate () {
|
||||
this.$store.dispatch('login', { email: this.email, password: this.password })
|
||||
.then(() => this.$router.push('/'))
|
||||
},
|
||||
register () {
|
||||
this.$store.dispatch('register', { email: this.email, password: this.password })
|
||||
.then(() => this.$router.push('/'))
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
EventBus.$on('failedRegistering', (msg) => {
|
||||
this.errorMsg = msg
|
||||
})
|
||||
EventBus.$on('failedAuthentication', (msg) => {
|
||||
this.errorMsg = msg
|
||||
})
|
||||
},
|
||||
beforeDestroy () {
|
||||
EventBus.$off('failedRegistering')
|
||||
EventBus.$off('failedAuthentication')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.error-msg {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
75
src/components/NewQuestion.vue
Normal file
75
src/components/NewQuestion.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field">
|
||||
<label class="label is-large">Question</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input is-large" v-model="question">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<a class="button is-large is-info" @click="addChoice">
|
||||
<span class="icon is-small">
|
||||
<i class="fa fa-plus-square-o fa-align-left" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span>Add choice</span>
|
||||
</a>
|
||||
<a class="button is-large is-primary" @click="saveQuestion">
|
||||
<span class="icon is-small">
|
||||
<i class="fa fa-check"></i>
|
||||
</span>
|
||||
<span>Save</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="label is-large" v-show="choices.length > 0">Question Choices</h2>
|
||||
<div class="field has-addons" v-for="(choice, idx) in choices" v-bind:key="idx">
|
||||
<div class="control choice">
|
||||
<input type="text" class="input is-large" v-model="choices[idx]">
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-large">
|
||||
<span class="icon is-small" @click.stop="removeChoice(choice)">
|
||||
<i class="fa fa-times" aria-hidden="true"></i>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
question: '',
|
||||
choices: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeChoice (choice) {
|
||||
const idx = this.choices.findIndex(c => c === choice)
|
||||
this.choices.splice(idx, 1)
|
||||
},
|
||||
saveQuestion () {
|
||||
this.$emit('questionComplete', {
|
||||
question: this.question,
|
||||
choices: this.choices.filter(c => !!c)
|
||||
})
|
||||
this.question = ''
|
||||
this.choices = ['']
|
||||
},
|
||||
addChoice () {
|
||||
this.choices.push('')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.choice {
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
122
src/components/NewSurvey.vue
Normal file
122
src/components/NewSurvey.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
<h2 class="title">{{ name }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="tabs is-centered is-fullwidth is-large">
|
||||
<ul>
|
||||
<li :class="{'is-active': step == 'name'}" @click="step = 'name'">
|
||||
<a>Name</a>
|
||||
</li>
|
||||
<li :class="{'is-active': step == 'questions'}" @click="step = 'questions'">
|
||||
<a>Questions</a>
|
||||
</li>
|
||||
<li :class="{'is-active': step == 'review'}" @click="step = 'review'">
|
||||
<a>Review</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column is-half is-offset-one-quarter">
|
||||
|
||||
<div class="name" v-show="step === 'name'">
|
||||
<div class="field">
|
||||
<label class="label is-large" for="name">Survey name:</label>
|
||||
<div class="control">
|
||||
<input type="text" class="input is-large" id="name" v-model="name">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="questions" v-show="step === 'questions'">
|
||||
<new-question v-on:questionComplete="appendQuestion"/>
|
||||
</div>
|
||||
|
||||
<div class="review" v-show="step === 'review'">
|
||||
<ul>
|
||||
<li class="question" v-for="(question, qIdx) in questions" :key="`question-${qIdx}`">
|
||||
<div class="title">
|
||||
{{ question.question }}
|
||||
<span class="icon is-medium is-pulled-right delete-question"
|
||||
@click.stop="removeQuestion(question)">
|
||||
<i class="fa fa-times" aria-hidden="true"></i>
|
||||
</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li v-for="(choice , cIdx) in question.choices" :key="`choice-${cIdx}`">
|
||||
{{ cIdx + 1 }}. {{ choice }}
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="control">
|
||||
<a class="button is-large is-primary" @click="submitSurvey">Submit</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NewQuestion from '@/components/NewQuestion'
|
||||
|
||||
export default {
|
||||
components: { NewQuestion },
|
||||
data () {
|
||||
return {
|
||||
step: 'name',
|
||||
name: '',
|
||||
questions: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
appendQuestion (newQuestion) {
|
||||
this.questions.push(newQuestion)
|
||||
},
|
||||
removeQuestion (question) {
|
||||
const idx = this.questions.findIndex(q => q.question === question.question)
|
||||
this.questions.splice(idx, 1)
|
||||
},
|
||||
submitSurvey () {
|
||||
this.$store.dispatch('submitNewSurvey', {
|
||||
name: this.name,
|
||||
questions: this.questions
|
||||
})
|
||||
.then(() => this.$router.push('/'))
|
||||
.catch((error) => {
|
||||
console.log('Error creating survey', error)
|
||||
this.$router.push('/')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.question {
|
||||
margin: 10px 20px 25px 10px;
|
||||
}
|
||||
|
||||
.delete-question {
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.delete-question:hover {
|
||||
background-color: lightgray;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
115
src/components/Survey.vue
Normal file
115
src/components/Survey.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div>
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container has-text-centered">
|
||||
<h2 class="title">{{ survey.name }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
|
||||
<div class="columns">
|
||||
<div class="column is-10 is-offset-1">
|
||||
|
||||
<div
|
||||
v-for="(question, idx) in survey.questions"
|
||||
v-bind:key="question.id"
|
||||
v-show="currentQuestion === idx">
|
||||
|
||||
<div class="column is-offset-3 is-6">
|
||||
<h4 class='title has-text-centered'>{{ question.text }}</h4>
|
||||
</div>
|
||||
<div class="column is-offset-4 is-4">
|
||||
<div class="control">
|
||||
<div v-for="choice in question.choices" v-bind:key="choice.id">
|
||||
<label class="radio">
|
||||
<input type="radio" v-model="question.choice" name="choice" :value="choice.id">
|
||||
{{ choice.text }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="column is-offset-one-quarter is-half">
|
||||
<nav class="pagination is-centered" role="navigation" aria-label="pagination">
|
||||
<a class="pagination-previous" @click.stop="goToPreviousQuestion"><i class="fa fa-chevron-left" aria-hidden="true"></i> Back</a>
|
||||
<a class="pagination-next" @click.stop="goToNextQuestion">Next <i class="fa fa-chevron-right" aria-hidden="true"></i></a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="has-text-centered">
|
||||
<a v-show="surveyComplete" class='button is-large is-focused is-primary' @click="handleSubmit">Submit</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
currentQuestion: 0
|
||||
}
|
||||
},
|
||||
beforeMount () {
|
||||
this.$store.dispatch('loadSurvey', { id: parseInt(this.$route.params.id) })
|
||||
},
|
||||
methods: {
|
||||
goToNextQuestion () {
|
||||
if (this.currentQuestion === this.survey.questions.length - 1) {
|
||||
this.currentQuestion = 0
|
||||
} else {
|
||||
this.currentQuestion++
|
||||
}
|
||||
},
|
||||
goToPreviousQuestion () {
|
||||
if (this.currentQuestion === 0) {
|
||||
this.currentQuestion = this.survey.questions.lenth - 1
|
||||
} else {
|
||||
this.currentQuestion--
|
||||
}
|
||||
},
|
||||
handleSubmit () {
|
||||
this.$store.dispatch('addSurveyResponse')
|
||||
.then(() => this.$router.push('/'))
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
surveyComplete () {
|
||||
if (this.survey.questions) {
|
||||
const numQuestions = this.survey.questions.length
|
||||
const numCompleted = this.survey.questions.filter(q => q.choice).length
|
||||
return numQuestions === numCompleted
|
||||
}
|
||||
return false
|
||||
},
|
||||
survey () {
|
||||
return this.$store.state.currentSurvey
|
||||
},
|
||||
selectedChoice: {
|
||||
get () {
|
||||
const question = this.survey.questions[this.currentQuestion]
|
||||
return question.choice
|
||||
},
|
||||
set (value) {
|
||||
const question = this.survey.questions[this.currentQuestion]
|
||||
this.$store.commit('setChoice', { questionId: question.id, choice: value })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
Reference in New Issue
Block a user