add color and routing

This commit is contained in:
2025-06-01 11:43:00 +02:00
parent 03e4a5790a
commit 87865871df
7 changed files with 93 additions and 22 deletions
+4 -2
View File
@@ -1,6 +1,7 @@
<template>
<div class="emphased">
<div v-for="(val, index) in values" :id="`${questionId}-${val}`" :key="index">
<div v-for="(val, index) in values" :id="`${questionId}-${val}`" :key="index"
:style="{ background: colors[index] }">
<input type="radio" :value="val" :name="String(questionId)">
<label :for="`${questionId}-${val}`">{{ val }}</label>
</div>
@@ -11,10 +12,11 @@
<script setup lang="ts">
interface Props {
values?: string[]
colors?: string[]
questionId: string
}
const { values = ["Très bien", "Bien", "Passable", "Insuffisant", "À rejeter"], questionId } = defineProps<Props>()
const { values = ["Très bien", "Bien", "Passable", "Insuffisant", "À rejeter"], colors = ["#4DB544", "#87E169", "#FFC33C", "#FF824B", "#E94A4D"], questionId } = defineProps<Props>()
</script>
+4 -3
View File
@@ -1,7 +1,7 @@
<template>
<div class="emphased">
<div v-for="(amount, val) in filtered_results" :id="`${questionId}-${val}`" :key="val"
:style="{ width: `${(amount / total) * 100}%` }">
:style="{ width: `${(amount / total) * 100}%`, background: colors[values.indexOf(val)] }">
<span>({{ amount }}){{ val }}</span>
</div>
</div>
@@ -12,11 +12,12 @@
interface Props {
values?: string[]
colors?: string[]
results: { [question_id: string]: { [values: string]: number } }
questionId: string
}
const { values = ["Très bien", "Bien", "Passable", "Insuffisant", "À rejeter"], results, questionId } = defineProps<Props>()
const { values = ["Très bien", "Bien", "Passable", "Insuffisant", "À rejeter"], colors = ["#4DB544", "#87E169", "#FFC33C", "#FF824B", "#E94A4D"], results, questionId } = defineProps<Props>()
const filtered_results = computed(() => {
if (!(questionId in results)) {
@@ -57,7 +58,7 @@ const total = computed(() => Object.values(filtered_results.value).reduce((acc,
.emphased:after {
content: "";
position: absolute;
z-index: -1;
z-index: 100;
top: -10px;
bottom: -10px;
left: 50%;
+18
View File
@@ -0,0 +1,18 @@
<script setup lang="ts">
import type { NuxtError } from '#app'
const { error } = defineProps({
error: Object as () => NuxtError
})
// const handleError = () => clearError({ redirect: '/' })
</script>
<template>
<div>
<h2>{{ error?.statusCode }}</h2>
<div>{{ error?.statusMessage }}</div>
<div>{{ error?.message }}</div>
<!-- <button @click="handleError">Clear errors</button> -->
</div>
</template>
+30
View File
@@ -0,0 +1,30 @@
export default defineNuxtRouteMiddleware(async (to, _from) => {
const runtimeConfig = useRuntimeConfig()
const code = to.query.code;
if (to.path === "/poll") {
const { error } = await useFetch(`${runtimeConfig.public.apiBase}/check/${code}`);
if (error.value && error.value.statusCode !== 200) {
if(error.value.statusCode == 403){
return navigateTo({path:"/results", query:to.query});
}
throw createError({
statusCode: error.value.statusCode,
statusMessage: error.value.statusMessage,
message: error.value.data.message
});
}
return;
}
if(to.path === "/results"){
return
}
// In a real app you would probably not redirect every route to `/`
// however it is important to check `to.path` before redirecting or you
// might get an infinite redirect loop
if (to.path !== "/") {
return navigateTo("/");
}
});
+6 -1
View File
@@ -2,5 +2,10 @@
export default defineNuxtConfig({
compatibilityDate: '2025-05-15',
devtools: { enabled: true },
modules: ['@nuxt/eslint']
modules: ['@nuxt/eslint'],
runtimeConfig:{
public: {
apiBase: '/api'
}
}
})
+20 -13
View File
@@ -1,23 +1,30 @@
<template>
<MainPoll :question-component="QuestionChoice" @submit="submitForm">
<template #submit>
<button type="submit">Submit</button>
</template>
</MainPoll>
<MainPoll :question-component="QuestionChoice" @submit="submitForm">
<template #submit>
<button type="submit">Submit</button>
</template>
</MainPoll>
</template>
<script setup lang="ts">
import { MainPoll } from '#components';
import QuestionChoice from '~/components/QuestionChoice.vue';
const runtimeConfig = useRuntimeConfig()
const route = useRoute()
async function submitForm(e: Event) {
const target = e.target
if (!target || !(target instanceof HTMLFormElement)) {
throw Error("Form target not found")
}
await $fetch("http://localhost:3000/vote/beautifulAccessCode", {
method: "POST",
body: Object.fromEntries(new FormData(target))
})
const target = e.target
if (!target || !(target instanceof HTMLFormElement)) {
throw Error("Form target not found")
}
await $fetch(`${runtimeConfig.public.apiBase}/vote/${route.query.code}`, {
method: "POST",
body: Object.fromEntries(new FormData(target))
})
navigateTo({ path: "/results", query: route.query })
}
</script>
+11 -3
View File
@@ -10,10 +10,18 @@
<script setup lang="ts">
import QuestionResult from '~/components/QuestionResult.vue';
const { data, error } = await useFetch<{ [question_id: string]: { [values: string]: number } }>('http://localhost:3000/results/beautifulAccessCode', {
const runtimeConfig = useRuntimeConfig()
const route = useRoute()
const { data, error } = await useFetch<{ [question_id: string]: { [values: string]: number } }>(`${runtimeConfig.public.apiBase}/results/${route.query.code}`, {
})
if (error) {
console.log(error.value)
if (error && error.value) {
throw createError({
statusCode: error.value.statusCode,
statusMessage: error.value.statusMessage,
message: error.value.data.message
});
}
</script>