# Basic Quiz app
This project is part of
Basic quiz app
## Basic setup
# Quiz app in JS for portfolio.
The quiz app is a common
Let's create the `package.json` with the following
```
npm init -y
```
## Install dependencies
```
npm install lite-server --save-dev
```
For front-end, we are to use going.
```
npm install bulma-extensions
```
### Create directories and files
```bash
mkdir -p js css
```
```bash
touch index.html README.md js/app.js css/styles.css
```
## Basic template
For the next step I use Bulma's [Starter template](https://bulma.io/documentation/overview/start/):
> Copy the "Starter template"
>
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Quiz app</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.0/css/bulma.min.css">
</head>
<body>
<section class="section">
<div class="container">
<h1 class="title">
Welcome to the Quiz App Show
</h1>
<p class="subtitle">
My first website with <strong>Bulma</strong>!
</p>
</div>
</section>
</body>
</html>
```
## Create dev script
In the `package.json` file add the following script
```json
...
"scripts": {
"dev": "lite-server"
}
...
```
Open your terminal and run it. It will open a new browser window and will show our new page
```bash
npm run dev
```

## Add Bulma extensions
Just below to the bulma's style sheet
```htmlmixed=
<link rel="stylesheet" href="/node_modules/bulma-extensions/dist/css/bulma-extensions.min.css">
```
Then add this line just above the `</body>` tag
```htmlembedded=
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bulma-steps@2.2.1/dist/js/bulma-steps.min.js"></script>
```
## Add the survey structure
```htmlmixed=
<!-- Main container -->
<nav class="level">
<div class="level-left"></div>
<!-- Right side -->
<div class="level-right has-text-centered">
<div class="level-item">
<div>
<p class="heading">Hits</p>
<p class="title">Hits / Total</p>
</div>
</div>
</div>
</nav>
<!-- /nav.level -->
```
## Adding Questions
Add the `bulma steps` script just above the `</body>` tag
```htmlmixed=
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bulma-steps@2.2.1/dist/js/bulma-steps.min.js"></script>
```
Then, add this code to below of `</nav>` tag
> [reference]: https://wikiki.github.io/components/steps/
```htmlmixed=
<div class="steps" id="stepsDemo">
<div class="step-item is-active is-success">
<div class="step-marker">1</div>
<div class="step-details">
<p class="step-title">Account</p>
</div>
</div>
<!-- /div.step-item -->
<div class="step-item">
<div class="step-marker">2</div>
<div class="step-details">
<p class="step-title">Profile</p>
</div>
</div>
<!-- /div.step-item -->
<div class="step-item">
<div class="step-marker">3</div>
<div class="step-details">
<p class="step-title">Social</p>
</div>
</div>
<!-- /div.step-item -->
<div class="step-item">
<div class="step-marker">4</div>
<div class="step-details">
<p class="step-title">Finish</p>
</div>
</div>
<!-- /div.step-item -->
<div class="steps-content column is-mobile">
<!-- Your questions here -->
</div>
<!-- /div.step-content -->
<div class="steps-actions">
<div class="steps-action">
<a href="#" data-nav="previous" class="button is-light">Previous</a>
</div>
<div class="steps-action">
<a href="#" data-nav="next" class="button is-light">Next</a>
</div>
</div>
<!-- /div.step-actions -->
</div>
```
Note that there are three main sections in "`bulma steps`":
- steps items
- steps content
- steps actions
You must add a `step-item` for each question of the quiz.
The questions must be inside of the `<div class="steps-content column is-mobile">` tag.
### Question structure
Every question have the following structure:
```htmlmixed=
<div class="step-content column is-6 is-offset-3 is-active">
<h2 class="title">Question # 1</h2>
<div class="tile is-ancestor">
<div class="tile is-12">
<div class="tile box option-box answer">
<p class="subtitle">a)</p>
<p>Option 1</p>
</div>
</div>
</div>
</div>
```
So, we will add three more questions:
### Add vue.js
Go to [Vue official page](https://vuejs.org/v2/guide/) and add to the `index.html` dependencies
```htmlmixed=
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
```
### Edit the app.js file
Write the following code in the `js/app.js`.
```js
var app = new Vue({
el: '#app',
data: {},
methods: {}
})
```
Add your `app.js` file to `index.html`.
Add the `hits` and `questions` length.
```js
var app = new Vue({
el: '#app',
data: {
hits: 0,
answers: 0,
questions: []
},
methods: {}
})
```
Now, Fill the questions array:
```js
questions: [
{
"id": 1,
"question": "What does CSS stand for?",
"nextId": 2,
"previousId": null,
"answer": "c",
"options": {
"a": "Computer Style Sheets",
"b": "Creative Style Sheets",
"c": "Cascading Style Sheets",
"d": "Colourful Style Sheets"
}
},
{
"id": 2,
"question": "Where in an HTML document is the correct place to refer to an external style sheet?",
"nextId": 2,
"previousId": 1,
"answer": "a",
"options": {
"a": "In the <head> section",
"b": "In the <body> section",
"c": "At the end of the document",
"d": "You can't refer to an external style sheet"
}
},
{
"id": 3,
"question": "Which HTML tag is used to define an internal style sheet?",
"nextId": 4,
"previousId": 2,
"answer": "a",
"options": {
"a": "<style>",
"b": "<script>",
"c": "<headStyle>",
"d": "<css>"
}
},
{
"id": 4,
"question": "Which HTML attribute is used to define inline styles?",
"nextId": null,
"previousId": 3,
"answer": "b",
"options": {
"a": "class",
"b": "style",
"c": "font",
"d": "styles"
}
}
]
```
in `index.html` edit the the level component
```html
<p class="title">{{ hits }}/{{ questions.length }}</p>
```
Edit your questions and add them dinamically adding the `v-for` attribute
```htmlmixed=
<div v-for="(question, index) in questions" class="step-content is-active column is-6 is-offset-3">
```
Render the options for each question:
```htmlmixed=
<div v-for="(value, key) in question.options" class="tile is-ancestor">
<div class="tile is-12">
<div class="tile box option-box answer" v-on:click.self="selectOption" :data-index="index" :data-key="key" :data-value="value">
<p class="subtitle">{{ key }})</p>
<p>{{ value }}</p>
</div>
</div>
</div>
```
## Add actions
Add the `selectOption` method:
```javascript=
methods: {
selectOption: function (evt) {
if (evt) {
document.querySelectorAll('div.answer').forEach(element => {
element.classList.remove('answer') // disable css hover effect
})
const element = evt.target
const answer = element.dataset.key
const index = parseInt(element.dataset.index) + 1
const question = this.getQuestion(index)
if (answer === question.answer) {
this.hits++
element.classList.add('right-answer')
} else {
element.classList.add('wrong-answer')
}
this.answers++
if (this.answers === this.questions.length) {
// show modal and return
document.querySelector('div.modal').classList.add('is-active')
}
setTimeout(function () {
// trigger click event on <a> next button
document.querySelector('a[data-nav="next"]').click()
document.querySelectorAll('div.option-box').forEach(element => {
element.classList.add('answer') // enable css hover effect
})
}, 1000)
}
}
},
getQuestion: function (index) {
for (let i = 0; i < this.questions.length; i++) {
if (index === this.questions[i].id) {
return this.questions[i]
}
}
return false
}
```
## Add styles
Edit you `app.css` file:
```css
div.answer:hover {
background-color: rgb(14, 140, 243);
}
h2.question {
margin-bottom: 10% !important;
}
.right-answer {
background-color: mediumaquamarine;
}
.wrong-answer {
background-color: orangered;
}
nav.level {
padding: 0 10%;
}
div.modal-content {
padding: 10% 0;
background-color: powderblue;
}
div.modal-content button {
margin-top: 5%;
}
```
And add the file to the `index.html`
## Add modal
Below to step component, add the following code:
```htmlmixed=
<div class="modal">
<div class="modal-background"></div>
<div class="modal-content">
<div class="has-text-centered">
<h2 class="title">Congratulations!!!</h2>
<h2 class="subtitle">You have {{ hits }} / {{ questions.length }} rigth answers</h2>
<button v-on:click="closeModal" class="button is-success">Ok</button>
</div>
</div>
<button class="modal-close is-large" aria-label="close" v-on:click="closeModal"></button>
</div>
<!-- /div.model -->
</div>
```
Master Source: https://github.com/driverInside/basic-quiz/blob/master/js/app.js