✨ Added practice-mode
This commit is contained in:
+15
-15
@@ -18,19 +18,19 @@
|
|||||||
"@felte/reporter-tippy": "^1.1.3",
|
"@felte/reporter-tippy": "^1.1.3",
|
||||||
"@felte/validator-yup": "^1.0.9",
|
"@felte/validator-yup": "^1.0.9",
|
||||||
"@fontsource/marck-script": "^4.5.10",
|
"@fontsource/marck-script": "^4.5.10",
|
||||||
"@sentry/browser": "^7.11.1",
|
"@sentry/browser": "^7.13.0",
|
||||||
"@sentry/tracing": "^7.11.1",
|
"@sentry/tracing": "^7.13.0",
|
||||||
"@sveltejs/adapter-auto": "next",
|
"@sveltejs/adapter-auto": "next",
|
||||||
"@sveltejs/adapter-node": "^1.0.0-next.86",
|
"@sveltejs/adapter-node": "^1.0.0-next.92",
|
||||||
"@sveltejs/kit": "next",
|
"@sveltejs/kit": "next",
|
||||||
"@tailwindcss/typography": "^0.5.4",
|
"@tailwindcss/typography": "^0.5.7",
|
||||||
"@types/cookie": "^0.5.1",
|
"@types/cookie": "^0.5.1",
|
||||||
"@types/js-cookie": "^3.0.2",
|
"@types/js-cookie": "^3.0.2",
|
||||||
"@types/luxon": "^2.4.0",
|
"@types/luxon": "^2.4.0",
|
||||||
"@types/ua-parser-js": "^0.7.36",
|
"@types/ua-parser-js": "^0.7.36",
|
||||||
"@types/yup": "^0.29.14",
|
"@types/yup": "^0.29.14",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.33.1",
|
"@typescript-eslint/eslint-plugin": "^5.37.0",
|
||||||
"@typescript-eslint/parser": "^5.33.1",
|
"@typescript-eslint/parser": "^5.37.0",
|
||||||
"@uppy/compressor": "^0.3.3",
|
"@uppy/compressor": "^0.3.3",
|
||||||
"@uppy/core": "^2.3.3",
|
"@uppy/core": "^2.3.3",
|
||||||
"@uppy/dashboard": "^2.4.2",
|
"@uppy/dashboard": "^2.4.2",
|
||||||
@@ -38,11 +38,11 @@
|
|||||||
"@uppy/image-editor": "^1.4.2",
|
"@uppy/image-editor": "^1.4.2",
|
||||||
"@uppy/svelte": "^1.0.9",
|
"@uppy/svelte": "^1.0.9",
|
||||||
"@uppy/xhr-upload": "^2.1.3",
|
"@uppy/xhr-upload": "^2.1.3",
|
||||||
"autoprefixer": "^10.4.8",
|
"autoprefixer": "^10.4.11",
|
||||||
"cookie": "^0.5.0",
|
"cookie": "^0.5.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"cssnano": "^5.1.13",
|
"cssnano": "^5.1.13",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.23.1",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-svelte3": "^4.0.0",
|
"eslint-plugin-svelte3": "^4.0.0",
|
||||||
"felte": "^1.2.3",
|
"felte": "^1.2.3",
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
"i18next-browser-languagedetector": "^6.1.5",
|
"i18next-browser-languagedetector": "^6.1.5",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"luxon": "^2.5.0",
|
"luxon": "^2.5.0",
|
||||||
"mapbox-gl": "^2.9.2",
|
"mapbox-gl": "^2.10.0",
|
||||||
"minisearch": "^5.0.0",
|
"minisearch": "^5.0.0",
|
||||||
"plausible-tracker": "^0.3.8",
|
"plausible-tracker": "^0.3.8",
|
||||||
"postcss": "^8.4.16",
|
"postcss": "^8.4.16",
|
||||||
@@ -58,20 +58,20 @@
|
|||||||
"postcss-load-config": "^4.0.1",
|
"postcss-load-config": "^4.0.1",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"prettier-plugin-svelte": "^2.7.0",
|
"prettier-plugin-svelte": "^2.7.0",
|
||||||
"sass": "^1.54.4",
|
"sass": "^1.54.9",
|
||||||
"socket.io-client": "^4.5.1",
|
"socket.io-client": "^4.5.2",
|
||||||
"svelte": "^3.49.0",
|
"svelte": "^3.50.1",
|
||||||
"svelte-check": "^2.8.1",
|
"svelte-check": "^2.9.0",
|
||||||
"svelte-preprocess": "^4.10.7",
|
"svelte-preprocess": "^4.10.7",
|
||||||
"svelte-range-slider-pips": "^2.0.3",
|
"svelte-range-slider-pips": "^2.0.3",
|
||||||
"svelte-tippy": "^1.3.2",
|
"svelte-tippy": "^1.3.2",
|
||||||
"swiper": "^8.3.2",
|
"swiper": "^8.4.2",
|
||||||
"tailwindcss": "^3.1.8",
|
"tailwindcss": "^3.1.8",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"tslib": "^2.4.0",
|
"tslib": "^2.4.0",
|
||||||
"typescript": "~4.7.4",
|
"typescript": "~4.7.4",
|
||||||
"ua-parser-js": "^1.0.2",
|
"ua-parser-js": "^1.0.2",
|
||||||
"vite": "^3.0.8",
|
"vite": "^3.1.1",
|
||||||
"vite-plugin-iso-import": "^0.1.3",
|
"vite-plugin-iso-import": "^0.1.3",
|
||||||
"yup": "^0.32.11"
|
"yup": "^0.32.11"
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+367
-355
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
|||||||
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
import { Map, Marker } from '@beyonk/svelte-mapbox';
|
import { Map, Marker } from '@beyonk/svelte-mapbox';
|
||||||
|
|
||||||
export let lng: number;
|
export let lng: number;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
export let languages: Array<{
|
export let languages: Array<{
|
||||||
flag: string;
|
flag: string;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
import { signedIn, pathname } from '$lib/stores';
|
import { signedIn, pathname } from '$lib/stores';
|
||||||
import { createTippy } from 'svelte-tippy';
|
import { createTippy } from 'svelte-tippy';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
const tippy = createTippy({
|
const tippy = createTippy({
|
||||||
arrow: true,
|
arrow: true,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { socket } from '$lib/socket';
|
import { socket } from '$lib/socket';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
import { alertModal } from '../stores';
|
import { alertModal } from '../stores';
|
||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<!--
|
||||||
|
- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import type { Question } from '$lib/quiz_types';
|
||||||
|
import { fly } from 'svelte/transition';
|
||||||
|
import { getLocalization } from '$lib/i18n';
|
||||||
|
|
||||||
|
export let question: Question;
|
||||||
|
|
||||||
|
const { t } = getLocalization();
|
||||||
|
|
||||||
|
let selected_question = undefined;
|
||||||
|
let timer_res = question.time;
|
||||||
|
let show_results = false;
|
||||||
|
|
||||||
|
// Stop the timer if the question is answered
|
||||||
|
const timer = (time: string) => {
|
||||||
|
let seconds = Number(time);
|
||||||
|
let timer_interval = setInterval(() => {
|
||||||
|
if (timer_res === '0') {
|
||||||
|
clearInterval(timer_interval);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
seconds--;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_res = seconds.toString();
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
timer(question.time);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="w-full px-6 lg:px-20 h-[80vh] absolute" in:fly={{ x: 100 }} out:fly={{ x: -100 }}>
|
||||||
|
<h1 class="text-3xl text-center">{question.question}</h1>
|
||||||
|
{#if question.image !== null}
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src={question.image}
|
||||||
|
class="max-h-[40vh] object-cover mx-auto mb-8 w-auto"
|
||||||
|
alt="Content for Question"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<p class="text-center">{timer_res}</p>
|
||||||
|
{#if show_results}
|
||||||
|
<div>
|
||||||
|
{#each question.answers as answer, i}
|
||||||
|
<button
|
||||||
|
disabled
|
||||||
|
class:bg-green-500={question.answers[i].right}
|
||||||
|
class:bg-red-500={!question.answers[i].right}
|
||||||
|
class="p-2 rounded-lg flex justify-center w-full transition my-5"
|
||||||
|
>{answer.answer}</button
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div>
|
||||||
|
{#each question.answers as answer, i}
|
||||||
|
<button
|
||||||
|
disabled={selected_question !== undefined || timer_res === '0'}
|
||||||
|
class="p-2 rounded-lg flex justify-center w-full transition bg-amber-300 my-5 disabled:grayscale"
|
||||||
|
on:click={() => {
|
||||||
|
selected_question = i;
|
||||||
|
timer_res = '0';
|
||||||
|
}}>{answer.answer}</button
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
{#if timer_res === '0'}
|
||||||
|
<button
|
||||||
|
class="bg-orange-500 p-2 rounded-lg flex justify-center w-full transition my-5"
|
||||||
|
on:click={() => {
|
||||||
|
show_results = true;
|
||||||
|
}}>{$t('admin_page.get_results')}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<!--
|
||||||
|
- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { getLocalization } from '$lib/i18n';
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
import { fly } from 'svelte/transition';
|
||||||
|
|
||||||
|
const { t } = getLocalization();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="w-full px-6 lg:px-20 h-[80vh] absolute" in:fly={{ x: 100 }} out:fly={{ x: -100 }}>
|
||||||
|
<div class="rounded-lg bg-white w-full h-full border-gray-500 dark:bg-gray-700">
|
||||||
|
<div class="h-fit bg-gray-300 rounded-t-lg dark:bg-gray-500">
|
||||||
|
<div class="flex align-middle p-4 gap-3">
|
||||||
|
<span
|
||||||
|
class="inline-block bg-gray-600 w-4 h-4 rounded-full hover:bg-red-400 transition"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="inline-block bg-gray-600 w-4 h-4 rounded-full hover:bg-yellow-400 transition"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="inline-block bg-gray-600 w-4 h-4 rounded-full hover:bg-green-400 transition"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dark:bg-gray-700">
|
||||||
|
<div class="flex justify-center pt-10 w-full">
|
||||||
|
<p
|
||||||
|
class="p-3 rounded-lg border-gray-500 border text-center w-11/12 lg:w-1/3 text-lg font-semibold dark:bg-gray-500"
|
||||||
|
>
|
||||||
|
{data.title}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center pt-10 w-full max-h-32">
|
||||||
|
<p
|
||||||
|
class="p-3 rounded-lg border-gray-500 border text-center w-11/12 lg:w-1/3 h-20 resize-none dark:bg-gray-500"
|
||||||
|
>
|
||||||
|
{data.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if data.cover_image != undefined && data.cover_image !== ''}
|
||||||
|
<div class="flex justify-center pt-10 w-full max-h-72 w-full">
|
||||||
|
<img
|
||||||
|
src={data.cover_image}
|
||||||
|
alt="not available"
|
||||||
|
class="max-h-72 h-auto w-auto"
|
||||||
|
on:contextmenu|preventDefault={() => {
|
||||||
|
data.cover_image = '';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="pt-10 w-full flex justify-center">
|
||||||
|
{#if data.public}
|
||||||
|
<svg
|
||||||
|
class="w-8 h-8 inline-block"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>{$t('words.public')}</span>
|
||||||
|
{:else}
|
||||||
|
<svg
|
||||||
|
class="w-8 h-8 inline-block"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>{$t('words.private')}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
import { BrowserTracing } from '@sentry/tracing';
|
import { BrowserTracing } from '@sentry/tracing';
|
||||||
import { initLocalizationContext } from '$lib/i18n';
|
import { initLocalizationContext } from '$lib/i18n';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
import Alert from '$lib/modals/alert.svelte';
|
import Alert from '$lib/modals/alert.svelte';
|
||||||
|
|
||||||
/* afterNavigate(() => {
|
/* afterNavigate(() => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
import { navbarVisible } from '$lib/stores';
|
import { navbarVisible } from '$lib/stores';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
import Footer from '$lib/footer.svelte';
|
import Footer from '$lib/footer.svelte';
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
import { navbarVisible } from '$lib/stores';
|
import { navbarVisible } from '$lib/stores';
|
||||||
import type { PlayerAnswer, Player } from '$lib/admin.ts';
|
import type { PlayerAnswer, Player } from '$lib/admin.ts';
|
||||||
import SomeAdminScreen from '$lib/admin.svelte';
|
import SomeAdminScreen from '$lib/admin.svelte';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
navbarVisible.set(false);
|
navbarVisible.set(false);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<!--
|
||||||
|
- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import type { QuizData } from '$lib/quiz_types';
|
||||||
|
import Spinner from '$lib/Spinner.svelte';
|
||||||
|
import TitleScreen from '$lib/practice/title_screen.svelte';
|
||||||
|
import Question from '$lib/practice/question.svelte';
|
||||||
|
|
||||||
|
let quiz: QuizData;
|
||||||
|
let unique = {};
|
||||||
|
|
||||||
|
let selected_question = -1;
|
||||||
|
|
||||||
|
const get_quiz = async () => {
|
||||||
|
const res = await fetch(`/api/v1/quiz/get/public/${$page.url.searchParams.get('quiz_id')}`);
|
||||||
|
quiz = await res.json();
|
||||||
|
return quiz;
|
||||||
|
};
|
||||||
|
const reload_q = () => {
|
||||||
|
unique = {};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#await get_quiz()}
|
||||||
|
<Spinner />
|
||||||
|
{:then q}
|
||||||
|
<div class="h-full overflow-hidden">
|
||||||
|
{#if selected_question === -1}
|
||||||
|
<TitleScreen bind:data={quiz} />
|
||||||
|
{:else}
|
||||||
|
{#key unique}
|
||||||
|
<Question bind:question={quiz.questions[selected_question]} />
|
||||||
|
{/key}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 h-fit px-20 mt-6 absolute bottom-0 w-full">
|
||||||
|
<button
|
||||||
|
class="flex justify-start transition-all disabled:opacity-60"
|
||||||
|
disabled={selected_question <= -1}
|
||||||
|
on:click={() => {
|
||||||
|
selected_question -= 1;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="w-16 h-16"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M15 19l-7-7 7-7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="flex justify-end transition-all disabled:opacity-60"
|
||||||
|
disabled={selected_question >= quiz.questions.length - 1}
|
||||||
|
on:click={() => {
|
||||||
|
reload_q();
|
||||||
|
selected_question += 1;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="w-16 h-16"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9 5l7 7-7 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/await}
|
||||||
Reference in New Issue
Block a user