Nearly finished app
This commit is contained in:
parent
0965548a6c
commit
3788f08679
23
client/src/components/icons/FeatureSearch.vue
Normal file
23
client/src/components/icons/FeatureSearch.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<svg-icon type="mdi" :path="path"></svg-icon>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SvgIcon from '@jamescoyle/vue-icon'
|
||||||
|
import { mdiFeatureSearch } from '@mdi/js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MdiFeatureSearch",
|
||||||
|
|
||||||
|
components: {
|
||||||
|
SvgIcon
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
path: mdiFeatureSearch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -37,20 +37,20 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
<!-- Menu Items -->
|
<!-- Menu Items -->
|
||||||
<div class="hidden md:flex space-x-3 justify-center items-center">
|
<div class="hidden md:flex space-x-3 justify-center items-center">
|
||||||
<Navlink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes.filter( value => value.meta.index >= 0 )" :key="route.path" />
|
<Navlink :svgPath="route.meta.svgPath" :text="route.meta.title" :to="route.path" v-for="route in $router.options.routes.filter( value => value.meta.indexBase >= 0 )" :key="route.path" />
|
||||||
</div>
|
</div>
|
||||||
<Menu v-slot="{ open }" as="div" class="relative inline-block text-left md:hidden">
|
<Menu v-slot="{ open }" as="div" class="relative inline-block text-left md:hidden">
|
||||||
<div>
|
<div>
|
||||||
<MenuButton class="inline-flex justify-center w-full rounded-md shadow-sm px-4 py-2 bg-lime-800 text-white hover:bg-lime-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500">
|
<MenuButton class="inline-flex justify-center w-full rounded-md drop-shadow-sm px-4 py-2 bg-lime-800 text-white hover:bg-lime-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500">
|
||||||
<span class="scale-150">
|
<span class="scale-150">
|
||||||
<mdiMenu/>
|
<mdiMenu/>
|
||||||
</span>
|
</span>
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
</div>
|
</div>
|
||||||
<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">
|
<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">
|
<MenuItems class="origin-top-right absolute right-0 mt-2 p-1 space-y-2 w-56 rounded-md drop-shadow-lg bg-lime-700 ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||||
<div class="py-1">
|
<div class="py-1">
|
||||||
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes.filter( value => value.meta.index >= 0 )" :key="route.path" >
|
<MenuItem v-slot="{ active }" v-for="route in $router.options.routes.filter( value => value.meta.indexBase >= 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')">
|
<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">
|
<div class="inline-flex px-3 py-1 space-x-1">
|
||||||
<span class="scale-75">
|
<span class="scale-75">
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</h1>
|
</h1>
|
||||||
<div class="flex flex-col text-md">
|
<div class="flex flex-col text-md">
|
||||||
<Navlink :svgPath="route.meta.svgPath" :text="route.meta.title" :prefix="prefix" :to="route.path" v-for="route in routes" :key="route.path" />
|
<Navlink :route="route" :prefix="prefix" v-for="route in routes" :key="route.path" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -7,27 +7,25 @@ export default {
|
|||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
'prefix',
|
'prefix',
|
||||||
'svgPath',
|
'route'
|
||||||
'text',
|
|
||||||
'to'
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<a :href="to" class="navlink" target="_blank" rel="noopener noreferrer" v-if="to.startsWith('http')">
|
<a :href="route.path" class="navlink" target="_blank" rel="noopener noreferrer" v-if="route.path.startsWith('http')">
|
||||||
<div class="inline-flex px-2 py-1 items-center space-x-1">
|
<div class="inline-flex px-2 py-1 items-center space-x-1">
|
||||||
<span class="scale-75">
|
<span class="scale-75">
|
||||||
<svg-icon type="mdi" :path="svgPath"></svg-icon>
|
<svg-icon type="mdi" :path="route.meta.svgPath"></svg-icon>
|
||||||
</span>
|
</span>
|
||||||
<span>{{ text }}</span>
|
<span>{{ route.meta.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<router-link exact-active-class="active-link" class="navlink" :to="prefix + '/' + to" v-else>
|
<router-link :exact-active-class="route.hasOwnProperty('children') ? `` : `active-link`" :active-class="route.hasOwnProperty('children') ? 'active-link' : ''" class="navlink" :to="prefix + '/' + route.path" v-else>
|
||||||
<div class="inline-flex px-2 py-1 items-center space-x-1">
|
<div class="inline-flex px-2 py-1 items-center space-x-1">
|
||||||
<span class="scale-75">
|
<span class="scale-75">
|
||||||
<svg-icon type="mdi" :path="svgPath"></svg-icon>
|
<svg-icon type="mdi" :path="route.meta.svgPath"></svg-icon>
|
||||||
</span>
|
</span>
|
||||||
<span>{{ text }}</span>
|
<span>{{ route.meta.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import { mdiAccountBoxMultiple, mdiAccountGroupOutline, mdiAccountQuestion, mdiChartBox, mdiCodeTags, mdiCompare, mdiCounter, mdiEarth, mdiHandCoin, mdiHome, mdiInformation, mdiWeb } from '@mdi/js'
|
import { mdiAccountBoxMultiple, mdiAccountGroupOutline, mdiAccountQuestion, mdiChartBox, mdiCodeTags, mdiCompare, mdiCounter, mdiForum, mdiHandCoin, mdiHome, mdiInformation, mdiLicense, mdiWeb } from '@mdi/js'
|
||||||
import About from '@/views/about/Index.vue'
|
import About from '@/views/about/Index.vue'
|
||||||
import AboutPage from '@/views/about/About.vue'
|
import AboutPage from '@/views/about/About.vue'
|
||||||
|
import Licenses from '@/views/about/Licenses.vue'
|
||||||
import Acknowledgements from '@/views/about/Acknowledgements.vue'
|
import Acknowledgements from '@/views/about/Acknowledgements.vue'
|
||||||
import Wanderhome from '@/views/about/Wanderhome.vue'
|
import Wanderhome from '@/views/about/Wanderhome.vue'
|
||||||
import Home from '@/views/Home.vue'
|
import Home from '@/views/Home.vue'
|
||||||
@ -13,9 +14,11 @@ import Refused from '@/views/errors/Refused.vue'
|
|||||||
import Results from '@/views/results/Index.vue'
|
import Results from '@/views/results/Index.vue'
|
||||||
import ResultsPage from '@/views/results/Results.vue'
|
import ResultsPage from '@/views/results/Results.vue'
|
||||||
import Scores from '@/views/results/Scores.vue'
|
import Scores from '@/views/results/Scores.vue'
|
||||||
import CompareAnswers from '@/views/results/CompareAnswers.vue'
|
import CompareAnswersIndex from '@/views/results/compare-answers/Index.vue'
|
||||||
import Statistics from '@/views/results/Statistics.vue'
|
import Statistics from '@/views/results/Statistics.vue'
|
||||||
import CompareResults from '@/views/results/CompareResults.vue'
|
import CompareResults from '@/views/results/CompareResults.vue'
|
||||||
|
import CompareQuestion from '@/views/results/compare-answers/CompareQuestion.vue'
|
||||||
|
import CompareQuestions from '@/views/results/compare-answers/CompareQuestions.vue'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -23,7 +26,7 @@ const routes = [
|
|||||||
name: 'Home',
|
name: 'Home',
|
||||||
component: Home,
|
component: Home,
|
||||||
meta: {
|
meta: {
|
||||||
index: 0,
|
indexBase: 0,
|
||||||
svgPath: mdiHome,
|
svgPath: mdiHome,
|
||||||
title: 'Home'
|
title: 'Home'
|
||||||
}
|
}
|
||||||
@ -33,7 +36,7 @@ const routes = [
|
|||||||
name: 'Quiz',
|
name: 'Quiz',
|
||||||
component: Quiz,
|
component: Quiz,
|
||||||
meta: {
|
meta: {
|
||||||
index: 1,
|
indexBase: 1,
|
||||||
svgPath: mdiAccountQuestion,
|
svgPath: mdiAccountQuestion,
|
||||||
title: 'Take the Quiz'
|
title: 'Take the Quiz'
|
||||||
},
|
},
|
||||||
@ -43,8 +46,8 @@ const routes = [
|
|||||||
name: 'Quiz',
|
name: 'Quiz',
|
||||||
component: QuizPage,
|
component: QuizPage,
|
||||||
meta: {
|
meta: {
|
||||||
index: 0,
|
indexChild: 0,
|
||||||
parentIndex: 1,
|
indexBase: 1,
|
||||||
title: 'Take the Quiz'
|
title: 'Take the Quiz'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -56,8 +59,8 @@ const routes = [
|
|||||||
id: parseInt(route.params.id)
|
id: parseInt(route.params.id)
|
||||||
}),
|
}),
|
||||||
meta: {
|
meta: {
|
||||||
index: 1,
|
indexChild: 1,
|
||||||
parentIndex: 1,
|
indexBase: 1,
|
||||||
title: 'Take the Quiz'
|
title: 'Take the Quiz'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,7 +71,7 @@ const routes = [
|
|||||||
name: 'About',
|
name: 'About',
|
||||||
component: About,
|
component: About,
|
||||||
meta: {
|
meta: {
|
||||||
index: 2,
|
indexBase: 2,
|
||||||
svgPath: mdiInformation,
|
svgPath: mdiInformation,
|
||||||
title: 'About'
|
title: 'About'
|
||||||
},
|
},
|
||||||
@ -78,19 +81,30 @@ const routes = [
|
|||||||
name: 'About',
|
name: 'About',
|
||||||
component: AboutPage,
|
component: AboutPage,
|
||||||
meta: {
|
meta: {
|
||||||
index: 0,
|
indexChild: 0,
|
||||||
parentIndex: 2,
|
indexBase: 2,
|
||||||
svgPath: mdiInformation,
|
svgPath: mdiInformation,
|
||||||
title: 'Background'
|
title: 'Background'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'licenses',
|
||||||
|
name: 'Licenses',
|
||||||
|
component: Licenses,
|
||||||
|
meta: {
|
||||||
|
indexChild: 1,
|
||||||
|
indexBase: 2,
|
||||||
|
svgPath: mdiLicense,
|
||||||
|
title: 'Licenses'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'wanderhome',
|
path: 'wanderhome',
|
||||||
name: 'Wanderhome',
|
name: 'Wanderhome',
|
||||||
component: Wanderhome,
|
component: Wanderhome,
|
||||||
meta: {
|
meta: {
|
||||||
index: 1,
|
indexChild: 2,
|
||||||
parentIndex: 2,
|
indexBase: 2,
|
||||||
svgPath: mdiHandCoin,
|
svgPath: mdiHandCoin,
|
||||||
title: 'About Wanderhome'
|
title: 'About Wanderhome'
|
||||||
}
|
}
|
||||||
@ -100,8 +114,8 @@ const routes = [
|
|||||||
name: 'Acknowledgements',
|
name: 'Acknowledgements',
|
||||||
component: Acknowledgements,
|
component: Acknowledgements,
|
||||||
meta: {
|
meta: {
|
||||||
index: 2,
|
indexChild: 3,
|
||||||
parentIndex: 2,
|
indexBase: 2,
|
||||||
svgPath: mdiAccountGroupOutline,
|
svgPath: mdiAccountGroupOutline,
|
||||||
title: 'Acknowledgements'
|
title: 'Acknowledgements'
|
||||||
}
|
}
|
||||||
@ -110,8 +124,8 @@ const routes = [
|
|||||||
path: 'https://git.vsnt.uk/viveksantayana/wanderhome-quiz',
|
path: 'https://git.vsnt.uk/viveksantayana/wanderhome-quiz',
|
||||||
name: 'SourceCode',
|
name: 'SourceCode',
|
||||||
meta: {
|
meta: {
|
||||||
index: 3,
|
indexChild: 4,
|
||||||
parentIndex: 2,
|
indexBase: 2,
|
||||||
svgPath: mdiCodeTags,
|
svgPath: mdiCodeTags,
|
||||||
title: 'View Source Code'
|
title: 'View Source Code'
|
||||||
}
|
}
|
||||||
@ -123,7 +137,7 @@ const routes = [
|
|||||||
name: 'Results',
|
name: 'Results',
|
||||||
component: Results,
|
component: Results,
|
||||||
meta: {
|
meta: {
|
||||||
index: -1,
|
indexBase: -1,
|
||||||
title: 'Results',
|
title: 'Results',
|
||||||
svgPath: mdiAccountBoxMultiple
|
svgPath: mdiAccountBoxMultiple
|
||||||
},
|
},
|
||||||
@ -133,10 +147,10 @@ const routes = [
|
|||||||
name: 'Result',
|
name: 'Result',
|
||||||
component: ResultsPage,
|
component: ResultsPage,
|
||||||
meta: {
|
meta: {
|
||||||
index: 0,
|
indexChild: 0,
|
||||||
title: 'Your Results',
|
title: 'Your Results',
|
||||||
svgPath: mdiAccountBoxMultiple,
|
svgPath: mdiAccountBoxMultiple,
|
||||||
parentIndex: -1
|
indexBase: -1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -144,10 +158,10 @@ const routes = [
|
|||||||
name: 'Scores',
|
name: 'Scores',
|
||||||
component: Scores,
|
component: Scores,
|
||||||
meta: {
|
meta: {
|
||||||
index: 1,
|
indexChild: 1,
|
||||||
title: 'Your Scores',
|
title: 'Your Scores',
|
||||||
svgPath: mdiCounter,
|
svgPath: mdiCounter,
|
||||||
parentIndex: -1
|
indexBase: -1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -155,10 +169,10 @@ const routes = [
|
|||||||
name: 'CompareResults',
|
name: 'CompareResults',
|
||||||
component: CompareResults,
|
component: CompareResults,
|
||||||
meta: {
|
meta: {
|
||||||
index: 2,
|
indexChild: 2,
|
||||||
title: 'Compare Results',
|
title: 'Compare Results',
|
||||||
svgPath: mdiCompare,
|
svgPath: mdiCompare,
|
||||||
parentIndex: -1
|
indexBase: -1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -166,22 +180,51 @@ const routes = [
|
|||||||
name: 'Statistics',
|
name: 'Statistics',
|
||||||
component: Statistics,
|
component: Statistics,
|
||||||
meta: {
|
meta: {
|
||||||
index: 3,
|
indexChild: 3,
|
||||||
title: 'Statistics',
|
title: 'Statistics',
|
||||||
svgPath: mdiChartBox,
|
svgPath: mdiChartBox,
|
||||||
parentIndex: -1
|
indexBase: -1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'answers',
|
path: 'answers',
|
||||||
name: 'Answers',
|
name: 'Answers',
|
||||||
component: CompareAnswers,
|
component: CompareAnswersIndex,
|
||||||
meta: {
|
meta: {
|
||||||
index: 4,
|
indexChild: 4,
|
||||||
title: 'Compare Answers',
|
title: 'Compare Answers',
|
||||||
svgPath: mdiEarth,
|
svgPath: mdiForum,
|
||||||
parentIndex: -1
|
indexBase: -1
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'RootAnswer',
|
||||||
|
component: CompareQuestions,
|
||||||
|
meta: {
|
||||||
|
indexGrandchild: 0,
|
||||||
|
title: 'Compare Answers',
|
||||||
|
svgPath: mdiForum,
|
||||||
|
indexBase: -1,
|
||||||
|
indexChild: 4
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':id',
|
||||||
|
name: 'CompareQuestion',
|
||||||
|
component: CompareQuestion,
|
||||||
|
props: route => ({
|
||||||
|
id: parseInt(route.params.id)
|
||||||
|
}),
|
||||||
|
meta: {
|
||||||
|
indexGrandchild: 1,
|
||||||
|
title: 'Compare Answers',
|
||||||
|
svgPath: mdiForum,
|
||||||
|
indexBase: -1,
|
||||||
|
indexChild: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -190,17 +233,17 @@ const routes = [
|
|||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
component: NotFound,
|
component: NotFound,
|
||||||
meta: {
|
meta: {
|
||||||
index: -1,
|
indexBase: -2,
|
||||||
title: 'Error: Not Found',
|
title: 'Error: Not Found',
|
||||||
svgPath: mdiWeb
|
svgPath: mdiWeb
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:catchAll(.*)",
|
path: "/:catchAll(.*)",
|
||||||
name: 'NotFound',
|
name: 'CatchAll',
|
||||||
redirect: '/err_notfound',
|
redirect: '/err_notfound',
|
||||||
meta: {
|
meta: {
|
||||||
index: -1,
|
indexBase: -3,
|
||||||
title: 'Error: Not Found',
|
title: 'Error: Not Found',
|
||||||
svgPath: mdiWeb
|
svgPath: mdiWeb
|
||||||
}
|
}
|
||||||
@ -210,7 +253,7 @@ const routes = [
|
|||||||
name: 'Refused',
|
name: 'Refused',
|
||||||
component: Refused,
|
component: Refused,
|
||||||
meta: {
|
meta: {
|
||||||
index: -1,
|
indexBase: -4,
|
||||||
title: 'Error: Connection Refused',
|
title: 'Error: Connection Refused',
|
||||||
svgPath: mdiWeb
|
svgPath: mdiWeb
|
||||||
}
|
}
|
||||||
@ -222,31 +265,36 @@ const Router = createRouter({
|
|||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
Router.beforeEach((to, from, next) => {
|
Router.beforeEach((to, from) => {
|
||||||
if (to.meta.title != 'Home') {
|
if (to.meta.title != 'Home') {
|
||||||
document.title = `Wanderhome Quiz | V.S. - ${to.meta.title}`
|
document.title = `Wanderhome Quiz | V.S. - ${to.meta.title}`
|
||||||
} else {
|
} else {
|
||||||
document.title = `Wanderhome Quiz | V.S.`
|
document.title = `Wanderhome Quiz | V.S.`
|
||||||
}
|
}
|
||||||
next()
|
if (from.meta.indexBase == -1 && to.meta.indexBase != -1) {
|
||||||
|
if (!confirm('If you navigate away from the Results section, then you will lose your results and need to start the quiz again. Are you sure?')) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
to.meta.resetApp = true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Router.afterEach( (to, from) => {
|
Router.afterEach( (to, from) => {
|
||||||
const enterActiveClass = 'transition-all duration-300 origin-top ease-in'
|
const enterActiveClass = 'transition-all duration-300 origin-top ease-in'
|
||||||
const leaveActiveClass = 'transition-all duration-300 origin-top ease-out'
|
const leaveActiveClass = 'transition-all duration-300 origin-top ease-out'
|
||||||
const baseFromClass = 'transform opacity-0 md:scale-75'
|
const baseFromClass = 'transform opacity-0 md:scale-75'
|
||||||
if ( to.fullPath.split('/')[1] !== from.fullPath.split('/')[1] || !from.matched.length ) {
|
if ( from.meta.indexBase !== to.meta.indexBase ) {
|
||||||
const fromIndex = from.meta.parentIndex ? from.meta.parentIndex : from.meta.index
|
const fromIndex = from.meta.indexBase
|
||||||
const toIndex = to.meta.parentIndex ? to.meta.parentIndex : to.meta.index
|
const toIndex = to.meta.indexBase
|
||||||
const slideInDirection = toIndex < fromIndex ? 'md:-translate-x-1/3' : 'md:translate-x-1/3'
|
const slideInDirection = toIndex < fromIndex ? 'md:-translate-x-1/3' : 'md:translate-x-1/3'
|
||||||
const slideOutDirection = toIndex < fromIndex ? 'md:translate-x-1/3' : 'md:-translate-x-1/3'
|
const slideOutDirection = toIndex < fromIndex ? 'md:translate-x-1/3' : 'md:-translate-x-1/3'
|
||||||
to.meta.mainEnterActiveClass = enterActiveClass
|
to.meta.mainEnterActiveClass = enterActiveClass
|
||||||
to.meta.mainLeaveActiveClass = leaveActiveClass
|
to.meta.mainLeaveActiveClass = leaveActiveClass
|
||||||
to.meta.mainEnterFromClass = baseFromClass + ' ' + slideInDirection
|
to.meta.mainEnterFromClass = baseFromClass + ' ' + slideInDirection
|
||||||
to.meta.mainLeaveToClass = baseFromClass + ' ' + slideOutDirection
|
to.meta.mainLeaveToClass = baseFromClass + ' ' + slideOutDirection
|
||||||
} else if ( to.fullPath.split('/')[1] == from.fullPath.split('/')[1] && from.matched.length ) {
|
} else if ( from.meta.indexChild !== to.meta.indexChild ) {
|
||||||
const fromIndex = from.meta.index
|
const fromIndex = from.meta.indexChild
|
||||||
const toIndex = to.meta.index
|
const toIndex = to.meta.indexChild
|
||||||
const slideInDirection = toIndex < fromIndex ? 'md:-translate-y-1/3' : 'md:translate-y-1/3'
|
const slideInDirection = toIndex < fromIndex ? 'md:-translate-y-1/3' : 'md:translate-y-1/3'
|
||||||
const slideOutDirection = toIndex < fromIndex ? 'md:translate-y-1/3' : 'md:-translate-y-1/3'
|
const slideOutDirection = toIndex < fromIndex ? 'md:translate-y-1/3' : 'md:-translate-y-1/3'
|
||||||
to.meta.panelEnterActiveClass = enterActiveClass
|
to.meta.panelEnterActiveClass = enterActiveClass
|
||||||
|
@ -4,6 +4,7 @@ export const useAnswersStore = defineStore({
|
|||||||
id: 'answers',
|
id: 'answers',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
answers: [],
|
answers: [],
|
||||||
|
quizCurrent: null
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
isAnswered(index) {
|
isAnswered(index) {
|
||||||
|
@ -3,18 +3,14 @@ import { defineStore } from 'pinia'
|
|||||||
export const useAppStore = defineStore({
|
export const useAppStore = defineStore({
|
||||||
id: 'app',
|
id: 'app',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
hasData: false,
|
|
||||||
answers: [],
|
answers: [],
|
||||||
playbooks: {},
|
playbooks: {},
|
||||||
results: {},
|
results: {},
|
||||||
scores: {},
|
scores: {},
|
||||||
count: null
|
count: null,
|
||||||
|
compareCurrent: null
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
toggleData() {
|
|
||||||
this.hasData = !this.hasData
|
|
||||||
console.log('Toggled Has Data. New value', this.hasData)
|
|
||||||
},
|
|
||||||
store(key, data) {
|
store(key, data) {
|
||||||
this[key] = JSON.parse(JSON.stringify(data))
|
this[key] = JSON.parse(JSON.stringify(data))
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,7 @@ import { defineStore } from 'pinia'
|
|||||||
export const useQuestionStore = defineStore({
|
export const useQuestionStore = defineStore({
|
||||||
id: 'questions',
|
id: 'questions',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
questions: [],
|
questions: []
|
||||||
currentQuestion: 0
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
storeQuestions(questionArray) {
|
storeQuestions(questionArray) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
import Content from '@/components/Content.vue'
|
import Content from '@/components/Content.vue'
|
||||||
import Header from '@/components/Header.vue'
|
import Header from '@/components/Header.vue'
|
||||||
import TextFrame from '@/components/TextFrame.vue'
|
import TextFrame from '@/components/TextFrame.vue'
|
||||||
@ -10,7 +11,17 @@
|
|||||||
Content,
|
Content,
|
||||||
Header,
|
Header,
|
||||||
TextFrame
|
TextFrame
|
||||||
}
|
},
|
||||||
|
setup() {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.appStore.$reset()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
@ -41,11 +52,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm">
|
|
||||||
This quiz is not affiliated with, endorsed by, or in any way connected to Possum Creek Games.
|
|
||||||
It is a fan project and a programming exercise by someone who loves Jay’s game.
|
|
||||||
I would nevertheless implore you to play <em>Wanderhome</em> if you haven’t already.
|
|
||||||
</p>
|
|
||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
|
@ -18,11 +18,12 @@
|
|||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>
|
||||||
<article class="prose mx-auto">
|
<article class="prose mx-auto">
|
||||||
|
<section>
|
||||||
<h2>What Exactly Is This?</h2>
|
<h2>What Exactly Is This?</h2>
|
||||||
<p>
|
<p>
|
||||||
This web app is a personality quiz to see what <em class="uncial-antiqua">Wanderhome</em> playbook you are.
|
This web app is a personality quiz to see what <em class="uncial-antiqua">Wanderhome</em> playbook you are.
|
||||||
I have previously made a smilar <a href="https://masks.vsnt.uk/" target="_blank" rel="noopener noreferrer">character quiz for Brendan Conway’s <em>Masks: a New Generation</em></a>.
|
I have previously made a smilar <a href="https://masks.vsnt.uk/" target="_blank" rel="noopener noreferrer" class="hover:bg-orange-200">character quiz for Brendan Conway’s <em>Masks: a New Generation</em></a>.
|
||||||
I have also made a digital version of the <a href="https://reftest.vsnt.uk/" target="_blank" rel="noopener noreferrer">Scottish Korfball refereeing exam</a>.
|
I have also made a digital version of the <a href="https://reftest.vsnt.uk/" target="_blank" rel="noopener noreferrer" class="hover:bg-orange-200">Scottish Korfball refereeing exam</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This was a fun programming exercise I set myself.
|
This was a fun programming exercise I set myself.
|
||||||
@ -30,10 +31,12 @@
|
|||||||
And I would love to make this quiz if it gives me a reason to talk to people I know about my favourite TTRPGs.
|
And I would love to make this quiz if it gives me a reason to talk to people I know about my favourite TTRPGs.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If you want to read more about <em class="uncial-antiqua">Wanderhome</em>, you can do so in the <router-link to="/about/wanderhome">relevant page in this app</router-link>.
|
If you want to read more about <em class="uncial-antiqua">Wanderhome</em>, you can do so in the <router-link to="/about/wanderhome" class="hover:bg-orange-200">relevant section</router-link>.
|
||||||
I wholeheartedly recommend playing it!
|
I wholeheartedly recommend playing it!
|
||||||
</p>
|
</p>
|
||||||
|
</section>
|
||||||
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
||||||
|
<section>
|
||||||
<h2>
|
<h2>
|
||||||
Technobabble
|
Technobabble
|
||||||
</h2>
|
</h2>
|
||||||
@ -77,19 +80,22 @@
|
|||||||
On the whole, despite how much of a hassle it was, I preferred the outcome of using Vue and Tailwind because the result looks a lot less samey to my Flask/Bootstrap projects.
|
On the whole, despite how much of a hassle it was, I preferred the outcome of using Vue and Tailwind because the result looks a lot less samey to my Flask/Bootstrap projects.
|
||||||
The result here is one that has much more polish.
|
The result here is one that has much more polish.
|
||||||
</p>
|
</p>
|
||||||
|
</section>
|
||||||
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
||||||
<h3>
|
<section>
|
||||||
|
<h2>
|
||||||
What Next?
|
What Next?
|
||||||
</h3>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
I am running out of geeky TTRPG-related programming projects.
|
I am running out of geeky TTRPG-related programming projects.
|
||||||
I was thinking of making a web app to play a game of <a href="https://www.lamemage.com/microscope/" target="_blank" rel="noopener noreferrer"><em>Microscope</em> by Ben Robbins</a>, published by Lame Mage Productions.
|
I was thinking of making a web app to play a game of <a href="https://www.lamemage.com/microscope/" target="_blank" rel="noopener noreferrer" class="hover:bg-orange-200"><em>Microscope</em> by Ben Robbins</a>, published by Lame Mage Productions.
|
||||||
There is an app that exists, but every time I tried using it I struggled to get it to work properly.
|
There is an app that exists, but every time I tried using it I struggled to get it to work properly.
|
||||||
The developer has not responded to my issues on GitHub, so I am tempted to reverse engineer it and make one from the ground up.
|
The developer has not responded to my issues on GitHub, so I am tempted to reverse engineer it and make one from the ground up.
|
||||||
The original app was written in programming languages that I have no clue about, so I would rather just build it from sratch in Python and, unfortunately, Vue.
|
The original app was written in programming languages that I have no clue about, so I would rather just build it from sratch in Python and, unfortunately, Vue.
|
||||||
That might be the next project I tinker with.
|
That might be the next project I tinker with.
|
||||||
It will apply all the things I currently know, and also add websockets and state synchronisation to the mix.
|
It will apply all the things I currently know, and also add websockets and state synchronisation to the mix.
|
||||||
</p>
|
</p>
|
||||||
|
</section>
|
||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
|
@ -12,27 +12,40 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
Acknowledgements
|
Acknowledgements
|
||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>
|
||||||
<article class="prose mx-auto">
|
<article class="prose mx-auto">
|
||||||
|
<section>
|
||||||
|
<p class="text-leader mx-12">
|
||||||
|
This one is for all my friends and ‘incidental companions’ alike whose paths criss-crossed with mine;
|
||||||
|
</p>
|
||||||
|
<p class="text-leader mx-12">
|
||||||
|
And all the wonderful people from my home town whom I ironically met only after leaving;
|
||||||
|
</p>
|
||||||
|
<p class="text-leader mx-12">
|
||||||
|
Especially you, 8Bit.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
<p>
|
<p>
|
||||||
First and foremost, I am delighted that Jay Dragon and Possum Creek Games created such a magnificent work of art.
|
First and foremost, I am delighted that Jay Dragon and Possum Creek Games created such a magnificent work of art.
|
||||||
|
I am also grateful for Jay’s enthusiasm about this project.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
I would also like to thank 8bit for his inspiring enthusiasm: I would have arrived at this game a whole lot later if it weren’ for his shilling for it.
|
I would also like to thank 8bit for his inspiring enthusiasm: I would have arrived at this game a whole lot later if it weren’t for his relentless shilling for it.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
And I am deeply grateful to my friends along the way: Claire Bath for being the first playtester of the quiz.
|
And I am deeply grateful to my friends along the way: Claire Bath for being the first playtester of the quiz, and for impeccable design advice.
|
||||||
|
There will be no doubt others to go to this list for helping me test this app.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This section is still a work in progress because the programme is still not yet finished.
|
And not to mention, the innumerable developers with their tutorials and guides that helped me learn a new programming framework to make this.
|
||||||
</p>
|
</p>
|
||||||
|
</section>
|
||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
67
client/src/views/about/Licenses.vue
Normal file
67
client/src/views/about/Licenses.vue
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<script>
|
||||||
|
import Content from '@/components/Content.vue'
|
||||||
|
import Header from '@/components/Header.vue'
|
||||||
|
import TextFrame from '@/components/TextFrame.vue'
|
||||||
|
export default {
|
||||||
|
name: 'Licenses',
|
||||||
|
components: {
|
||||||
|
Content,
|
||||||
|
Header,
|
||||||
|
TextFrame
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<TextFrame>
|
||||||
|
<Header>
|
||||||
|
Licenses
|
||||||
|
</Header>
|
||||||
|
<Content>
|
||||||
|
<article class="prose mx-auto">
|
||||||
|
<section>
|
||||||
|
<a href="https://possumcreekgames.com/en-gb/pages/wanderhome-3rd-party-license" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="@/assets/img/wh_ic_banner.png" alt="Wanderhome Independent Content banner" class="drop-shadow-lg scale-75 my-0 inline-block">
|
||||||
|
</a>
|
||||||
|
<h2>
|
||||||
|
<em class="uncial-antiqua">Wanderhome</em> Text and Artwork
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
<em class="uncial-antiqua">Wanderhome</em> is copyright of Possum Creek Games Inc.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <em><span class="uncial-antiqua">Wanderhome</span> Quiz | V.S.</em> is an independent production by Vivek Santayana and is not affiliated with Possum Creek Games Inc.
|
||||||
|
It is published under the <a href="https://possumcreekgames.com/en-gb/pages/wanderhome-3rd-party-license" target="_blank" class="hover:bg-orange-200" rel="noopener noreferrer">Wanderhome Third Party License</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The excerpts from <em class="uncial-antiqua">Wanderhome</em>, including the names of the playbook, flavour text, playbook descriptions, natures, animal forms, and character action options, as well as the setting of Hæth, are copyright of Possum Creek Games Inc.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Artwork from <em class="uncial-antiqua">Wanderhome</em>, including game art and illustrations of playbooks, are also copyright Possum Creek Games Inc.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
||||||
|
<section>
|
||||||
|
<h2>
|
||||||
|
Question Text
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
The questions used in this quiz were written by Vivek Santayana, and are licensed under a <a rel="license noopener noreferrer" target="_blank" class="hover:bg-orange-200" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
|
||||||
|
</p>
|
||||||
|
<div class="flex">
|
||||||
|
<a class="mx-auto w-fit" target="_blank" rel="license noopener noreferrer" href="http://creativecommons.org/licenses/by-sa/4.0/"><img src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" alt="Creative Commons Licence BY SA" class="m-0 inline-block"></a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
||||||
|
<section>
|
||||||
|
<h2>
|
||||||
|
Source Code
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
This quiz is an opensource project.
|
||||||
|
The source code for this project, including <a rel="noopener noreferrer" target="_blank" class="hover:bg-orange-200" href="https://git.vsnt.uk/viveksantayana/wanderhome-quiz">the quiz server and API</a> and the <a rel="noopener noreferrer" target="_blank" class="hover:bg-orange-200" href="https://git.vsnt.uk/viveksantayana/wanderhome-quiz-client">the client app</a>, are available under an MIT License at the respective GIT repositories.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</Content>
|
||||||
|
</TextFrame>
|
||||||
|
</template>
|
@ -12,13 +12,13 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
About <em>Wanderhome</em>
|
About <em>Wanderhome</em>
|
||||||
</Header>
|
</Header>
|
||||||
<Content>
|
<Content>
|
||||||
<article class="prose mx-auto">
|
<article class="prose mx-auto">
|
||||||
|
<section>
|
||||||
<p>
|
<p>
|
||||||
<em class="uncial-antiqua">Wanderhome</em> is a pastoral fantasy table-top role-playing game by Jay Dragon, published by Possum Creek Games.
|
<em class="uncial-antiqua">Wanderhome</em> is a pastoral fantasy table-top role-playing game by Jay Dragon, published by Possum Creek Games.
|
||||||
Players play anthropomorphic animals who are travelling through a vast landscape, dotted with different features and locales.
|
Players play anthropomorphic animals who are travelling through a vast landscape, dotted with different features and locales.
|
||||||
@ -32,19 +32,21 @@
|
|||||||
In the midst of this, the game does not have any combat: it is explicitly about healing and building a fragile peace.
|
In the midst of this, the game does not have any combat: it is explicitly about healing and building a fragile peace.
|
||||||
And it is hopeful.
|
And it is hopeful.
|
||||||
</p>
|
</p>
|
||||||
|
</section>
|
||||||
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
<hr class="border-gray-400 w-2/3 mx-auto"/>
|
||||||
|
<section>
|
||||||
<h2>
|
<h2>
|
||||||
Where to Find a Copy
|
Where to Find a Copy
|
||||||
</h2>
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
You can buy the game from <a href="https://possumcreekgames.com/en-gb/products/wanderhome" target="_blank" rel="noopener noreferrer">Possum Creek Games’ web site</a>.
|
You can buy the game from <a href="https://possumcreekgames.com/en-gb/products/wanderhome" target="_blank" rel="noopener noreferrer" class="hover:bg-orange-200">Possum Creek Games’ web site</a>.
|
||||||
Physical books have sold out at the time of writing, but you can always <a href="https://possumcreekgames.com/en-gb/products/wanderhome-pdf" target="_blank" rel="noopener noreferrer">buy a pdf</a>.
|
Physical books have been re-stocked in a new print run at the time of writing, and you can also <a href="https://possumcreekgames.com/en-gb/products/wanderhome-pdf" target="_blank" rel="noopener noreferrer" class="hover:bg-orange-200">buy a pdf</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If you are one of my friends and would like to play <em class="uncial-antiqua">Wanderhome</em>, let me know!
|
If you are one of my friends and would like to play <em class="uncial-antiqua">Wanderhome</em>, let me know!
|
||||||
</p>
|
</p>
|
||||||
|
</section>
|
||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
@ -12,7 +12,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div >
|
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
Error: Not Found
|
Error: Not Found
|
||||||
@ -32,7 +31,6 @@
|
|||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
</style>
|
</style>
|
@ -12,7 +12,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div >
|
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
Error: Connection Refused
|
Error: Connection Refused
|
||||||
@ -28,7 +27,6 @@
|
|||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
</style>
|
</style>
|
@ -19,28 +19,27 @@
|
|||||||
},
|
},
|
||||||
name: 'QuestionIndex',
|
name: 'QuestionIndex',
|
||||||
created() {
|
created() {
|
||||||
if (!this.appStore.hasData) {
|
if (this.questionStore.questions.length == 0) {
|
||||||
this.getQuestions()
|
this.getQuestions()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
mounted() {
|
||||||
return {
|
if (this.answersStore.quizCurrent !== null) {
|
||||||
error: null,
|
this.$router.push(`/quiz/question/${this.answersStore.quizCurrent}`)
|
||||||
loading: false,
|
} else {
|
||||||
questions: null
|
this.answersStore.$reset()
|
||||||
|
this.appStore.$reset()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getQuestions() {
|
getQuestions() {
|
||||||
this.error = this.questions = null
|
|
||||||
this.loading = true
|
|
||||||
axios.get(`${Config.SERVER}api/questions/`)
|
axios.get(`${Config.SERVER}api/questions/`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.error = false
|
console.log('Fetched questions from server.')
|
||||||
this.questionStore.storeQuestions(response.data)
|
this.questionStore.storeQuestions(response.data)
|
||||||
this.appStore.toggleData()
|
|
||||||
})
|
})
|
||||||
.catch( error => {
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
this.$router.push('/err_refused')
|
this.$router.push('/err_refused')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -35,52 +35,28 @@
|
|||||||
this.answersStore.makeArray(this.id, this.questionStore.questions[this.id].select)
|
this.answersStore.makeArray(this.id, this.questionStore.questions[this.id].select)
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.answersStore.quizCurrent = this.id
|
||||||
this.$watch(
|
this.$watch(
|
||||||
() => this.$route.params, (toParams, previousParams) => {
|
() => this.$route.params, (toParams, previousParams) => {
|
||||||
if (this.$route.name == 'Question') {
|
if (this.$route.name == 'Question') {
|
||||||
if (toParams.id >= this.questionStore.questions.length || this.id < 0) {
|
if (toParams.id >= this.questionStore.questions.length || this.id < 0) {
|
||||||
this.$router.push('/err_notfound')
|
this.$router.push('/err_notfound')
|
||||||
} else {
|
} else {
|
||||||
if ( toParams.id == 0 ) {
|
this.answersStore.quizCurrent = toParams.id
|
||||||
this.enableBack = false
|
|
||||||
}
|
|
||||||
if ( toParams.id == this.questionStore.questions.length - 1 ) {
|
|
||||||
console.log('Condition met')
|
|
||||||
this.enableNext = false
|
|
||||||
} else {
|
|
||||||
this.enableNext = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
this.$watch(
|
this.$watch(
|
||||||
() => this.appStore.hasData, (newValue) => {
|
() => this.questionStore.questions, (newValue) => {
|
||||||
if (this.id >= this.questionStore.questions.length || this.id < 0) {
|
if (this.id >= this.questionStore.questions.length || this.id < 0) {
|
||||||
this.$router.push('/err_notfound')
|
this.$router.push('/err_notfound')
|
||||||
} else {
|
} else {
|
||||||
this.answersStore.makeArray(this.id, this.questionStore.questions[this.id].select)
|
this.answersStore.makeArray(this.id, this.questionStore.questions[this.id].select)
|
||||||
if ( this.id == this.questionStore.questions.length -1 ) {
|
|
||||||
this.enableNext = false
|
|
||||||
} else {
|
|
||||||
this.enableNext = true
|
|
||||||
}
|
|
||||||
if ( this.id == 0 ) {
|
|
||||||
this.enableBack = false
|
|
||||||
} else {
|
|
||||||
this.enableBack = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
question: null,
|
|
||||||
select: null,
|
|
||||||
answers: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
submitAnswers() {
|
submitAnswers() {
|
||||||
const data = JSON.stringify(this.answersStore.answers)
|
const data = JSON.stringify(this.answersStore.answers)
|
||||||
@ -93,10 +69,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
).then( (response) => {
|
).then( (response) => {
|
||||||
|
console.log('Submitted results.')
|
||||||
this.appStore.store('results', response.data)
|
this.appStore.store('results', response.data)
|
||||||
console.log('Results fetched from the server.')
|
console.log('Results fetched from the server.')
|
||||||
|
this.answersStore.quizCurrent = null
|
||||||
this.$router.push('/results')
|
this.$router.push('/results')
|
||||||
}).catch( (error) => {
|
}).catch( (error) => {
|
||||||
|
console.log(error)
|
||||||
this.$router.push('/err_refused')
|
this.$router.push('/err_refused')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -106,8 +85,7 @@
|
|||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -119,7 +97,8 @@
|
|||||||
<Content>
|
<Content>
|
||||||
<div v-if="questionStore.questions[this.id]">
|
<div v-if="questionStore.questions[this.id]">
|
||||||
<article class="prose">
|
<article class="prose">
|
||||||
<div v-html="questionStore.questions[this.id].question"></div>
|
<h3>Question {{ this.id + 1}}</h3>
|
||||||
|
<div v-html="questionStore.questions[this.id].question"/>
|
||||||
</article>
|
</article>
|
||||||
<div class="grid grid-cols-1 content-evenly items-center gap-2 justify-center my-12 mx-auto md:grid-cols-2 lg:grid-cols-3" :aria-multiselectable="questionStore.questions[this.id].select > 1 ? true: false">
|
<div class="grid grid-cols-1 content-evenly items-center gap-2 justify-center my-12 mx-auto md:grid-cols-2 lg:grid-cols-3" :aria-multiselectable="questionStore.questions[this.id].select > 1 ? true: false">
|
||||||
<div v-for="(answer, index) in questionStore.questions[this.id].answers" :key="`q${this.id}-o${index}`" class="inline-flex">
|
<div v-for="(answer, index) in questionStore.questions[this.id].answers" :key="`q${this.id}-o${index}`" class="inline-flex">
|
||||||
@ -188,7 +167,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.checkbox {
|
.checkbox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<TextFrame>
|
<TextFrame>
|
||||||
<Header>
|
<Header>
|
||||||
Take the Quiz
|
Take the Quiz
|
||||||
@ -55,7 +54,6 @@
|
|||||||
</article>
|
</article>
|
||||||
</Content>
|
</Content>
|
||||||
</TextFrame>
|
</TextFrame>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
</style>
|
</style>
|
@ -1,23 +0,0 @@
|
|||||||
<script>
|
|
||||||
import Content from '@/components/Content.vue'
|
|
||||||
import Header from '@/components/Header.vue'
|
|
||||||
import TextFrame from '@/components/TextFrame.vue'
|
|
||||||
export default {
|
|
||||||
name: 'Answers',
|
|
||||||
components: {
|
|
||||||
Content,
|
|
||||||
Header,
|
|
||||||
TextFrame
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<TextFrame>
|
|
||||||
<Header>
|
|
||||||
Compare Answers
|
|
||||||
</Header>
|
|
||||||
<Content>
|
|
||||||
|
|
||||||
</Content>
|
|
||||||
</TextFrame>
|
|
||||||
</template>
|
|
@ -29,18 +29,20 @@
|
|||||||
getResults() {
|
getResults() {
|
||||||
axios.get(`${Config.SERVER}api/playbooks/`)
|
axios.get(`${Config.SERVER}api/playbooks/`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.error = false
|
console.log('Fetched playbook stats from the server.')
|
||||||
this.appStore.store('playbooks', response.data)
|
this.appStore.store('playbooks', response.data)
|
||||||
})
|
})
|
||||||
.catch( error => {
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
this.$router.push('/err_refused')
|
this.$router.push('/err_refused')
|
||||||
})
|
})
|
||||||
axios.get(`${Config.SERVER}api/count/`)
|
axios.get(`${Config.SERVER}api/count/`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.error = false
|
console.log('Fetched user count from the server.')
|
||||||
this.appStore.store('count', response.data)
|
this.appStore.store('count', response.data)
|
||||||
})
|
})
|
||||||
.catch( error => {
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
this.$router.push('/err_refused')
|
this.$router.push('/err_refused')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -92,7 +94,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4" class="text-center text-lg">Out of a total {{ this.appStore.count }} users</td>
|
<td colspan="4" class="text-center text-lg text-gray-600">Out of {{ this.appStore.count }} users</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,9 +1,25 @@
|
|||||||
<script>
|
<script>
|
||||||
import Sidebar from '@/components/sidebar/Index.vue'
|
import Sidebar from '@/components/sidebar/Index.vue'
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
setup() {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
name: 'ResultsIndex',
|
name: 'ResultsIndex',
|
||||||
components: {
|
components: {
|
||||||
Sidebar
|
Sidebar
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.appStore.results.playbooks.length > 1) {
|
||||||
|
this.$router.options.routes[3].children[0].meta.title = 'Your Results'
|
||||||
|
} else {
|
||||||
|
this.$router.options.routes[3].children[0].meta.title = 'Your Result'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -53,13 +53,10 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="text-sm">Pages {{ Object.values(playbook)[0].pages }}</span>
|
<span class="text-sm">Pages {{ Object.values(playbook)[0].pages }}</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-leader" v-html="Object.values(playbook)[0].flavour">
|
<p class="text-leader" v-html="Object.values(playbook)[0].flavour"/>
|
||||||
</p>
|
<p v-html="Object.values(playbook)[0].blurb"/>
|
||||||
<p>
|
<p>
|
||||||
{{ Object.values(playbook)[0].blurb }}
|
You are alive. Your care is <strong v-html="Object.values(playbook)[0].care"></strong>.
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You are alive. Your care is <strong>{{ Object.values(playbook)[0].care }}</strong>.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Your animal form is {{ renderAnimals(Object.values(playbook)[0].animals) }}
|
Your animal form is {{ renderAnimals(Object.values(playbook)[0].animals) }}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
Playbook
|
Playbook
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Score
|
Score (%)
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -46,7 +46,7 @@
|
|||||||
The {{ playbook }}
|
The {{ playbook }}
|
||||||
</td>
|
</td>
|
||||||
<td scope="col" class="py-1">
|
<td scope="col" class="py-1">
|
||||||
{{ Math.round(100*score/this.appStore.results.max_score) }} %
|
{{ Math.round(100*score/this.appStore.results.max_score) }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -29,18 +29,20 @@
|
|||||||
getScores() {
|
getScores() {
|
||||||
axios.get(`${Config.SERVER}api/scores/`)
|
axios.get(`${Config.SERVER}api/scores/`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.error = false
|
console.log('Fetched score stats from the server.')
|
||||||
this.appStore.store('scores', response.data)
|
this.appStore.store('scores', response.data)
|
||||||
})
|
})
|
||||||
.catch( error => {
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
this.$router.push('/err_refused')
|
this.$router.push('/err_refused')
|
||||||
})
|
})
|
||||||
axios.get(`${Config.SERVER}api/count/`)
|
axios.get(`${Config.SERVER}api/count/`)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.error = false
|
console.log('Fetched user count from the server.')
|
||||||
this.appStore.store('count', response.data)
|
this.appStore.store('count', response.data)
|
||||||
})
|
})
|
||||||
.catch( error => {
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
this.$router.push('/err_refused')
|
this.$router.push('/err_refused')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -57,7 +59,7 @@
|
|||||||
Sometimes, it can help to have some additional insight into the likelihood of meeting different people.
|
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.
|
Or, indeed, it can provide insight into how the questions we ask of each other bias the way we perceive the world.
|
||||||
</p>
|
</p>
|
||||||
<table class="table-auto w-full max-w-lg mx-auto text-left">
|
<table class="table-auto w-full mx-auto max-w-lg text-left">
|
||||||
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
|
<thead class="text-xs text-gray-700 uppercase bg-lime-100 dark:bg-gray-700 dark:text-gray-400">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
@ -67,16 +69,16 @@
|
|||||||
Playbook
|
Playbook
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Your Score
|
Your Score (%)
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Mean Score
|
Mean
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Median Score
|
Median
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th class="lowercase underline" title="Standard Deviation">
|
||||||
Standard Deviation
|
σ*
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -105,7 +107,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4" class="text-center text-lg">Out of a total {{ this.appStore.count }} users</td>
|
<td colspan="6" class="text-center text-lg text-gray-600">From {{ this.appStore.count }} users</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
125
client/src/views/results/compare-answers/CompareQuestion.vue
Normal file
125
client/src/views/results/compare-answers/CompareQuestion.vue
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<script>
|
||||||
|
import { useQuestionStore } from '@/stores/questions.js'
|
||||||
|
import { useAnswersStore } from '@/stores/answers.js'
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
|
import Content from '@/components/Content.vue'
|
||||||
|
import Header from '@/components/Header.vue'
|
||||||
|
import TextFrame from '@/components/TextFrame.vue'
|
||||||
|
import ArrowLeftBold from '@/components/icons/ArrowLeftBold.vue'
|
||||||
|
import ArrowRightBold from '@/components/icons/ArrowRightBold.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CompareQuestion',
|
||||||
|
components: {
|
||||||
|
ArrowLeftBold,
|
||||||
|
ArrowRightBold,
|
||||||
|
Content,
|
||||||
|
Header,
|
||||||
|
TextFrame
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
const answersStore = useAnswersStore()
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
questionStore,
|
||||||
|
answersStore,
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
optionSelected(id, index) {
|
||||||
|
if (Array.isArray(this.answersStore.answers[id])) {
|
||||||
|
return this.answersStore.answers[id].includes(index)
|
||||||
|
}
|
||||||
|
return this.answersStore.answers[id] == index
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.appStore.compareCurrent = this.id
|
||||||
|
this.$watch(
|
||||||
|
() => this.$route.params, (toParams, previousParams) => {
|
||||||
|
if (this.$route.name == 'CompareQuestion') {
|
||||||
|
if (toParams.id >= this.questionStore.questions.length || this.id < 0) {
|
||||||
|
this.$router.push('/err_notfound')
|
||||||
|
} else {
|
||||||
|
this.appStore.compareCurrent = toParams.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<TextFrame>
|
||||||
|
<Header>
|
||||||
|
Compare Answers
|
||||||
|
</Header>
|
||||||
|
<Content>
|
||||||
|
<div v-if="questionStore.questions[this.id] && answersStore.answers[this.id] != null && appStore.answers[this.id]">
|
||||||
|
<article class="prose">
|
||||||
|
<h3>Question {{ this.id + 1}}</h3>
|
||||||
|
<div v-html="questionStore.questions[this.id].question"></div>
|
||||||
|
</article>
|
||||||
|
<div class="grid grid-cols-1 content-evenly items-center gap-2 justify-between mt-12 mx-auto lg:grid-cols-2">
|
||||||
|
<div v-for="(answer, index) in questionStore.questions[this.id].answers" :key="`q${this.id}-o${index}`" class="inline-flex justify-between rounded-md bg-lime-200" :style="`background: linear-gradient(to right, rgb(217 249 157) ${100*this.appStore.answers[this.id][index] / this.appStore.count}%, transparent ${100*this.appStore.answers[this.id][index] / this.appStore.count+3}%)`">
|
||||||
|
<div v-html="answer" class="flex uncial-antiqua h-full p-2 select-none transition-all duration-100 ease-in-out" :class=" optionSelected(this.id, index) ? 'option-selected' : '' " :aria-label="answer" :title="answer"></div>
|
||||||
|
<div class="flex p-2 w-fit items-center" style="white-space:nowrap;">{{ Math.round(100*this.appStore.answers[this.id][index] / this.appStore.count) }} %</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center mt-6 mb-12 text-lg text-gray-600">
|
||||||
|
From of {{ this.appStore.count }} users.
|
||||||
|
</div>
|
||||||
|
<div class="w-full flex mx-auto items-center justify-between max-w-sm">
|
||||||
|
<router-link :to="`/results/answers/${this.id-1}`" v-if="this.id > 0">
|
||||||
|
<div class="inline-flex h-full px-3 py-1 space-x-1 rounded-md bg-lime-800 text-white items-center transition-all duration-300 ease-in-out hover:bg-lime-600" title="Back">
|
||||||
|
<span class="scale-100">
|
||||||
|
<ArrowLeftBold/>
|
||||||
|
</span>
|
||||||
|
<span class="uncial-antiqua">Back</span>
|
||||||
|
</div>
|
||||||
|
</router-link>
|
||||||
|
<div class="inline-flex h-full px-3 py-1 space-x-1 rounded-md bg-lime-800 opacity-50 text-white items-center hover:cursor-not-allowed" v-else>
|
||||||
|
<span class="scale-100">
|
||||||
|
<ArrowLeftBold/>
|
||||||
|
</span>
|
||||||
|
<span class="uncial-antiqua">Back</span>
|
||||||
|
</div>
|
||||||
|
<router-link :to="`/results/answers/${this.id+1}`" v-if="this.id < this.questionStore.questions.length - 1">
|
||||||
|
<div class="inline-flex h-full px-3 py-1 space-x-1 rounded-md bg-lime-800 text-white items-center transition-all duration-300 ease-in-out hover:bg-lime-600" title="Next">
|
||||||
|
<span class="uncial-antiqua">Next</span>
|
||||||
|
<span class="scale-100">
|
||||||
|
<ArrowRightBold/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</router-link>
|
||||||
|
<div class="inline-flex h-full px-3 py-1 space-x-1 rounded-md bg-lime-800 opacity-50 text-white items-center hover:cursor-not-allowed" v-else>
|
||||||
|
<span class="uncial-antiqua">Next</span>
|
||||||
|
<span class="scale-100">
|
||||||
|
<ArrowRightBold/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Content>
|
||||||
|
</TextFrame>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.option-selected {
|
||||||
|
@apply border-lime-600;
|
||||||
|
@apply border-solid;
|
||||||
|
@apply border-l-2;
|
||||||
|
@apply text-orange-600;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,54 @@
|
|||||||
|
<script>
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
|
import Content from '@/components/Content.vue'
|
||||||
|
import Header from '@/components/Header.vue'
|
||||||
|
import TextFrame from '@/components/TextFrame.vue'
|
||||||
|
import FeatureSearch from '@/components/icons/FeatureSearch.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CompareQuestions',
|
||||||
|
components: {
|
||||||
|
Content,
|
||||||
|
FeatureSearch,
|
||||||
|
Header,
|
||||||
|
TextFrame
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.appStore.compareCurrent !== null) {
|
||||||
|
this.$router.push(`/results/answers/${this.appStore.compareCurrent}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<TextFrame>
|
||||||
|
<Header>
|
||||||
|
Compare Answers
|
||||||
|
</Header>
|
||||||
|
<Content>
|
||||||
|
<article class="prose mx-auto">
|
||||||
|
<p class="text-leader">
|
||||||
|
There are many turning points and forks in the road we will encounter along the way.
|
||||||
|
There is a little illustration of how your choices compared to other people’s.
|
||||||
|
</p>
|
||||||
|
<div class="w-fit mx-auto">
|
||||||
|
<router-link active-class="active-link" class="navlink" to="/results/answers/0">
|
||||||
|
<div class="inline-flex px-3 py-1 space-x-2 rounded-md bg-lime-800 text-white transition-all duration-300 ease-in-out hover:bg-lime-600">
|
||||||
|
<span class="scale-75">
|
||||||
|
<FeatureSearch/>
|
||||||
|
</span>
|
||||||
|
<span class="uncial-antiqua">Take a Look</span>
|
||||||
|
</div>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</Content>
|
||||||
|
</TextFrame>
|
||||||
|
</template>
|
63
client/src/views/results/compare-answers/Index.vue
Normal file
63
client/src/views/results/compare-answers/Index.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
import Config from '@/config.js'
|
||||||
|
import { useQuestionStore } from '@/stores/questions.js'
|
||||||
|
import { useAnswersStore } from '@/stores/answers.js'
|
||||||
|
import { useAppStore } from '@/stores/app.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const questionStore = useQuestionStore()
|
||||||
|
const answersStore = useAnswersStore()
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
return {
|
||||||
|
questionStore,
|
||||||
|
answersStore,
|
||||||
|
appStore
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'CompareAnswersIndex',
|
||||||
|
mounted() {
|
||||||
|
this.getAnswers()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getAnswers() {
|
||||||
|
this.error = this.questions = null
|
||||||
|
this.loading = true
|
||||||
|
axios.get(`${Config.SERVER}api/answers/`)
|
||||||
|
.then((response) => {
|
||||||
|
console.log('Fetched answer stats from the server.')
|
||||||
|
this.appStore.store('answers', response.data)
|
||||||
|
})
|
||||||
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
|
this.$router.push('/err_refused')
|
||||||
|
})
|
||||||
|
axios.get(`${Config.SERVER}api/count/`)
|
||||||
|
.then((response) => {
|
||||||
|
console.log('Fetched user count from the server.')
|
||||||
|
this.appStore.store('count', response.data)
|
||||||
|
})
|
||||||
|
.catch( error => {
|
||||||
|
console.log(error)
|
||||||
|
this.$router.push('/err_refused')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<router-view v-slot="{ Component, route }" class="w-full" ref="panel" appear>
|
||||||
|
<Transition mode="out-in"
|
||||||
|
enter-active-class="transition-all duration-300 origin-center ease-in"
|
||||||
|
enter-from-class="transform opacity-0 md:scale-95"
|
||||||
|
leave-active-class="transition-all duration-300 origin-center ease-out"
|
||||||
|
leave-to-class="transform opacity-0 md:scale-95"
|
||||||
|
>
|
||||||
|
<component :is="Component" :key="route.path"/>
|
||||||
|
</Transition>
|
||||||
|
</router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Reference in New Issue
Block a user