nuxt-prawo-jazdy/pages/exam.vue

230 lines
5.4 KiB
Vue

<script lang="ts" setup>
definePageMeta({
layout: "exam",
});
import "7.css/dist/7.scoped.css";
import { useExamStore } from "~/store/examResults";
import { intervalToDuration, addMinutes, addSeconds, isEqual } from "date-fns";
const nowTime = ref(new Date());
const timeEnd = addMinutes(new Date(), 25);
const timeRemainingTotal = computed(() =>
intervalToDuration({
start: nowTime.value,
end: timeEnd,
})
);
// const timeRemainingQuestion - to implement
onMounted(() => {
const endInterval = setInterval(() => {
nowTime.value = addSeconds(nowTime.value, 1);
if (isEqual(nowTime.value, timeEnd)) {
clearInterval(endInterval);
endExam();
}
}, 1000);
});
const examStore = useExamStore();
examStore.resetExam();
useHead({
title: "Pytanie 1/20",
});
const {
data: dataBasic,
error: errorBasic,
status: statusBasic,
} = await useFetch<BasicQuestion[]>("/api/basic");
const {
data: dataAdvanced,
error: errorAdvanced,
status: statusAdvanced,
} = await useFetch<AdvancedQuestion[]>("/api/advanced");
const countBasic = ref(0);
const countAdvanced = ref(-1);
const now = ref("basic");
const tak_nie_model = ref();
const abc_model = ref();
const ending = ref(false);
async function next() {
if (countBasic.value + 1 < dataBasic.value?.length!) {
result.value.basic.push({
question: questionBasic.value,
chosen_answer: tak_nie_model.value ?? "",
chosen_is_correct:
tak_nie_model.value == questionBasic.value?.poprawna_odp?.toLowerCase(),
liczba_pkt: questionBasic.value?.liczba_pkt,
});
tak_nie_model.value = "";
countBasic.value++;
useHead({
title: `Pytanie ${countBasic.value + 1}/${dataBasic.value?.length}`,
});
} else if (countAdvanced.value + 1 <= dataAdvanced.value?.length!) {
if (countAdvanced.value != -1) {
result.value.advanced.push({
question: questionAdvanced.value,
chosen_answer: abc_model.value ?? "",
chosen_is_correct:
abc_model.value ==
questionAdvanced.value?.poprawna_odp?.toLowerCase(),
liczba_pkt: questionAdvanced.value?.liczba_pkt,
});
} else {
now.value = "advanced";
result.value.basic.push({
question: questionBasic.value,
chosen_answer: tak_nie_model.value ?? "",
chosen_is_correct:
tak_nie_model.value ==
questionBasic.value?.poprawna_odp?.toLowerCase(),
liczba_pkt: questionBasic.value?.liczba_pkt,
});
tak_nie_model.value = "";
}
if (countAdvanced.value + 1 < dataAdvanced.value?.length!) {
countAdvanced.value++;
}
if (countAdvanced.value == dataAdvanced.value?.length! - 1) {
ending.value = true;
}
abc_model.value = "";
}
}
function endExam() {
while (!ending.value) {
next();
}
next();
examStore.result = result.value;
examStore.end = true;
return navigateTo("/result", { replace: true });
}
const questionBasic = computed<BasicQuestion | undefined>(() =>
dataBasic.value?.at(countBasic.value)
);
const questionAdvanced = computed<AdvancedQuestion | undefined>(() =>
dataAdvanced.value?.at(countAdvanced.value)
);
const question = computed(() => {
if (now.value == "basic") {
return questionBasic.value;
} else if (now.value == "advanced") {
return questionAdvanced.value;
} else {
return;
}
});
const media = computed(() => {
const mediaSplit = question.value?.media?.split(".");
return {
fileType: mediaSplit?.pop()?.toLowerCase(),
fileName: mediaSplit?.join("."),
ogName: question.value?.media,
};
});
const result: Ref<ResultEndType> = ref({
basic: [],
advanced: [],
});
</script>
<template>
<div>
<div v-if="statusBasic === '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`"
:time-remaining="timeRemainingTotal"
/>
<Media :media="media" />
<BasicQuestionBlock
v-if="countAdvanced < 0"
:question="questionBasic"
v-model="tak_nie_model"
/>
<AdvancedQuestionBlock
v-else
:question="questionAdvanced"
v-model="abc_model"
/>
</div>
<RightBarExam
:result="result"
:data-basic="dataBasic"
:data-advanced="dataAdvanced"
:count-basic="countBasic"
:count-advanced="countAdvanced"
@next-question="next()"
@end-exam="endExam()"
:now="now"
:ending="ending"
/>
</div>
</div>
<div v-else-if="statusBasic === 'error' || statusAdvanced === 'error'">
An API error occurred: {{ errorBasic }} {{ errorAdvanced }}
</div>
<div v-else>Loading...</div>
</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>