Finished creating result statistic views

This commit is contained in:
Vivek Santayana 2022-08-31 23:58:48 +01:00
parent 187c52cd44
commit 96d751843a
10 changed files with 258 additions and 28 deletions

View File

@ -0,0 +1,23 @@
<template>
<svg-icon type="mdi" :path="path"></svg-icon>
</template>
<script>
import SvgIcon from '@jamescoyle/vue-icon'
import { mdiChevronDoubleRight } from '@mdi/js'
export default {
name: "mdiChefronDoubleRight",
components: {
SvgIcon
},
data() {
return {
path: mdiChevronDoubleRight,
}
}
}
</script>

View File

@ -50,7 +50,7 @@
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
<MenuItems class="origin-top-right absolute right-0 mt-2 p-1 space-y-2 w-56 rounded-md shadow-lg bg-lime-700 ring-1 ring-black ring-opacity-5 focus:outline-none">
<div class="py-1">
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes" :key="route.path" >
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes.filter( value => value.meta.index >= 0 )" :key="route.path" >
<a :href="route.path" target="_blank" rel="noopener noreferrer" :class="[active ? 'text-orange-300' : 'text-white', 'flex px-4 py-2 active:text-orange-500 rounded-lg h-fit align-middle transition-all ease-in-out duration-500']" v-if="route.path.startsWith('http')">
<div class="inline-flex px-3 py-1 space-x-1">
<span class="scale-75">

View File

@ -1,5 +1,5 @@
import { createRouter, createWebHistory } from 'vue-router'
import { mdiAccountBoxMultiple, mdiAccountGroupOutline, mdiAccountQuestion, mdiChartBox, mdiCodeTags, mdiCounter, mdiEarth, mdiHandCoin, mdiHome, mdiInformation, mdiWeb } from '@mdi/js'
import { mdiAccountBoxMultiple, mdiAccountGroupOutline, mdiAccountQuestion, mdiChartBox, mdiCodeTags, mdiCompare, mdiCounter, mdiEarth, mdiHandCoin, mdiHome, mdiInformation, mdiWeb } from '@mdi/js'
import About from '@/views/about/Index.vue'
import AboutPage from '@/views/about/About.vue'
import Acknowledgements from '@/views/about/Acknowledgements.vue'
@ -13,8 +13,9 @@ import Refused from '@/views/errors/Refused.vue'
import Results from '@/views/results/Index.vue'
import ResultsPage from '@/views/results/Results.vue'
import Scores from '@/views/results/Scores.vue'
import Answers from '@/views/results/Answers.vue'
import CompareAnswers from '@/views/results/CompareAnswers.vue'
import Statistics from '@/views/results/Statistics.vue'
import CompareResults from '@/views/results/CompareResults.vue'
const routes = [
{
@ -144,17 +145,28 @@ const routes = [
component: Scores,
meta: {
index: 1,
title: 'All Scores',
title: 'Your Scores',
svgPath: mdiCounter,
parentIndex: -1
}
},
{
path: 'compare',
name: 'CompareResults',
component: CompareResults,
meta: {
index: 2,
title: 'Compare Results',
svgPath: mdiCompare,
parentIndex: -1
}
},
{
path: 'statistics',
name: 'Statistics',
component: Statistics,
meta: {
index: 2,
index: 3,
title: 'Statistics',
svgPath: mdiChartBox,
parentIndex: -1
@ -163,10 +175,10 @@ const routes = [
{
path: 'answers',
name: 'Answers',
component: Answers,
component: CompareAnswers,
meta: {
index: 3,
title: 'Global Answers',
index: 4,
title: 'Compare Answers',
svgPath: mdiEarth,
parentIndex: -1
}

View File

@ -4,15 +4,19 @@ export const useAppStore = defineStore({
id: 'app',
state: () => ({
hasData: false,
results: {}
answers: [],
playbooks: {},
results: {},
scores: {},
count: null
}),
actions: {
toggleData() {
this.hasData = !this.hasData
console.log('Toggled Has Data. New value', this.hasData)
},
storeResults(results) {
this.results = JSON.parse(JSON.stringify(results))
store(key, data) {
this[key] = JSON.parse(JSON.stringify(data))
}
}
})

View File

@ -93,7 +93,7 @@
}
}
).then( (response) => {
this.appStore.storeResults(response.data)
this.appStore.store('results', response.data)
console.log('Results fetched from the server.')
this.$router.push('/results')
}).catch( (error) => {
@ -125,7 +125,7 @@
<div v-for="(answer, index) in questionStore.questions[this.id].answers" :key="`q${this.id}-o${index}`" class="inline-flex">
<input :type="this.questionStore.questions[this.id].select > 1 ? 'checkbox' : 'radio'" class="checkbox" :id="`q${this.id}-o${index}`" :value=index :key="`q${this.id}-o${index}`" v-model="answersStore.answers[this.id]" :disabled="this.questionStore.questions[this.id].select > 1 && this.answersStore.answers[this.id].length == this.questionStore.questions[this.id].select && !this.answersStore.answers[this.id].includes(index)">
<label :for="`q${this.id}-o${index}`">
<div v-html="answer" class="uncial-antiqua w-full h-full p-2 transition-all duration-100 ease-in-out hover:bg-lime-200 hover:text-orange-600 hover:cursor-pointer" :aria-label="answer" :title="answer"></div>
<div v-html="answer" class="uncial-antiqua w-full h-full p-2 select-none transition-all duration-100 ease-in-out hover:bg-lime-200 hover:text-orange-600 hover:cursor-pointer" :aria-label="answer" :title="answer"></div>
</label>
</div>
</div>

View File

@ -14,7 +14,7 @@
<template>
<TextFrame>
<Header>
Global Answers
Compare Answers
</Header>
<Content>

View File

@ -0,0 +1,101 @@
<script>
import axios from 'axios'
import Config from '@/config.js'
import Content from '@/components/Content.vue'
import Header from '@/components/Header.vue'
import TextFrame from '@/components/TextFrame.vue'
import { useAppStore } from '@/stores/app.js'
import ChevronDoubleRight from '@/components/icons/ChevronDoubleRight.vue'
export default {
setup() {
const appStore = useAppStore()
return {
appStore
}
},
mounted() {
this.getResults()
},
name: 'CompareResults',
components: {
ChevronDoubleRight,
Content,
Header,
TextFrame
},
methods: {
getResults() {
axios.get(`${Config.SERVER}api/playbooks/`)
.then((response) => {
this.error = false
this.appStore.store('playbooks', response.data)
})
.catch( error => {
this.$router.push('/err_refused')
})
axios.get(`${Config.SERVER}api/count/`)
.then((response) => {
this.error = false
this.appStore.store('count', response.data)
})
.catch( error => {
this.$router.push('/err_refused')
})
}
}
}
</script>
<template>
<TextFrame>
<Header>
Compare Results
</Header>
<Content>
<p class="text-leader">
Based on others who have taken this quiz, here are the playbooks of fellow travellers you are likely to meet along the way.
</p>
<table class="table-auto w-full max-w-sm mx-auto text-left">
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th>
</th>
<th>
Playbook
</th>
<th>
Number
</th>
<th>
Percentage
</th>
</tr>
</thead>
<tbody>
<tr v-for="(number, playbook, index) in this.appStore.playbooks" :key="playbook" class="hover:bg-yellow-50" :class="index % 2 == 0? `bg-lime-50 border-b dark:bg-gray-900 dark:border-gray-700` : `bg-lime-100 border-b dark:bg-gray-800 dark:border-gray-700`">
<td v-if="this.appStore.results.playbooks.some(obj => obj.hasOwnProperty(playbook))">
<ChevronDoubleRight/>
</td>
<td v-else>
</td>
<td scope="col" class="py-1 capitalize">
The {{ playbook }}
</td>
<td scope="col" class="py-1">
{{ number }}
</td>
<td scope="col" class="py-1">
{{ Math.round(100*number/this.appStore.count) }} &#x25;
</td>
</tr>
<tr>
<td colspan="4" class="text-center text-lg">Out of a total {{ this.appStore.count }} users</td>
</tr>
</tbody>
</table>
</Content>
</TextFrame>
</template>

View File

@ -49,12 +49,11 @@
<section v-for="playbook in this.appStore.results.playbooks" :key="Object.keys(playbook)[0]" class="border-solid border-b-2 border-lime-600 border-opacity-25">
<h2 class="flex justify-between">
<span class="uncial-antiqua align-bottom">
<span class="text-xl">The</span> <span class="text-3xl">{{ Object.keys(playbook)[0].slice(0,1).toUpperCase()+Object.keys(playbook)[0].slice(1) }}</span>
<span class="text-xl">The</span> <span class="text-3xl capitalize">{{ Object.keys(playbook)[0] }}</span>
</span>
<span class="text-sm">Pages {{ Object.values(playbook)[0].pages }}</span>
</h2>
<p class="text-leader">
{{ Object.values(playbook)[0].flavour }}
<p class="text-leader" v-html="Object.values(playbook)[0].flavour">
</p>
<p>
{{ Object.values(playbook)[0].blurb }}

View File

@ -23,16 +23,16 @@
<template>
<TextFrame>
<Header>
Scores
Your Scores
</Header>
<Content>
<p>
The following are your scores for each playbook:
<p class="text-leader">
While the playbook you are is the one most reflected by your answers, here are the other playbooks and the extent to which they have a bearing upon your journey.
</p>
<table class="table-auto w-full max-w-xs mx-auto">
<thead>
<table class="table-auto w-full max-w-sm mx-auto text-left">
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th>
<th class="pl-10">
Playbook
</th>
<th>
@ -41,11 +41,11 @@
</tr>
</thead>
<tbody>
<tr v-for="(score, playbook) in this.appStore.results.all_playbooks" :key="playbook">
<td>
The {{ playbook.slice(0,1).toUpperCase() + playbook.slice(1) }}
<tr v-for="(score, playbook, index) in this.appStore.results.all_playbooks" :key="playbook" class="hover:bg-yellow-50" :class="index % 2 == 0? `bg-lime-50 border-b dark:bg-gray-900 dark:border-gray-700` : `bg-lime-100 border-b dark:bg-gray-800 dark:border-gray-700`">
<td scope="col" class="py-1 pl-10 capitalize">
The {{ playbook }}
</td>
<td>
<td scope="col" class="py-1">
{{ Math.round(100*score/this.appStore.results.max_score) }} &#x25;
</td>
</tr>

View File

@ -1,13 +1,49 @@
<script>
import axios from 'axios'
import Config from '@/config.js'
import Content from '@/components/Content.vue'
import Header from '@/components/Header.vue'
import TextFrame from '@/components/TextFrame.vue'
import { useAppStore } from '@/stores/app.js'
import ChevronDoubleRight from '@/components/icons/ChevronDoubleRight.vue'
export default {
setup() {
const appStore = useAppStore()
return {
appStore
}
},
mounted() {
this.getScores()
},
name: 'Statistics',
components: {
ChevronDoubleRight,
Content,
Header,
TextFrame
},
methods: {
getScores() {
axios.get(`${Config.SERVER}api/scores/`)
.then((response) => {
this.error = false
this.appStore.store('scores', response.data)
})
.catch( error => {
this.$router.push('/err_refused')
})
axios.get(`${Config.SERVER}api/count/`)
.then((response) => {
this.error = false
this.appStore.store('count', response.data)
})
.catch( error => {
this.$router.push('/err_refused')
})
}
}
}
</script>
@ -17,7 +53,62 @@
Statistics
</Header>
<Content>
<p class="text-leader">
Sometimes, it can help to have some additional insight into the likelihood of meeting different people.
Or, indeed, it can provide insight into how the questions we ask of each other bias the way we perceive the world.
</p>
<table class="table-auto w-full max-w-lg mx-auto text-left">
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th>
</th>
<th>
Playbook
</th>
<th>
Your Score
</th>
<th>
Mean Score
</th>
<th>
Median Score
</th>
<th>
Standard Deviation
</th>
</tr>
</thead>
<tbody>
<tr v-for="(stats, playbook, index) in this.appStore.scores" :key="playbook" class="hover:bg-yellow-50" :class="index % 2 == 0? `bg-lime-50 border-b dark:bg-gray-900 dark:border-gray-700` : `bg-lime-100 border-b dark:bg-gray-800 dark:border-gray-700`">
<td v-if="this.appStore.results.playbooks.some(obj => obj.hasOwnProperty(playbook))">
<ChevronDoubleRight/>
</td>
<td v-else>
</td>
<td scope="col" class="py-1 capitalize">
The {{ playbook }}
</td>
<td>
{{ Math.round(100*this.appStore.results.all_playbooks[playbook]/this.appStore.results.max_score) }}
</td>
<td scope="col" class="py-1">
{{ Math.round(stats.mean * 100) / 100 }}
</td>
<td scope="col" class="py-1">
{{ Math.round(stats.median * 100) / 100 }}
</td>
<td>
{{ Math.round(stats.standard_deviation * 100) / 100 }}
</td>
</tr>
<tr>
<td colspan="4" class="text-center text-lg">Out of a total {{ this.appStore.count }} users</td>
</tr>
</tbody>
</table>
</Content>
</TextFrame>
</template>