Compare commits

..

No commits in common. "19508f1148787b603587e22e456d4b4b68255a99" and "81346eb3b9cfcd8405d0419088f00cbd4fa466f6" have entirely different histories.

21 changed files with 173 additions and 2055 deletions

View file

@ -28,12 +28,8 @@ The newest at the moment of me writing this (December 13th 2025) are the (visual
- B - B - B - B
- C - C - C - C
- [ ] i18n - pl, en, de, ua (not all questions are available in ua, api handle) - [ ] i18n - pl, en, de, ua (not all questions are available in ua, api handle)
- [ ] UI i18n - UI i18n
- [x] pl - db: examstore add language field, api handle languages
- [ ] en
- [ ] de
- [ ] ua
- [ ] db: examstore add language field, api handle languages
- [ ] db: (revise) script for processing, (revise and) share appropriate files - [ ] db: (revise) script for processing, (revise and) share appropriate files
- [ ] clean up js code in exam.vue and result.vue (currently a little bit of a mess) - [ ] clean up js code in exam.vue and result.vue (currently a little bit of a mess)

View file

@ -12,3 +12,33 @@ export default [
'D1', 'D1',
'PT', 'PT',
]; ];
export const opis = [
'motocykle bez ograniczeń mocy',
'⭐ samochody osobowe do 3,5 t',
'pojazdy ciężarowe powyżej 3,5 t',
'autobusy',
'ciągniki rolnicze i pojazdy wolnobieżne',
'motorowery i lekkie czterokołowce',
'motocykle do 125 cm³ i 11 kW',
'motocykle do 35 kW',
'czterokołowce (np. quady)',
'pojazdy od 3,5 t do 7,5 t',
'autobusy do 16 pasażerów',
'tramwaje',
];
export const wiek = [
'(24 lata; lub 20 lat jeśli masz kat. A2 min. 2 lata)',
'(18 lat)',
'(21 lat; lub 18 lat z kwalifikacją wstępną)',
'(24 lata; lub 21 lat z kwalifikacją wstępną)',
'(16 lat)',
'(14 lat)',
'(16 lat)',
'(18 lat)',
'(16 lat)',
'(18 lat)',
'(21 lat; lub 18 lat z kwalifikacją wstępną)',
'(21 lat)',
];

View file

@ -18,8 +18,8 @@ watchEffect(() => {
class="flex justify-center items-center backdrop-blur-sm modal" class="flex justify-center items-center backdrop-blur-sm modal"
> >
<div class="flex flex-col p-3 bg-base rounded-md gap-3 modal-box min-w-fit"> <div class="flex flex-col p-3 bg-base rounded-md gap-3 modal-box min-w-fit">
<h1 class="text-[1.5rem]">{{ $t('examEnd') }}</h1> <h1 class="text-[1.5rem]">Koniec egzaminu</h1>
<div class="*:inline">{{ $t('doYouReallyWantToEndExam') }}</div> <div class="*:inline">Czy na pewno chcesz zakończyć egzamin?</div>
<div class="flex flex-row gap-2 justify-around"> <div class="flex flex-row gap-2 justify-around">
<div class="btn btn-lg btn-success" @click="emit('endExam')">Tak</div> <div class="btn btn-lg btn-success" @click="emit('endExam')">Tak</div>
<div class="btn btn-lg btn-error" @click="endModal?.close()">Nie</div> <div class="btn btn-lg btn-error" @click="endModal?.close()">Nie</div>

View file

@ -3,6 +3,6 @@
class="flex min-h-dvh justify-center items-center text-5xl flex-col gap-10" 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 class="loading loading-spinner loading-xl scale-[2.5] block" />
<span class="block">{{ $t('loading') }}</span> <span class="block">Ładowanie</span>
</div> </div>
</template> </template>

View file

@ -64,8 +64,8 @@ function onVideoLoad() {
> >
<source :src="joinURL(cdnUrl, media.name + '.mp4')" type="video/mp4" /> <source :src="joinURL(cdnUrl, media.name + '.mp4')" type="video/mp4" />
</video> </video>
<span v-else class="text-5xl font-bold flex items-center justify-center">{{ <span v-else class="text-5xl font-bold flex items-center justify-center"
$t('questionWithoutVisual') >Pytanie bez wizualizacji</span
}}</span> >
</div> </div>
</template> </template>

View file

@ -17,24 +17,18 @@ defineEmits(['again', 'home']);
<h1 class="text-[1.5rem]"> <h1 class="text-[1.5rem]">
<slot name="title" /> <slot name="title" />
</h1> </h1>
<div class="*:inline"> <div class="*:inline">Kategoria: <slot name="category" /></div>
{{ $t('categoryWord') }}: <slot name="category" /> <div class="*:inline">Punkty: <slot name="points" /> / 74</div>
</div> <div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div>
<div class="*:inline">
{{ $t('points') }}: <slot name="points" /> / 74
</div>
<div class="*:inline">
{{ $t('result') }}: <slot name="resultTrueFalse" />
</div>
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
<div class="btn btn-soft" @click="$emit('home')"> <div class="btn btn-soft" @click="$emit('home')">
{{ $t('goBackToHomePage') }} Wróć na stronę główną
</div> </div>
<div class="btn btn-outline" @click="$emit('again')"> <div class="btn btn-outline" @click="$emit('again')">
{{ $t('startAgain') }} Rozpocznij jeszcze raz
</div> </div>
<button class="btn btn-neutral" @click="myModal?.close()"> <button class="btn btn-neutral" @click="myModal?.close()">
{{ $t('viewAnswers') }} Przejrzyj odpowiedzi
</button> </button>
</div> </div>
</div> </div>

View file

@ -23,19 +23,19 @@ const timeRemainingFriendly = computed(() => {
class="flex flex-none flex-row gap-4 *:flex *:items-center *:gap-3 border-b p-4 border-base-300 bg-base-100" class="flex flex-none flex-row gap-4 *:flex *:items-center *:gap-3 border-b p-4 border-base-300 bg-base-100"
> >
<div> <div>
<span class="block">{{ $t('pointValue') }}</span> <span class="block">Wartość punktowa</span>
<div class="info-little-box"> <div class="info-little-box">
{{ points }} {{ points }}
</div> </div>
</div> </div>
<div> <div>
<span class="block">{{ $t('currentCategory') }}</span> <span class="block">Aktualna kategoria</span>
<div class="info-little-box"> <div class="info-little-box">
{{ category }} {{ category }}
</div> </div>
</div> </div>
<div v-if="typeof timeRemaining !== 'undefined'"> <div v-if="typeof timeRemaining !== 'undefined'">
<span class="block">{{ $t('timeToExamEnd') }}</span> <span class="block">Czas do końca egzaminu</span>
<div class="info-little-box w-20 text-center"> <div class="info-little-box w-20 text-center">
{{ timeRemainingFriendly }} {{ timeRemainingFriendly }}
</div> </div>

View file

@ -54,25 +54,21 @@ onKeyStroke(['X', 'x'], () => {
class="btn btn-warning btn-xl" class="btn btn-warning btn-xl"
@click="tryEndExam()" @click="tryEndExam()"
> >
{{ $t('endExam') }} Zakończ egzamin
</button> </button>
<div class="flex flex-row gap-6 *:flex-1 w-full"> <div class="flex flex-row gap-6 *:flex-1 w-full">
<CurrentQuestionCount <CurrentQuestionCount
:class="now === 'basic' ? 'font-semibold' : 'opacity-45'" :class="now === 'basic' ? 'font-semibold' : 'opacity-45'"
> >
<template #title> <template #title> Pytania podstawowe </template>
{{ $t('basicQuestions') }}
</template>
<template #count> {{ countBasic + 1 }} / 20 </template> <template #count> {{ countBasic + 1 }} / 20 </template>
</CurrentQuestionCount> </CurrentQuestionCount>
<CurrentQuestionCount <CurrentQuestionCount
:class="now === 'advanced' ? 'font-semibold' : 'opacity-45'" :class="now === 'advanced' ? 'font-semibold' : 'opacity-45'"
> >
<template #title> <template #title> Pytania specjalistyczne </template>
{{ $t('advancedQuestions') }}
</template>
<template #count> {{ countAdvanced + 1 }} / 12 </template> <template #count> {{ countAdvanced + 1 }} / 12 </template>
</CurrentQuestionCount> </CurrentQuestionCount>
</div> </div>
@ -81,16 +77,14 @@ onKeyStroke(['X', 'x'], () => {
v-if="phase == 'set-basic'" v-if="phase == 'set-basic'"
class="text-center text-xl flex flex-col gap-2" class="text-center text-xl flex flex-col gap-2"
> >
<span> <span>Czas na zapoznanie się z pytaniem</span>
{{ $t('timeToGetAcquaintedWithTheQuestion') }}
</span>
<div class="flex flex-row items-stretch gap-2"> <div class="flex flex-row items-stretch gap-2">
<div <div
ref="start-button" ref="start-button"
class="btn btn-primary" class="btn btn-primary"
@click="emit('nextTime')" @click="emit('nextTime')"
> >
{{ $t('startBtn') }} START
</div> </div>
<div class="h-full flex-1 relative"> <div class="h-full flex-1 relative">
<progress <progress
@ -99,16 +93,14 @@ onKeyStroke(['X', 'x'], () => {
max="20" max="20"
></progress> ></progress>
<span class="block set-translate z-10 text-black text-2xl"> <span class="block set-translate z-10 text-black text-2xl">
{{ time >= 0 ? time : 0 }} {{ $t('second') }} {{ time >= 0 ? time : 0 }}s
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<div v-else class="text-center text-xl flex flex-col gap-2"> <div v-else class="text-center text-xl flex flex-col gap-2">
<span> <span>Czas na udzielenie odpowiedzi</span>
{{ $t('timeForAnswer') }}
</span>
<div class="h-9 relative"> <div class="h-9 relative">
<progress <progress
class="progress progress-warning w-full h-full" class="progress progress-warning w-full h-full"
@ -116,23 +108,46 @@ onKeyStroke(['X', 'x'], () => {
:max="phase == 'start-basic' ? 15 : 45" :max="phase == 'start-basic' ? 15 : 45"
></progress> ></progress>
<span class="block set-translate z-10 text-black text-2xl"> <span class="block set-translate z-10 text-black text-2xl">
{{ time >= 0 ? time : 0 }} {{ $t('second') }} {{ time >= 0 ? time : 0 }}s
</span> </span>
</div> </div>
</div> </div>
<div class="flex-1"> <div class="flex-1">
<span class="text-xl"> <span class="text-xl">Skróty klawiszowe</span>
{{ $t('keybinds') }}
</span>
<table class="table table-sm"> <table class="table table-sm">
<tbody> <tbody>
<tr <tr>
v-for="key in ['S', 'D', 'X', 'T / Y', 'N', 'A', 'B', 'C']" <td>S</td>
:key="`keybind${key}`" <td>niebieski przycisk start</td>
> </tr>
<td>{{ key }}</td> <tr>
<td>{{ $t(`bindedKeys.${key}`) }}</td> <td>D</td>
<td>następne pytanie</td>
</tr>
<tr>
<td>X</td>
<td>zakończ egzamin</td>
</tr>
<tr>
<td>T / Y</td>
<td>Tak</td>
</tr>
<tr>
<td>N</td>
<td>Nie</td>
</tr>
<tr>
<td>A</td>
<td>A</td>
</tr>
<tr>
<td>B</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>C</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -144,7 +159,7 @@ onKeyStroke(['X', 'x'], () => {
:disabled="ending || setBasic" :disabled="ending || setBasic"
@click="emit('nextQuestion')" @click="emit('nextQuestion')"
> >
{{ $t('nextQuestion') }} Następne pytanie
</button> </button>
</div> </div>
</template> </template>

View file

@ -21,11 +21,11 @@ const emit = defineEmits<{
class="flex flex-col items-stretch p-4 gap-6 border-l border-base-300 bg-base-100" class="flex flex-col items-stretch p-4 gap-6 border-l border-base-300 bg-base-100"
> >
<div class="btn btn-warning btn-xl" @click="$emit('home')"> <div class="btn btn-warning btn-xl" @click="$emit('home')">
{{ $t('goBackToHomePage') }} Wróć na stronę główną
</div> </div>
<button class="btn btn-info btn-lg" @click="emit('changeNow', 'basic')"> <button class="btn btn-info btn-lg" @click="emit('changeNow', 'basic')">
{{ $t('basicQuestions') }} Pytania podstawowe
</button> </button>
<div <div
@ -55,7 +55,7 @@ const emit = defineEmits<{
</div> </div>
<button class="btn btn-info btn-lg" @click="emit('changeNow', 'advanced')"> <button class="btn btn-info btn-lg" @click="emit('changeNow', 'advanced')">
{{ $t('advancedQuestions') }} Pytania specjalistyczne
</button> </button>
<div <div
@ -84,15 +84,11 @@ const emit = defineEmits<{
/> />
</div> </div>
<div class="flex-1"> <div class="flex-1">
<div class="*:inline"> <div class="*:inline">Punkty: <slot name="points" /> / 74</div>
{{ $t('points') }}: <slot name="points" /> / 74 <div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div>
</div>
<div class="*:inline">
{{ $t('result') }}: <slot name="resultTrueFalse" />
</div>
</div> </div>
<div class="btn btn-warning btn-xl" @click="$emit('again')"> <div class="btn btn-warning btn-xl" @click="$emit('again')">
{{ $t('startAgain') }} Rozpocznij jeszcze raz
</div> </div>
</div> </div>
</template> </template>

View file

@ -1,73 +0,0 @@
{
"mainTitle": "Test na prawo jazdy",
"loading": "Ładowanie",
"keybinds": "Skróty klawiszowe",
"bindedKeys": {
"S": "niebieski przycisk start",
"D": "następne pytanie",
"X": "zakończ egzamin",
"T / Y": "Tak",
"N": "Nie",
"A": "A",
"B": "B",
"C": "C"
},
"endExam": "Zakończ egzamin",
"examEnd": "Koniec egzaminu",
"basicQuestions": "Pytania podstawowe",
"advancedQuestions": "Pytania specjalistyczne",
"timeToGetAcquaintedWithTheQuestion": "Czas na zapoznanie się z pytaniem",
"timeForAnswer": "Czas na udzielenie odpowiedzi",
"startBtn": "START",
"second": "s",
"nextQuestion": "Następne pytanie",
"goBackToHomePage": "Wróć na stronę główną",
"points": "Punkty",
"pointValue": "Wartość punktowa",
"currentCategory": "Aktualna kategoria",
"timeToExamEnd": "Czas do końca egzaminu",
"result": "Wynik",
"startAgain": "Rozpocznij jeszcze raz",
"viewAnswers": "Przejrzyj odpowiedzi",
"doYouReallyWantToEndExam": "Czy na pewno chcesz zakończyć egzamin?",
"questionWithoutVisual": "Pytanie bez wizualizacji",
"categoryWord": "Kategoria",
"anAnomalyHasOccured": "Nastąpiła anomalia",
"redirectFrom": "Przekierowanie z",
"end": "Koniec",
"question": "Pytanie",
"anAPIErrorOccured": "Wystąpił błąd z API",
"positive": "pozytywny",
"negative": "negatywny",
"theoreticalExam": "Egzamin teorytyczny",
"category": {
"description": {
"A": "motocykle bez ograniczeń mocy",
"B": "⭐ samochody osobowe do 3,5 t",
"C": "pojazdy ciężarowe powyżej 3,5 t",
"D": "autobusy",
"T": "ciągniki rolnicze i pojazdy wolnobieżne",
"AM": "motorowery i lekkie czterokołowce",
"A1": "motocykle do 125 cm³ i 11 kW",
"A2": "motocykle do 35 kW",
"B1": "czterokołowce (np. quady)",
"C1": "pojazdy od 3,5 t do 7,5 t",
"D1": "autobusy do 16 pasażerów",
"PT": "tramwaje"
},
"age": {
"A": "(24 lata; lub 20 lat jeśli masz kat. A2 min. 2 lata)",
"B": "(18 lat)",
"C": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"D": "(24 lata; lub 21 lat z kwalifikacją wstępną)",
"T": "(16 lat)",
"AM": "(14 lat)",
"A1": "(16 lat)",
"A2": "(18 lat)",
"B1": "(16 lat)",
"C1": "(18 lat)",
"D1": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"PT": "(21 lat)"
}
}
}

View file

@ -1,73 +0,0 @@
{
"mainTitle": "Test na prawo jazdy",
"loading": "Ładowanie",
"keybinds": "Skróty klawiszowe",
"bindedKeys": {
"S": "niebieski przycisk start",
"D": "następne pytanie",
"X": "zakończ egzamin",
"T / Y": "Tak",
"N": "Nie",
"A": "A",
"B": "B",
"C": "C"
},
"endExam": "Zakończ egzamin",
"examEnd": "Koniec egzaminu",
"basicQuestions": "Pytania podstawowe",
"advancedQuestions": "Pytania specjalistyczne",
"timeToGetAcquaintedWithTheQuestion": "Czas na zapoznanie się z pytaniem",
"timeForAnswer": "Czas na udzielenie odpowiedzi",
"startBtn": "START",
"second": "s",
"nextQuestion": "Następne pytanie",
"goBackToHomePage": "Wróć na stronę główną",
"points": "Punkty",
"pointValue": "Wartość punktowa",
"currentCategory": "Aktualna kategoria",
"timeToExamEnd": "Czas do końca egzaminu",
"result": "Wynik",
"startAgain": "Rozpocznij jeszcze raz",
"viewAnswers": "Przejrzyj odpowiedzi",
"doYouReallyWantToEndExam": "Czy na pewno chcesz zakończyć egzamin?",
"questionWithoutVisual": "Pytanie bez wizualizacji",
"categoryWord": "Kategoria",
"anAnomalyHasOccured": "Nastąpiła anomalia",
"redirectFrom": "Przekierowanie z",
"end": "Koniec",
"question": "Pytanie",
"anAPIErrorOccured": "Wystąpił błąd z API",
"positive": "pozytywny",
"negative": "negatywny",
"theoreticalExam": "Egzamin teorytyczny",
"category": {
"description": {
"A": "motocykle bez ograniczeń mocy",
"B": "⭐ samochody osobowe do 3,5 t",
"C": "pojazdy ciężarowe powyżej 3,5 t",
"D": "autobusy",
"T": "ciągniki rolnicze i pojazdy wolnobieżne",
"AM": "motorowery i lekkie czterokołowce",
"A1": "motocykle do 125 cm³ i 11 kW",
"A2": "motocykle do 35 kW",
"B1": "czterokołowce (np. quady)",
"C1": "pojazdy od 3,5 t do 7,5 t",
"D1": "autobusy do 16 pasażerów",
"PT": "tramwaje"
},
"age": {
"A": "(24 lata; lub 20 lat jeśli masz kat. A2 min. 2 lata)",
"B": "(18 lat)",
"C": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"D": "(24 lata; lub 21 lat z kwalifikacją wstępną)",
"T": "(16 lat)",
"AM": "(14 lat)",
"A1": "(16 lat)",
"A2": "(18 lat)",
"B1": "(16 lat)",
"C1": "(18 lat)",
"D1": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"PT": "(21 lat)"
}
}
}

View file

@ -1,73 +0,0 @@
{
"mainTitle": "Test na prawo jazdy",
"loading": "Ładowanie",
"keybinds": "Skróty klawiszowe",
"bindedKeys": {
"S": "niebieski przycisk start",
"D": "następne pytanie",
"X": "zakończ egzamin",
"T / Y": "Tak",
"N": "Nie",
"A": "A",
"B": "B",
"C": "C"
},
"endExam": "Zakończ egzamin",
"examEnd": "Koniec egzaminu",
"basicQuestions": "Pytania podstawowe",
"advancedQuestions": "Pytania specjalistyczne",
"timeToGetAcquaintedWithTheQuestion": "Czas na zapoznanie się z pytaniem",
"timeForAnswer": "Czas na udzielenie odpowiedzi",
"startBtn": "START",
"second": "s",
"nextQuestion": "Następne pytanie",
"goBackToHomePage": "Wróć na stronę główną",
"points": "Punkty",
"pointValue": "Wartość punktowa",
"currentCategory": "Aktualna kategoria",
"timeToExamEnd": "Czas do końca egzaminu",
"result": "Wynik",
"startAgain": "Rozpocznij jeszcze raz",
"viewAnswers": "Przejrzyj odpowiedzi",
"doYouReallyWantToEndExam": "Czy na pewno chcesz zakończyć egzamin?",
"questionWithoutVisual": "Pytanie bez wizualizacji",
"categoryWord": "Kategoria",
"anAnomalyHasOccured": "Nastąpiła anomalia",
"redirectFrom": "Przekierowanie z",
"end": "Koniec",
"question": "Pytanie",
"anAPIErrorOccured": "Wystąpił błąd z API",
"positive": "pozytywny",
"negative": "negatywny",
"theoreticalExam": "Egzamin teorytyczny",
"category": {
"description": {
"A": "motocykle bez ograniczeń mocy",
"B": "⭐ samochody osobowe do 3,5 t",
"C": "pojazdy ciężarowe powyżej 3,5 t",
"D": "autobusy",
"T": "ciągniki rolnicze i pojazdy wolnobieżne",
"AM": "motorowery i lekkie czterokołowce",
"A1": "motocykle do 125 cm³ i 11 kW",
"A2": "motocykle do 35 kW",
"B1": "czterokołowce (np. quady)",
"C1": "pojazdy od 3,5 t do 7,5 t",
"D1": "autobusy do 16 pasażerów",
"PT": "tramwaje"
},
"age": {
"A": "(24 lata; lub 20 lat jeśli masz kat. A2 min. 2 lata)",
"B": "(18 lat)",
"C": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"D": "(24 lata; lub 21 lat z kwalifikacją wstępną)",
"T": "(16 lat)",
"AM": "(14 lat)",
"A1": "(16 lat)",
"A2": "(18 lat)",
"B1": "(16 lat)",
"C1": "(18 lat)",
"D1": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"PT": "(21 lat)"
}
}
}

View file

@ -1,73 +0,0 @@
{
"mainTitle": "Test na prawo jazdy",
"loading": "Ładowanie",
"keybinds": "Skróty klawiszowe",
"bindedKeys": {
"S": "niebieski przycisk start",
"D": "następne pytanie",
"X": "zakończ egzamin",
"T / Y": "Tak",
"N": "Nie",
"A": "A",
"B": "B",
"C": "C"
},
"endExam": "Zakończ egzamin",
"examEnd": "Koniec egzaminu",
"basicQuestions": "Pytania podstawowe",
"advancedQuestions": "Pytania specjalistyczne",
"timeToGetAcquaintedWithTheQuestion": "Czas na zapoznanie się z pytaniem",
"timeForAnswer": "Czas na udzielenie odpowiedzi",
"startBtn": "START",
"second": "s",
"nextQuestion": "Następne pytanie",
"goBackToHomePage": "Wróć na stronę główną",
"points": "Punkty",
"pointValue": "Wartość punktowa",
"currentCategory": "Aktualna kategoria",
"timeToExamEnd": "Czas do końca egzaminu",
"result": "Wynik",
"startAgain": "Rozpocznij jeszcze raz",
"viewAnswers": "Przejrzyj odpowiedzi",
"doYouReallyWantToEndExam": "Czy na pewno chcesz zakończyć egzamin?",
"questionWithoutVisual": "Pytanie bez wizualizacji",
"categoryWord": "Kategoria",
"anAnomalyHasOccured": "Nastąpiła anomalia",
"redirectFrom": "Przekierowanie z",
"end": "Koniec",
"question": "Pytanie",
"anAPIErrorOccured": "Wystąpił błąd z API",
"positive": "pozytywny",
"negative": "negatywny",
"theoreticalExam": "Egzamin teorytyczny",
"category": {
"description": {
"A": "motocykle bez ograniczeń mocy",
"B": "⭐ samochody osobowe do 3,5 t",
"C": "pojazdy ciężarowe powyżej 3,5 t",
"D": "autobusy",
"T": "ciągniki rolnicze i pojazdy wolnobieżne",
"AM": "motorowery i lekkie czterokołowce",
"A1": "motocykle do 125 cm³ i 11 kW",
"A2": "motocykle do 35 kW",
"B1": "czterokołowce (np. quady)",
"C1": "pojazdy od 3,5 t do 7,5 t",
"D1": "autobusy do 16 pasażerów",
"PT": "tramwaje"
},
"age": {
"A": "(24 lata; lub 20 lat jeśli masz kat. A2 min. 2 lata)",
"B": "(18 lat)",
"C": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"D": "(24 lata; lub 21 lat z kwalifikacją wstępną)",
"T": "(16 lat)",
"AM": "(14 lat)",
"A1": "(16 lat)",
"A2": "(18 lat)",
"B1": "(16 lat)",
"C1": "(18 lat)",
"D1": "(21 lat; lub 18 lat z kwalifikacją wstępną)",
"PT": "(21 lat)"
}
}
}

View file

@ -9,7 +9,6 @@ export default defineNuxtConfig({
'pinia-plugin-persistedstate/nuxt', 'pinia-plugin-persistedstate/nuxt',
'@nuxt/eslint', '@nuxt/eslint',
'@nuxt/image', '@nuxt/image',
'@nuxtjs/i18n',
], ],
ssr: false, ssr: false,
imports: { imports: {
@ -36,15 +35,6 @@ export default defineNuxtConfig({
}, },
}, },
}, },
i18n: {
locales: [
{ code: 'pl', language: 'pl-PL', file: 'pl.json' },
{ code: 'en', language: 'en-GB', file: 'en.json' },
{ code: 'de', language: 'de-DE', file: 'de.json' },
{ code: 'ua', language: 'uk-UK', file: 'ua.json' },
],
defaultLocale: 'pl',
},
image: { image: {
providers: { providers: {
selfhost: { selfhost: {

View file

@ -17,7 +17,6 @@
"@libsql/client": "^0.15.15", "@libsql/client": "^0.15.15",
"@nuxt/fonts": "0.11.1", "@nuxt/fonts": "0.11.1",
"@nuxt/image": "1.10.0", "@nuxt/image": "1.10.0",
"@nuxtjs/i18n": "10.2.1",
"@nuxtjs/tailwindcss": "6.13.2", "@nuxtjs/tailwindcss": "6.13.2",
"@pinia/nuxt": "0.11.0", "@pinia/nuxt": "0.11.0",
"@vueuse/core": "^14.1.0", "@vueuse/core": "^14.1.0",
@ -34,7 +33,6 @@
"pinia-plugin-persistedstate": "^4.7.1", "pinia-plugin-persistedstate": "^4.7.1",
"ufo": "^1.6.1", "ufo": "^1.6.1",
"vue": "latest", "vue": "latest",
"vue-country-flag-next": "^2.3.2",
"vue-router": "latest" "vue-router": "latest"
}, },
"packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af", "packageManager": "pnpm@10.4.1+sha512.c753b6c3ad7afa13af388fa6d808035a008e30ea9993f58c6663e2bc5ff21679aa834db094987129aa4d488b86df57f7b634981b2f827cdcacc698cc0cfb88af",

View file

@ -6,20 +6,17 @@ const advancedStore = useAdvancedStore();
<template> <template>
<div class="flex flex-col gap-2 items-start m-2"> <div class="flex flex-col gap-2 items-start m-2">
<h1 class="text-2xl">{{ $t('anAnomalyHasOccured') }}</h1> <h1 class="text-2xl">Nastąpiła anomalia</h1>
<br /> <br />
{{ $t('redirectFrom') }}: {{ useRoute().redirectedFrom ?? '""' }} <br /> Przekierowanie z: {{ useRoute().redirectedFrom ?? '""' }} <br />
{{ $t('categoryWord') }}: Kategoria:
{{ examStore.category != '' ? examStore.category : '""' }} {{ examStore.category != '' ? examStore.category : '""' }}
<br /> <br />
{{ $t('end') }}: {{ examStore.end }} <br /> Koniec: {{ examStore.end }} <br />
{{ $t('basicQuestions') }}: Pytania podstawowe: <code class="text-xs">{{ basicStore.basic }}</code>
<code class="text-xs">{{ basicStore.basic }}</code>
<br /> <br />
{{ $t('advancedQuestions') }}: Pytania specjalistyczne:
<code class="text-xs">{{ advancedStore.advanced }}</code> <br /> <code class="text-xs">{{ advancedStore.advanced }}</code> <br />
<NuxtLink to="/" class="btn btn-primary"> <NuxtLink to="/" class="btn btn-primary"> Wróć na stronę główną </NuxtLink>
{{ $t('goBackToHomePage') }}
</NuxtLink>
</div> </div>
</template> </template>

View file

@ -80,7 +80,7 @@ function clickNext() {
onMounted(() => { onMounted(() => {
useHead({ useHead({
title: `${$t('question')} 1/20`, title: 'Pytanie 1/20',
}); });
window.addEventListener('beforeunload', preventRefresh); window.addEventListener('beforeunload', preventRefresh);
@ -90,9 +90,9 @@ onMounted(() => {
watchEffect(() => { watchEffect(() => {
if (now.value === 'basic') if (now.value === 'basic')
useHead({ title: `${$t('question')} ${countBasic.value + 1}/20` }); useHead({ title: `Pytanie ${countBasic.value + 1}/20` });
if (now.value === 'advanced') if (now.value === 'advanced')
useHead({ title: `${$t('question')} ${countAdvanced.value + 1}/12` }); useHead({ title: `Pytanie ${countAdvanced.value + 1}/12` });
}); });
watchEffect(() => { watchEffect(() => {
@ -257,10 +257,7 @@ const showEndModal = ref(false);
</div> </div>
</div> </div>
<div v-else-if="statusBasic === 'error' || statusAdvanced === 'error'"> <div v-else-if="statusBasic === 'error' || statusAdvanced === 'error'">
{{ $t('anAPIErrorOccured') }}:<br /> An API error occurred: {{ errorBasic }} {{ errorAdvanced }}
<code class="text-sm">{{ errorBasic }}</code>
<br />
<code class="text-sm">{{ errorAdvanced }}</code>
</div> </div>
<LoadingScreen v-else /> <LoadingScreen v-else />
<EndModal <EndModal

View file

@ -1,15 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import CountryFlag from 'vue-country-flag-next'; import categories, { opis, wiek } from '~/categories';
import categories from '~/categories';
onMounted(() => { onMounted(() => {
useHead({ useHead({
title: $t('mainTitle'), title: 'Test na prawo jazdy',
}); });
}); });
const { setLocale } = useI18n();
const loading = ref(false); const loading = ref(false);
const examStore = useExamStore(); const examStore = useExamStore();
@ -24,37 +21,17 @@ function setAndGo(category: string) {
} }
} }
} }
const langSelect = ref(examStore.lang);
function changeLanguage() {
examStore.setLang(langSelect.value);
setLocale(langSelect.value as 'pl' | 'en' | 'de' | 'ua');
}
</script> </script>
<template> <template>
<div> <div>
<div v-if="!loading" class="text-3xl m-2 flex flex-col gap-2"> <div v-if="!loading" class="text-3xl m-2 flex flex-col gap-2">
<span>{{ $t('mainTitle') }}</span> <span>Test na prawo jazdy</span>
<div class="flex gap-2">
<CountryFlag
class="block border border-1 border-black"
:country="langSelect != 'en' ? langSelect : 'gb'"
size="big"
/>
<select v-model="langSelect" class="select" @change="changeLanguage">
<option value="pl">Polish (Polski)</option>
<option value="en">English</option>
<option value="de">German (Deutsch)</option>
<option value="ua">Ukrainian (Українська)</option>
</select>
</div>
<div <div
class="flex flex-col flex-wrap gap-2 items-start p-4 bg-slate-100 border-1 border-slate-500 rounded-xl w-fit" class="flex flex-col flex-wrap gap-2 items-start p-4 bg-slate-100 border-1 border-slate-500 rounded-xl w-fit"
> >
<div <div
v-for="category in categories" v-for="[index, category] of categories.entries()"
:key="`btn-${category}`" :key="`btn-${category}`"
class="flex flex-row gap-3 items-center" class="flex flex-row gap-3 items-center"
> >
@ -62,8 +39,8 @@ function changeLanguage() {
{{ category }} {{ category }}
</button> </button>
<div class="flex flex-col text-sm"> <div class="flex flex-col text-sm">
<div>{{ $t(`category.description.${category}`) }}</div> <div>{{ opis[index] }}</div>
<div>{{ $t(`category.age.${category}`) }}</div> <div>{{ wiek[index] }}</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -23,9 +23,7 @@ advancedStore.advanced.forEach((answer) => {
} }
}); });
const resultTrueFalse = ref( const resultTrueFalse = ref(points.value >= 68 ? 'pozytywny' : 'negatywny');
points.value >= 68 ? $t('positive') : $t('negative'),
);
onMounted(() => { onMounted(() => {
useHead({ useHead({
@ -107,7 +105,7 @@ async function home() {
<LoadingScreen v-if="loading" /> <LoadingScreen v-if="loading" />
<div v-else> <div v-else>
<ResultModal @again="again" @home="home"> <ResultModal @again="again" @home="home">
<template #title>{{ $t('theoreticalExam') }}</template> <template #title>Egzamin teorytyczny</template>
<template #category>{{ examStore.category }}</template> <template #category>{{ examStore.category }}</template>
<template #points>{{ points }}</template> <template #points>{{ points }}</template>
<template #resultTrueFalse>{{ resultTrueFalse }} </template> <template #resultTrueFalse>{{ resultTrueFalse }} </template>

1694
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,6 @@ export const useExamStore = defineStore('examStore', {
state: () => ({ state: () => ({
category: '', category: '',
end: false, end: false,
lang: 'pl',
}), }),
actions: { actions: {
async setCategory(category: string) { async setCategory(category: string) {
@ -39,9 +38,6 @@ export const useExamStore = defineStore('examStore', {
async setEnd(end: boolean) { async setEnd(end: boolean) {
this.end = end; this.end = end;
}, },
async setLang(lang: string) {
this.lang = lang;
},
async mildReset() { async mildReset() {
this.end = false; this.end = false;
useBasicStore().set([]); useBasicStore().set([]);