daisyui, categories, check examstore at middleware, remove 7.css
This commit is contained in:
parent
3c5511f067
commit
652550a41d
23 changed files with 296 additions and 303 deletions
22
app.vue
22
app.vue
|
@ -1,23 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import "~/assets/css/main.css";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.set-translate {
|
||||
@apply absolute top-[50%] left-[50%];
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
/* .page-enter-active,
|
||||
.page-leave-active {
|
||||
transition: all 0.4s;
|
||||
}
|
||||
.page-enter-from,
|
||||
.page-leave-to {
|
||||
opacity: 0;
|
||||
filter: blur(1rem);
|
||||
} */
|
||||
</style>
|
||||
|
|
23
assets/css/main.css
Normal file
23
assets/css/main.css
Normal file
|
@ -0,0 +1,23 @@
|
|||
.btn {
|
||||
height: initial !important;
|
||||
min-height: var(--size);
|
||||
}
|
||||
.set-translate {
|
||||
@apply absolute top-[50%] left-[50%];
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* Transition (later)
|
||||
.page-enter-active,
|
||||
.page-leave-active {
|
||||
transition: all 0.4s;
|
||||
}
|
||||
.page-enter-from,
|
||||
.page-leave-to {
|
||||
opacity: 0;
|
||||
filter: blur(1rem);
|
||||
} */
|
||||
|
||||
.info-little-box {
|
||||
@apply inline-block px-[15px] py-[8px] bg-blue-500 text-white font-bold rounded-md;
|
||||
}
|
|
@ -7,10 +7,12 @@ const abc_model = defineModel();
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-3 border-t p-4 border-slate-300 bg-slate-100">
|
||||
<div
|
||||
class="flex flex-col gap-5 border-t px-4 py-5 border-slate-300 bg-slate-100"
|
||||
>
|
||||
<div class="text-xl">{{ question?.pytanie }}</div>
|
||||
<div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col gap-3">
|
||||
<input
|
||||
type="radio"
|
||||
name="abc"
|
||||
|
@ -21,7 +23,9 @@ const abc_model = defineModel();
|
|||
/>
|
||||
<label for="odp_a">
|
||||
<div
|
||||
:class="`btn-answer ${abc_model == 'a' ? ' !bg-fuchsia-500' : ''}`"
|
||||
:class="`btn btn-primary btn-lg ${
|
||||
abc_model == 'a' ? ' !btn-secondary' : ''
|
||||
}`"
|
||||
>
|
||||
A
|
||||
</div>
|
||||
|
@ -37,7 +41,9 @@ const abc_model = defineModel();
|
|||
/>
|
||||
<label for="odp_b">
|
||||
<div
|
||||
:class="`btn-answer ${abc_model == 'b' ? ' !bg-fuchsia-500' : ''}`"
|
||||
:class="`btn btn-primary btn-lg ${
|
||||
abc_model == 'b' ? ' !btn-secondary' : ''
|
||||
}`"
|
||||
>
|
||||
B
|
||||
</div>
|
||||
|
@ -53,7 +59,9 @@ const abc_model = defineModel();
|
|||
/>
|
||||
<label for="odp_c">
|
||||
<div
|
||||
:class="`btn-answer ${abc_model == 'c' ? ' !bg-fuchsia-500' : ''}`"
|
||||
:class="`btn btn-primary btn-lg ${
|
||||
abc_model == 'c' ? ' !btn-secondary' : ''
|
||||
}`"
|
||||
>
|
||||
C
|
||||
</div>
|
||||
|
@ -65,21 +73,11 @@ const abc_model = defineModel();
|
|||
</template>
|
||||
|
||||
<style scoped>
|
||||
.btn-answer {
|
||||
@apply flex justify-center items-center text-center;
|
||||
}
|
||||
label {
|
||||
@apply cursor-pointer flex flex-row gap-2 items-center;
|
||||
}
|
||||
|
||||
label:hover .btn-answer {
|
||||
@apply bg-blue-300;
|
||||
}
|
||||
|
||||
label:hover {
|
||||
@apply bg-slate-200;
|
||||
}
|
||||
|
||||
/* label > div {
|
||||
} */
|
||||
</style>
|
||||
|
|
|
@ -7,44 +7,24 @@ const tak_nie_model = defineModel();
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-3 border-t p-4 border-slate-300 bg-slate-100">
|
||||
<div
|
||||
class="flex flex-col gap-6 border-t px-4 py-5 border-slate-300 bg-slate-100"
|
||||
>
|
||||
<div class="text-xl">{{ question?.pytanie }}</div>
|
||||
<div>
|
||||
<div class="flex flex-row justify-around">
|
||||
<input
|
||||
type="radio"
|
||||
name="tak_nie"
|
||||
id="odp_tak"
|
||||
v-for="tn in ['tak', 'nie']"
|
||||
:id="`odp_${tn}`"
|
||||
v-model="tak_nie_model"
|
||||
value="tak"
|
||||
class="hidden"
|
||||
:value="tn"
|
||||
class="btn btn-primary btn-xl"
|
||||
:aria-label="tn.toUpperCase()"
|
||||
:class="`${tak_nie_model == tn ? ' !btn-secondary' : ''}`"
|
||||
:checked="tak_nie_model == tn"
|
||||
/>
|
||||
<label for="odp_tak">
|
||||
<div
|
||||
:class="`btn-answer ${
|
||||
tak_nie_model == 'tak' ? ' !bg-fuchsia-500' : ''
|
||||
}`"
|
||||
>
|
||||
TAK
|
||||
</div>
|
||||
</label>
|
||||
<input
|
||||
type="radio"
|
||||
name="tak_nie"
|
||||
id="odp_nie"
|
||||
v-model="tak_nie_model"
|
||||
value="nie"
|
||||
class="hidden"
|
||||
/>
|
||||
<label for="odp_nie">
|
||||
<div
|
||||
:class="`btn-answer ${
|
||||
tak_nie_model == 'nie' ? ' !bg-fuchsia-500' : ''
|
||||
}`"
|
||||
>
|
||||
NIE
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
8
components/Loading.vue
Normal file
8
components/Loading.vue
Normal file
|
@ -0,0 +1,8 @@
|
|||
<template>
|
||||
<div
|
||||
class="flex min-h-dvh justify-center items-center text-5xl flex-col gap-10"
|
||||
>
|
||||
<span class="loading loading-spinner loading-xl scale-[2.5] block"></span>
|
||||
<span class="block">Ładowanie</span>
|
||||
</div>
|
||||
</template>
|
|
@ -24,22 +24,14 @@ const emit = defineEmits<{
|
|||
<h1 class="text-[1.5rem]">{{ title }}</h1>
|
||||
<div class="*:inline">Punkty: <slot name="points" /> / 74</div>
|
||||
<div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div>
|
||||
<div
|
||||
class="flex flex-row gap-2 *:py-1 *:px-3 *:border *:border-1 *:border-slate-300 *:rounded-md *:bg-slate-100"
|
||||
>
|
||||
<button
|
||||
class="!border-slate-200 text-slate-600"
|
||||
@click="emit('homepage')"
|
||||
>
|
||||
<div class="flex flex-row gap-2">
|
||||
<button class="btn btn-soft" @click="emit('homepage')">
|
||||
Wróć na stronę główną
|
||||
</button>
|
||||
<button class="!bg-slate-200 text-slate-800" @click="emit('newExam')">
|
||||
<button class="btn btn-outline" @click="emit('newExam')">
|
||||
Rozpocznij jeszcze raz
|
||||
</button>
|
||||
<button
|
||||
class="!border-2 !border-slate-200 !bg-slate-700 text-white"
|
||||
@click="emit('close')"
|
||||
>
|
||||
<button class="btn btn-neutral" @click="emit('close')">
|
||||
Przejrzyj odpowiedzi
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
import "7.css/dist/7.scoped.css";
|
||||
|
||||
const props = defineProps<{
|
||||
result: ResultEndType;
|
||||
countBasic: number;
|
||||
|
@ -17,98 +15,68 @@ const isAdvanced = computed(() => props.now == "advanced");
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col items-center p-4 gap-10 border-l border-slate-300 bg-slate-100"
|
||||
class="flex flex-col items-stretch p-4 gap-10 border-l border-slate-300 bg-slate-100"
|
||||
>
|
||||
<div>
|
||||
<button @click="$emit('end-exam')" class="btn-major">
|
||||
<button @click="$emit('end-exam')" class="btn btn-warning btn-xl">
|
||||
Zakończ egzamin
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex flex-row gap-6 *:flex-1 w-full">
|
||||
<div :class="isBasic ? '' : 'opacity-45'">
|
||||
<div class="flex flex-col gap-1" :class="isBasic ? '' : 'opacity-45'">
|
||||
<span class="text-lg">Pytania podstawowe</span>
|
||||
<div class="win7 *:!h-10 *:*:!h-10 *:*:*:h-10 text-lg">
|
||||
<div
|
||||
role="progressbar"
|
||||
class="relative"
|
||||
:class="isBasic ? 'animate' : ''"
|
||||
>
|
||||
<div :class="`w-full`">
|
||||
<div
|
||||
class="set-translate w-full text-center bg-blue-500 bg-opacity-60"
|
||||
class="info-little-box w-full text-center"
|
||||
:class="isBasic ? 'font-semibold' : ''"
|
||||
>
|
||||
<span class="block set-translate w-full text-center"
|
||||
>{{ countBasic + 1 }} / {{ dataBasic?.length }}</span
|
||||
>
|
||||
{{ countBasic + 1 }} / {{ dataBasic?.length }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="isAdvanced ? '' : 'opacity-45'">
|
||||
<div class="flex flex-col gap-1" :class="isAdvanced ? '' : 'opacity-45'">
|
||||
<span class="text-lg">Pytania specjalistyczne</span>
|
||||
<div class="win7 *:!h-10 *:*:!h-10 *:*:*:h-10 text-lg">
|
||||
<div
|
||||
role="progressbar"
|
||||
class="relative"
|
||||
:class="isAdvanced ? 'animate' : ''"
|
||||
>
|
||||
<div class="w-full">
|
||||
<div
|
||||
class="set-translate w-full text-center bg-blue-500 bg-opacity-60"
|
||||
class="info-little-box w-full text-center"
|
||||
:class="isAdvanced ? 'font-semibold' : ''"
|
||||
>
|
||||
<span class="block set-translate w-full text-center">
|
||||
{{ countAdvanced + 1 }} / {{ dataAdvanced?.length }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center text-xl flex flex-col gap-2">
|
||||
<span>Czas na zapoznanie się z pytaniem</span>
|
||||
<div class="flex flex-row items-stretch gap-2">
|
||||
<div class="btn btn-primary">START</div>
|
||||
<div class="h-full flex-1 relative">
|
||||
<progress
|
||||
class="progress progress-warning w-full h-full"
|
||||
value="50"
|
||||
max="100"
|
||||
></progress>
|
||||
<span class="block set-translate z-10 text-black text-2xl">20s</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center text-xl">
|
||||
Czas na zapoznanie się z pytaniem
|
||||
|
||||
<div class="flex flex-row items-stretch">
|
||||
<div class="btn-major">START</div>
|
||||
<div class="win7 flex-1 *:!h-[100%] *:*:!h-[100%]">
|
||||
<div role="progressbar" class="relative min-h-6">
|
||||
<div class="progressive !bg-orange-500">
|
||||
<div class="set-translate w-full text-center text-3xl">10 s</div>
|
||||
<div class="text-center text-xl flex flex-col gap-2">
|
||||
<span>Czas na udzielenie odpowiedzi</span>
|
||||
<div class="h-9 relative">
|
||||
<progress
|
||||
class="progress progress-warning w-full h-full"
|
||||
value="50"
|
||||
max="100"
|
||||
></progress>
|
||||
<span class="block set-translate z-10 text-black text-2xl">15s</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-h-[150px] overflow-y-scroll">
|
||||
{{ result }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center text-xl">
|
||||
Czas na udzielenie odpowiedzi
|
||||
|
||||
<div class="flex flex-row items-stretch">
|
||||
<div class="win7 flex-1 *:!h-[100%] *:*:!h-[100%]">
|
||||
<div role="progressbar" class="relative min-h-6">
|
||||
<div class="progressive !bg-orange-500">
|
||||
<div class="set-translate w-full text-center text-3xl">10 s</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex-1"></div>
|
||||
<button
|
||||
@click="$emit('next-question')"
|
||||
class="btn-major"
|
||||
class="btn btn-warning btn-xl"
|
||||
:disabled="ending"
|
||||
>
|
||||
Następne pytanie
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="max-h-[150px] overflow-y-scroll">{{ result }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
@ -116,11 +84,6 @@ const isAdvanced = computed(() => props.now == "advanced");
|
|||
animation: progressZapoznanie 20s linear;
|
||||
}
|
||||
|
||||
.btn-major:disabled,
|
||||
.btn-major:disabled:hover {
|
||||
@apply cursor-not-allowed bg-orange-600 !bg-opacity-40;
|
||||
}
|
||||
|
||||
@keyframes progressZapoznanie {
|
||||
0% {
|
||||
width: 0;
|
||||
|
|
|
@ -16,9 +16,9 @@ const isAdvanced = computed(() => props.now == "advanced");
|
|||
|
||||
const boxesAmount = computed(() => {
|
||||
if (isBasic.value) {
|
||||
return 20 + 1;
|
||||
return 20;
|
||||
} else if (isAdvanced.value) {
|
||||
return 12 + 1;
|
||||
return 12;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,22 +37,17 @@ const countSwitchable = computed(() => {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col items-center p-4 gap-6 border-l border-slate-300 bg-slate-100"
|
||||
class="flex flex-col items-stretch p-4 gap-6 border-l border-slate-300 bg-slate-100"
|
||||
>
|
||||
<div>
|
||||
<button @click="$emit('nav', '/')" class="btn-major">
|
||||
<button @click="$emit('nav', '/')" class="btn btn-warning btn-xl">
|
||||
Wróć na stronę główną
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex flex-row gap-6 *:flex-1 w-full">
|
||||
<button
|
||||
class="text-md text-white bg-blue-400"
|
||||
@click="$emit('change-now', 'basic')"
|
||||
>
|
||||
<div class="flex flex-row gap-4 *:flex-1 w-full flex-wrap">
|
||||
<button class="btn btn-info btn-lg" @click="$emit('change-now', 'basic')">
|
||||
Pytania podstawowe
|
||||
</button>
|
||||
<button
|
||||
class="text-md text-white bg-blue-400"
|
||||
class="btn btn-info btn-lg"
|
||||
@click="$emit('change-now', 'advanced')"
|
||||
>
|
||||
Pytania specjalistyczne
|
||||
|
@ -61,37 +56,32 @@ const countSwitchable = computed(() => {
|
|||
<div
|
||||
class="grid grid-cols-[repeat(auto-fit,50px)] gap-2 justify-around w-full"
|
||||
>
|
||||
<div
|
||||
v-for="num in range(1, boxesAmount)"
|
||||
class="p-1 bg-blue-500 text-white text-center cursor-pointer"
|
||||
@click="$emit('change-count', num - 1)"
|
||||
<input
|
||||
type="radio"
|
||||
:aria-label="(num + 1).toString()"
|
||||
class="btn btn-lg"
|
||||
:name="`${now}-chooser`"
|
||||
v-for="num in range(0, boxesAmount)"
|
||||
@click="$emit('change-count', num)"
|
||||
:class="`${
|
||||
isBasic
|
||||
? result.basic[num - 1].question?.poprawna_odp.toLowerCase() ==
|
||||
result.basic[num - 1].chosen_answer
|
||||
? 'bg-green-500'
|
||||
: 'bg-red-500'
|
||||
? result.basic[num].question?.poprawna_odp.toLowerCase() ==
|
||||
result.basic[num].chosen_answer
|
||||
? 'btn-success'
|
||||
: 'btn-error'
|
||||
: ''
|
||||
}${
|
||||
isAdvanced
|
||||
? result.advanced[num - 1].question?.poprawna_odp.toLowerCase() ==
|
||||
result.advanced[num - 1].chosen_answer
|
||||
? 'bg-green-500'
|
||||
: 'bg-red-500'
|
||||
? result.advanced[num].question?.poprawna_odp.toLowerCase() ==
|
||||
result.advanced[num].chosen_answer
|
||||
? 'btn-success'
|
||||
: 'btn-error'
|
||||
: ''
|
||||
} ${countSwitchable + 1 == num ? '!bg-orange-500' : ''}`"
|
||||
>
|
||||
{{ num }}
|
||||
}`"
|
||||
:checked="countSwitchable == num"
|
||||
:key="`choose-${num}-${now}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="flex flex-row gap-6 *:flex-1 w-full">
|
||||
<button class="text-md text-white bg-blue-400">
|
||||
Odtwórz film ponownie
|
||||
</button>
|
||||
<button class="text-md text-white bg-blue-400">
|
||||
Pokaż poprawną odpowiedź
|
||||
</button>
|
||||
</div> -->
|
||||
<div class="text-center text-4xl flex flex-col gap-5">
|
||||
<span class="block">Poprawna odpowiedź</span>
|
||||
<span class="block">{{ question?.poprawna_odp }}</span>
|
||||
|
@ -110,10 +100,9 @@ const countSwitchable = computed(() => {
|
|||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<button @click="$emit('nav', '/exam')" class="btn-major">
|
||||
<div class="flex-1"></div>
|
||||
<button @click="$emit('nav', '/exam')" class="btn btn-warning btn-xl">
|
||||
Rozpocznij jeszcze raz
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -28,12 +28,12 @@ const timeRemainingFriendly = computed(() => {
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span class="block">Aktualna kategoria (implement)</span>
|
||||
<span class="block">Aktualna kategoria</span>
|
||||
<div class="info-little-box">{{ category }}</div>
|
||||
</div>
|
||||
<div v-if="typeof timeRemaining !== 'undefined'">
|
||||
<span class="block">Czas do końca egzaminu</span>
|
||||
<div class="info-little-box w-18 text-center">
|
||||
<div class="info-little-box w-20 text-center">
|
||||
{{ timeRemainingFriendly }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<template>
|
||||
<div><slot /></div>
|
||||
</template>
|
|
@ -1,5 +0,0 @@
|
|||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div><slot /></div>
|
||||
</template>
|
10
middleware/exam.ts
Normal file
10
middleware/exam.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
const examStore = useExamStore();
|
||||
|
||||
if (examStore.category != "") {
|
||||
examStore.mildReset();
|
||||
} else {
|
||||
examStore.resetExam();
|
||||
return navigateTo("/");
|
||||
}
|
||||
});
|
8
middleware/result.ts
Normal file
8
middleware/result.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
const examStore = useExamStore();
|
||||
|
||||
if (!examStore.end) {
|
||||
examStore.resetExam();
|
||||
return navigateTo("/");
|
||||
}
|
||||
});
|
|
@ -10,6 +10,7 @@ export default defineNuxtConfig({
|
|||
imports: {
|
||||
dirs: ["types/*.ts", "store/*.ts", "types/**/*.ts"],
|
||||
},
|
||||
// Transition (later)
|
||||
// app: {
|
||||
// pageTransition: { name: "page", mode: "out-in" },
|
||||
// },
|
||||
|
@ -18,4 +19,7 @@ export default defineNuxtConfig({
|
|||
cdn_url: process.env.CDN_URL,
|
||||
},
|
||||
},
|
||||
routeRules: {
|
||||
"/": { prerender: true },
|
||||
},
|
||||
});
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"7.css": "^0.17.0",
|
||||
"@nuxt/fonts": "0.10.3",
|
||||
"@nuxtjs/tailwindcss": "6.13.1",
|
||||
"@pinia/nuxt": "0.10.1",
|
||||
"array-shuffle": "^3.0.0",
|
||||
"daisyui": "^5.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"drizzle-orm": "^0.40.0",
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
definePageMeta({
|
||||
layout: "exam",
|
||||
});
|
||||
|
||||
import "7.css/dist/7.scoped.css";
|
||||
import { useExamStore } from "~/store/examResults";
|
||||
import { useExamStore } from "~/store/examStore";
|
||||
|
||||
import { intervalToDuration, addMinutes, addSeconds, isEqual } from "date-fns";
|
||||
|
||||
definePageMeta({ middleware: ["exam"] });
|
||||
|
||||
const nowTime = ref(new Date());
|
||||
const timeEnd = addMinutes(new Date(), 25);
|
||||
|
||||
|
@ -31,8 +28,6 @@ onMounted(() => {
|
|||
|
||||
const examStore = useExamStore();
|
||||
|
||||
examStore.resetExam();
|
||||
|
||||
useHead({
|
||||
title: "Pytanie 1/20",
|
||||
});
|
||||
|
@ -41,13 +36,21 @@ const {
|
|||
data: dataBasic,
|
||||
error: errorBasic,
|
||||
status: statusBasic,
|
||||
} = await useFetch<BasicQuestion[]>("/api/basic");
|
||||
} = await useLazyFetch<BasicQuestion[]>(`/api/basic`, {
|
||||
query: {
|
||||
category: examStore.category,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
data: dataAdvanced,
|
||||
error: errorAdvanced,
|
||||
status: statusAdvanced,
|
||||
} = await useFetch<AdvancedQuestion[]>("/api/advanced");
|
||||
} = await useLazyFetch<AdvancedQuestion[]>(`/api/advanced`, {
|
||||
query: {
|
||||
category: examStore.category,
|
||||
},
|
||||
});
|
||||
|
||||
const countBasic = ref(0);
|
||||
const countAdvanced = ref(-1);
|
||||
|
@ -150,12 +153,12 @@ const result: Ref<ResultEndType> = ref({
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="statusBasic === 'success'">
|
||||
<div v-if="statusBasic === 'success' && statusAdvanced === 'success'">
|
||||
<div class="grid grid-cols-4 min-h-dvh">
|
||||
<div class="col-span-3 flex flex-col gap-4">
|
||||
<TopBar
|
||||
:points="question?.liczba_pkt"
|
||||
:category="`B`"
|
||||
:category="examStore.category"
|
||||
:time-remaining="timeRemainingTotal"
|
||||
/>
|
||||
<Media :media="media" />
|
||||
|
@ -187,44 +190,6 @@ const result: Ref<ResultEndType> = ref({
|
|||
<div v-else-if="statusBasic === 'error' || statusAdvanced === 'error'">
|
||||
An API error occurred: {{ errorBasic }} {{ errorAdvanced }}
|
||||
</div>
|
||||
<div v-else>Loading...</div>
|
||||
<Loading v-else />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
@apply box-border text-white font-bold p-3 rounded-lg w-fit cursor-pointer border-[4px] transition duration-100 select-none;
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
@apply duration-0;
|
||||
}
|
||||
|
||||
.btn-answer {
|
||||
@apply btn bg-blue-500 text-xl;
|
||||
}
|
||||
|
||||
.btn-answer:hover {
|
||||
@apply bg-blue-300;
|
||||
}
|
||||
|
||||
.btn-answer:active {
|
||||
@apply bg-blue-400;
|
||||
}
|
||||
|
||||
.btn-major {
|
||||
@apply btn bg-orange-400 text-base;
|
||||
}
|
||||
|
||||
.btn-major:hover {
|
||||
@apply bg-orange-200;
|
||||
}
|
||||
|
||||
.btn-major:active {
|
||||
@apply bg-orange-300;
|
||||
}
|
||||
|
||||
.info-little-box {
|
||||
@apply inline-block px-[15px] py-[8px] bg-blue-500 text-white font-bold;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,43 @@
|
|||
<script setup lang="ts">
|
||||
const categories = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"T",
|
||||
"AM",
|
||||
"A1",
|
||||
"A2",
|
||||
"B1",
|
||||
"C1",
|
||||
"D1",
|
||||
"PT",
|
||||
];
|
||||
|
||||
const examStore = useExamStore();
|
||||
|
||||
function setAndGo(category: string) {
|
||||
examStore.category = category;
|
||||
return navigateTo("/exam");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Test na prawo jazdy kat.B</h1>
|
||||
<div class="text-3xl">
|
||||
<span>Test na prawo jazdy</span>
|
||||
<p>
|
||||
Witaj w teście na prawo jazdy kat.B, aby rozpocząć, naciśnij poniższy
|
||||
przycisk:
|
||||
Witaj w teście na prawo jazdy, aby rozpocząć, naciśnij jeden z poniższych
|
||||
przycisków:
|
||||
<br />
|
||||
</p>
|
||||
<NuxtLink to="/exam" class="text-4xl font-bold bg-fuchsia-200"
|
||||
>START!</NuxtLink
|
||||
<div class="flex flex-row flex-wrap gap-2">
|
||||
<button
|
||||
class="btn btn-xl btn-secondary"
|
||||
v-for="category in categories"
|
||||
@click="setAndGo(category)"
|
||||
>
|
||||
{{ category }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -2,18 +2,12 @@
|
|||
import { ModalsContainer, useModal } from "vue-final-modal";
|
||||
import ResultModal from "~/components/ResultModal.vue";
|
||||
|
||||
definePageMeta({
|
||||
layout: "exam",
|
||||
});
|
||||
definePageMeta({ middleware: ["result"] });
|
||||
|
||||
const examStore = useExamStore();
|
||||
|
||||
const points = ref<number>(0);
|
||||
|
||||
if (!examStore.end) {
|
||||
examStore.resetExam();
|
||||
await navigateTo("/");
|
||||
} else {
|
||||
examStore.result.basic.forEach((answer) => {
|
||||
if (answer.chosen_is_correct) {
|
||||
points.value += answer.question?.liczba_pkt ?? 0;
|
||||
|
@ -24,7 +18,6 @@ if (!examStore.end) {
|
|||
points.value += answer.question?.liczba_pkt ?? 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const resultTrueFalse = ref(points.value >= 68 ? "pozytywny" : "negatywny");
|
||||
|
||||
|
@ -117,7 +110,10 @@ function nav(route: string) {
|
|||
<div>
|
||||
<div class="grid grid-cols-4 min-h-dvh">
|
||||
<div class="col-span-3 flex flex-col gap-4">
|
||||
<TopBar :points="question?.liczba_pkt" :category="`B`" />
|
||||
<TopBar
|
||||
:points="question?.liczba_pkt"
|
||||
:category="examStore.category"
|
||||
/>
|
||||
<Media :media="media" />
|
||||
<BasicQuestionBlock
|
||||
v-if="now == 'basic'"
|
||||
|
|
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
|
@ -11,9 +11,6 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
7.css:
|
||||
specifier: ^0.17.0
|
||||
version: 0.17.0
|
||||
'@nuxt/fonts':
|
||||
specifier: 0.10.3
|
||||
version: 0.10.3(db0@0.2.4(drizzle-orm@0.40.0(@types/pg@8.11.11)(gel@2.0.0)(pg@8.13.3)))(ioredis@5.5.0)(magicast@0.3.5)(vite@6.1.1(@types/node@22.13.4)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))
|
||||
|
@ -26,6 +23,9 @@ importers:
|
|||
array-shuffle:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
daisyui:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
date-fns:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
|
@ -72,9 +72,6 @@ importers:
|
|||
|
||||
packages:
|
||||
|
||||
7.css@0.17.0:
|
||||
resolution: {integrity: sha512-U4DqX1WDFDbG6C9Myw/s2tgPapP8bkEYAd4tCchv3Zrjuugye3Fjv3IK32nq2cRO1Y4SnkbsBlyvu+o51rnPGg==}
|
||||
|
||||
'@alloc/quick-lru@5.2.0':
|
||||
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -1835,6 +1832,9 @@ packages:
|
|||
csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
daisyui@5.0.0:
|
||||
resolution: {integrity: sha512-U0K9Bac3Bi3zZGm6ojrw12F0vBHTpEgf46zv/BYxLe07hF0Xnx7emIQliwaRBgJuYhY0BhwQ6wSnq5cJXHA2yA==}
|
||||
|
||||
date-fns@4.1.0:
|
||||
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
|
||||
|
||||
|
@ -4190,8 +4190,6 @@ packages:
|
|||
|
||||
snapshots:
|
||||
|
||||
7.css@0.17.0: {}
|
||||
|
||||
'@alloc/quick-lru@5.2.0': {}
|
||||
|
||||
'@ampproject/remapping@2.3.0':
|
||||
|
@ -5984,6 +5982,8 @@ snapshots:
|
|||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
daisyui@5.0.0: {}
|
||||
|
||||
date-fns@4.1.0: {}
|
||||
|
||||
db0@0.2.4(drizzle-orm@0.40.0(@types/pg@8.11.11)(gel@2.0.0)(pg@8.13.3)):
|
||||
|
|
|
@ -56,11 +56,28 @@ export default defineEventHandler(async (event) => {
|
|||
}
|
||||
const query = getQuery(event);
|
||||
const category = query.category;
|
||||
if (typeof category != "undefined" && typeof category != "string") {
|
||||
const categories = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"T",
|
||||
"AM",
|
||||
"A1",
|
||||
"A2",
|
||||
"B1",
|
||||
"C1",
|
||||
"D1",
|
||||
"PT",
|
||||
];
|
||||
if (category == null || category == "") {
|
||||
throw new Error(
|
||||
"category argument has to be string (or not to be defined at all)"
|
||||
);
|
||||
}
|
||||
if (!categories.includes(`${category}`)) {
|
||||
throw new Error(`category argument has to be equal to: ${categories}`);
|
||||
}
|
||||
const db = drizzle(process.env.DATABASE_URL!);
|
||||
|
||||
const randomizedQuestions: AdvancedQuestion[] = [];
|
||||
|
@ -81,7 +98,7 @@ export default defineEventHandler(async (event) => {
|
|||
if (
|
||||
questionsKeyPoints[randomized].kategorie
|
||||
.split(",")
|
||||
.includes(category ?? "B")
|
||||
.includes(`${category}`)
|
||||
) {
|
||||
chosenRandomQuestions.push(questionsKeyPoints[randomized]);
|
||||
} else {
|
||||
|
|
|
@ -35,11 +35,28 @@ export default defineEventHandler(async (event) => {
|
|||
}
|
||||
const query = getQuery(event);
|
||||
const category = query.category;
|
||||
if (typeof category != "undefined" && typeof category != "string") {
|
||||
const categories = [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"T",
|
||||
"AM",
|
||||
"A1",
|
||||
"A2",
|
||||
"B1",
|
||||
"C1",
|
||||
"D1",
|
||||
"PT",
|
||||
];
|
||||
if (category == null || category == "") {
|
||||
throw new Error(
|
||||
"category argument has to be string (or not to be defined at all)"
|
||||
);
|
||||
}
|
||||
if (!categories.includes(`${category}`)) {
|
||||
throw new Error(`category argument has to be equal to: ${categories}`);
|
||||
}
|
||||
const db = drizzle(process.env.DATABASE_URL!);
|
||||
|
||||
const randomizedQuestions: BasicQuestion[] = [];
|
||||
|
@ -60,7 +77,7 @@ export default defineEventHandler(async (event) => {
|
|||
if (
|
||||
questionsKeyPoints[randomized].kategorie
|
||||
.split(",")
|
||||
.includes(category ?? "B")
|
||||
.includes(`${category}`)
|
||||
) {
|
||||
chosenRandomQuestions.push(questionsKeyPoints[randomized]);
|
||||
} else {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const useExamStore = defineStore("exam-results", () => {
|
||||
export const useExamStore = defineStore("exam-store", () => {
|
||||
const category = ref("");
|
||||
const end = ref(false);
|
||||
const result: Ref<ResultEndType> = ref({
|
||||
basic: [],
|
||||
advanced: [],
|
||||
});
|
||||
function resetExam() {
|
||||
category.value = "";
|
||||
mildReset();
|
||||
}
|
||||
function mildReset() {
|
||||
end.value = false;
|
||||
result.value = {
|
||||
basic: [],
|
||||
|
@ -15,8 +20,10 @@ export const useExamStore = defineStore("exam-results", () => {
|
|||
}
|
||||
|
||||
return {
|
||||
category,
|
||||
end,
|
||||
result,
|
||||
resetExam,
|
||||
mildReset,
|
||||
};
|
||||
});
|
7
tailwind.config.ts
Normal file
7
tailwind.config.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
plugins: [require("daisyui")],
|
||||
daisyui: {
|
||||
themes: ["light", "dark"],
|
||||
},
|
||||
};
|
Loading…
Add table
Reference in a new issue