Further cleanup, mostly with svelte 5 migration placeholder cleanup

This commit is contained in:
Mawoka
2025-10-26 11:53:53 +01:00
parent 0c23d9b9c1
commit 41fe3e3ad5
74 changed files with 309 additions and 1154 deletions
+1 -62
View File
@@ -9,8 +9,7 @@ SPDX-License-Identifier: MPL-2.0
import Navbar from '$lib/navbar.svelte';
import { pathname } from '$lib/stores';
import { navbarVisible } from '$lib/stores.svelte';
// import * as Sentry from '@sentry/browser';
// import { BrowserTracing } from '@sentry/tracing';
import { initLocalizationContext } from '$lib/i18n';
import { browser } from '$app/environment';
import CommandPalette from '$lib/components/commandpalette.svelte';
@@ -19,19 +18,6 @@ SPDX-License-Identifier: MPL-2.0
}
let { children }: Props = $props();
// import Alert from '$lib/modals/alert.svelte';
/* afterNavigate(() => {
if (browser) {
if (latestPageVisitURl === window.location.href) {
return;
} else {
latestPageVisitURl = window.location.href;
plausible.trackPageview();
}
console.log('After nav');
}
});*/
const plausible_data_url = import.meta.env.VITE_PLAUSIBLE_DATA_URL;
if (browser) {
@@ -45,34 +31,12 @@ SPDX-License-Identifier: MPL-2.0
} else {
document.documentElement.classList.remove('dark');
}
// Whenever the user explicitly chooses light mode
// localStorage.theme = 'light';
//
// // Whenever the user explicitly chooses dark mode
// localStorage.theme = 'dark';
//
// // Whenever the user explicitly chooses to respect the OS preference
// localStorage.removeItem('theme');
}
let start_language = 'en';
if (browser) {
start_language = localStorage.getItem('language') ?? 'en';
}
initLocalizationContext(start_language);
/*
if (import.meta.env.VITE_SENTRY !== undefined && import.meta.env.PROD) {
Sentry.init({
dsn: String(import.meta.env.VITE_SENTRY),
integrations: [new BrowserTracing()],
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 0.5
});
}
*/
</script>
<svelte:head>
@@ -92,40 +56,15 @@ SPDX-License-Identifier: MPL-2.0
{/if}
</svelte:head>
<!-- {#if navbarVisible.visible = true.visible}
<Navbar />
<div class="pt-16 h-screen">
<div class="z-40"></div>
<slot />
</div>
{:else}
<slot />
{/if} -->
{#if navbarVisible.visible}
<Navbar />
<div class="pt-16">
<div class="z-40"></div>
<!-- extra content above slot -->
</div>
{/if}
{@render children?.()}
<CommandPalette />
<!--{#if $alertModal.open ?? false}
<div
class="fixed inset-0 h-screen w-screen bg-black z-30 bg-opacity-60 items-center justify-center content-center"
class:hidden={!$alertModal.open}
class:flex={$alertModal.open}
class:visible={$alertModal.open}
>
<Alert
bind:title={$alertModal.title}
bind:body={$alertModal.body}
bind:open={$alertModal.open}
/>
</div>
{/if}-->
<style lang="scss">
:global(html:not(.dark)) {
// height: 100%;
-1
View File
@@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: MPL-2.0
// import { redirect } from '@sveltejs/kit';
import { signedIn } from '$lib/stores';
import type { LayoutLoad } from './$types';
+2 -1
View File
@@ -3,8 +3,9 @@
// SPDX-License-Identifier: MPL-2.0
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = async ({ parent }) => {
export const load: PageServerLoad = async ({ parent }) => {
const { email } = await parent();
if (email) {
redirect(302, '/dashboard');
+17 -111
View File
@@ -13,8 +13,6 @@ SPDX-License-Identifier: MPL-2.0
import Newsletter from '$lib/landing/newsletter.svelte';
import { fly, fade } from 'svelte/transition';
/* import LandingPromo from '$lib/landing/landing-promo.svelte';*/
import FindScreenshot from '$lib/assets/landing_new/find.webp';
import ImportScreenshot from '$lib/assets/landing_new/import.webp';
import EditScreenshot from '$lib/assets/landing_new/edit.webp';
@@ -27,16 +25,7 @@ SPDX-License-Identifier: MPL-2.0
navbarVisible.visible = true;
/* interface StatsData {
quiz_count: number;
user_count: number;
}*/
/* const getStats = async (): Promise<StatsData> => {
const response = await fetch('/api/v1/stats/combined');
return await response.json();
};*/
let newsletterModalOpen = $state();
let newsletterModalOpen: boolean = $state();
onMount(() => {
const ls = localStorage.getItem('newsletter');
newsletterModalOpen = ls === null;
@@ -65,18 +54,6 @@ SPDX-License-Identifier: MPL-2.0
let selected_create_thing = $state(SelectedCreateThing.Create);
let selected_play_thing = $state(SelectedPlayThing.Select);
/* <li>No;
Tracking < /li>
< li > Self - hostable < /li>
< li > German;
Server < /li>
< li > user - friendly < /li>
< li > Completely;
free < /li>
< li > Quiz - results;
are;
downloadable < /li>;*/
const classquiz_reasons = [
{
headline: $t('index_page.no_player_limit'),
@@ -154,57 +131,6 @@ SPDX-License-Identifier: MPL-2.0
/>
<meta name="twitter:image" content={WebPOpenGraph} />
</svelte:head>
<!--<div class="min-h-screen flex flex-col">
<section class="pb-40">
<div class="pt-12 text-center">
<h1 class="sm:text-8xl text-6xl mt-6 marck-script">ClassQuiz</h1>
<p class="text-xl mt-4">{$t('index_page.slogan')}</p>
</div>
</section>
<section id="features" class="mt-8">
<div class="text-center snap-y">
<h1 class="sm:text-6xl text-4xl">{$t('words.features')}</h1>
<p class="text-xl pt-4">
{$t('index_page.features_description.1')}
<br />
{$t('index_page.features_description.2')}
<br />
{$t('index_page.features_description.3')}
</p>
</div>
</section>
<section class="py-8">
<h1 class="sm:text-6xl text-4xl text-center break-words">
{$t('words.screenshot', { count: 2 })}
</h1>
<div>
<LandingPromo />
</div>
</section>
<section>
<h1 class="sm:text-6xl text-4xl text-center">Testimonials</h1>
{#await import('$lib/landing/testimonials.svelte') then testimonials}
<svelte:component this={testimonials.default} />
{/await}
</section>
<section id="stats">
<div class="text-center pb-20 pt-10 snap-y">
<h1 class="sm:text-6xl text-4xl">{$t('words.stats')}</h1>
<p class="text-xl pt-4">
{#await getStats() then stats}
{$t('index_page.stats', {
user_count: stats.user_count,
quiz_count: stats.quiz_count
})}
{/await}
</p>
</div>
</section>
</div>-->
<div class="min-h-screen flex flex-col">
<section class="pb-40">
<div class="pt-12 text-center">
@@ -264,6 +190,8 @@ SPDX-License-Identifier: MPL-2.0
}}
class:shadow-2xl={selected_create_thing === SelectedCreateThing.Create}
class:opacity-70={selected_create_thing !== SelectedCreateThing.Create}
role="button"
tabindex="0"
>
<div
class="rounded-lg w-fit p-1 bg-lime-500 hover:bg-lime-400 transition shadow-lg"
@@ -295,6 +223,8 @@ SPDX-License-Identifier: MPL-2.0
onkeyup={() => {
selected_create_thing = SelectedCreateThing.Find;
}}
role="button"
tabindex="0"
class:shadow-2xl={selected_create_thing === SelectedCreateThing.Find}
class:opacity-70={selected_create_thing !== SelectedCreateThing.Find}
>
@@ -320,38 +250,6 @@ SPDX-License-Identifier: MPL-2.0
<h5 class="text-xl dark:text-black">{$t('words.find')}</h5>
<p class="dark:text-black">{$t('index_page.find_or_explore')}</p>
</div>
<!--<div
class="m-2 rounded-lg p-2 bg-opacity-40 bg-white transition-all cursor-pointer lg:h-full"
onclick={() => {
selected_create_thing = SelectedCreateThing.Import;
}}
class:shadow-2xl={selected_create_thing === SelectedCreateThing.Import}
class:opacity-70={selected_create_thing !== SelectedCreateThing.Import}
>
<div
class="rounded-lg w-fit p-1 bg-lime-500 hover:bg-lime-400 transition shadow-lg"
>
<svg
class="w-8 h-8 text-black"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-label="Cloud with arrow pointing down"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10"
/>
</svg>
</div>
<h5 class="text-xl dark:text-black">{$t('words.import')}</h5>
<p class="dark:text-black">
{$t('index_page.import_quiz_from_kahoot_and_edit')}
</p>
</div>-->
</div>
</div>
</section>
@@ -405,11 +303,13 @@ SPDX-License-Identifier: MPL-2.0
onkeyup={() => {
selected_play_thing = SelectedPlayThing.Select;
}}
role="button"
tabindex="0"
class:shadow-2xl={selected_play_thing === SelectedPlayThing.Select}
class:opacity-70={selected_play_thing !== SelectedPlayThing.Select}
>
<div
class="rounded-lg bg-emerald-300 w-fit p-1 bg-lime-500 hover:bg-lime-400 transition shadow-lg"
class="rounded-lg bg-emerald-300 w-fit p-1 hover:bg-lime-400 transition shadow-lg"
>
<svg
aria-label="Mouse-Click icon"
@@ -432,6 +332,8 @@ SPDX-License-Identifier: MPL-2.0
</div>
<div
class="m-2 rounded-lg p-2 bg-white/40 transition-all cursor-pointer lg:h-full"
role="button"
tabindex="0"
onclick={() => {
selected_play_thing = SelectedPlayThing.Results;
}}
@@ -442,7 +344,7 @@ SPDX-License-Identifier: MPL-2.0
class:opacity-70={selected_play_thing !== SelectedPlayThing.Results}
>
<div
class="rounded-lg bg-emerald-300 w-fit p-1 bg-lime-500 hover:bg-lime-400 transition shadow-lg"
class="rounded-lg bg-emerald-300 w-fit p-1 hover:bg-lime-400 transition shadow-lg"
>
<svg
aria-label="context-menu icon"
@@ -465,6 +367,8 @@ SPDX-License-Identifier: MPL-2.0
</div>
<div
class="m-2 rounded-lg p-2 bg-white/40 transition-all cursor-pointer lg:h-full"
role="button"
tabindex="0"
onclick={() => {
selected_play_thing = SelectedPlayThing.Winners;
}}
@@ -475,7 +379,7 @@ SPDX-License-Identifier: MPL-2.0
class:opacity-70={selected_play_thing !== SelectedPlayThing.Winners}
>
<div
class="rounded-lg bg-emerald-300 w-fit p-1 bg-lime-500 hover:bg-lime-400 transition shadow-lg"
class="rounded-lg bg-emerald-300 w-fit p-1 hover:bg-lime-400 transition shadow-lg"
>
<svg
aria-label="sparkling stars-icon"
@@ -523,6 +427,8 @@ SPDX-License-Identifier: MPL-2.0
{#each classquiz_reasons as reason, index}
<div
class="m-2 rounded-lg p-2 bg-white/40 transition-all cursor-pointer lg:h-full"
role="button"
tabindex="0"
onclick={() => {
selected_classquiz_reason = index;
}}
@@ -541,7 +447,7 @@ SPDX-License-Identifier: MPL-2.0
</div>
{#if newsletterModalOpen}
<div
class="fixed bottom-8 right-5 bg-white rounded-lg h-fit w-11/12 ml-5 lg:w-2/12 z-50 p-2 bg-white dark:bg-gray-700"
class="fixed bottom-8 right-5 bg-white rounded-lg h-fit w-11/12 ml-5 lg:w-2/12 z-50 p-2 dark:bg-gray-700"
transition:fly|global
>
<Newsletter bind:open={newsletterModalOpen} />
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { goto } from '$app/navigation';
import type { PageData } from './$types';
@@ -20,14 +18,11 @@ SPDX-License-Identifier: MPL-2.0
name: ''
});
let isValid = $state(false);
let isValid = $derived(input_data.name.length !== 0 && input_data.player_name.length !== 0);
let isSubmitting = false;
run(() => {
isValid = input_data.name.length !== 0 && input_data.player_name.length !== 0;
});
const submit = async () => {
const submit = async (e: Event) => {
e.preventDefault();
if (!isValid) {
return;
}
@@ -59,7 +54,7 @@ SPDX-License-Identifier: MPL-2.0
Add a controller
</h3>
<form onsubmit={preventDefault(submit)}>
<form onsubmit={submit}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
+6 -11
View File
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run } from 'svelte/legacy';
import { alertModal } from '$lib/stores';
import { navbarVisible } from '$lib/stores.svelte';
import { slide } from 'svelte/transition';
@@ -23,7 +21,7 @@ SPDX-License-Identifier: MPL-2.0
navbarVisible.visible = true;
let { data } = $props();
const { verified }: boolean = data;
const { verified: boolean } = data;
let session_data = $state({});
let step = $state(0);
@@ -38,7 +36,7 @@ SPDX-License-Identifier: MPL-2.0
}
};
let alertModalOpen = false;
run(() => {
$effect(() => {
redirect_back(done);
});
@@ -51,8 +49,8 @@ SPDX-License-Identifier: MPL-2.0
}
});
const check_auto = () => {
if (step === 1) {
const check_auto = (stp: number) => {
if (stp === 1) {
if (!browserSupportsWebAuthn()) {
for (let i = 0; i < session_data.step_1.length; i++) {
if (session_data.step_1[i] === 'PASSKEY') {
@@ -65,7 +63,7 @@ SPDX-License-Identifier: MPL-2.0
selected_method = session_data.step_1[0];
}
}
if (step === 2) {
if (stp === 2) {
if (!browserSupportsWebAuthn()) {
for (let i = 0; i < session_data.step_2.length; i++) {
if (session_data.step_2[i] === 'PASSKEY') {
@@ -79,10 +77,7 @@ SPDX-License-Identifier: MPL-2.0
}
}
};
run(() => {
check_auto();
step;
});
$effect(() => check_auto(step));
</script>
<svelte:head>
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
@@ -20,12 +18,10 @@ SPDX-License-Identifier: MPL-2.0
let backup_code = $state('');
let isSubmitting = $state(false);
let backup_code_valid = $state(false);
run(() => {
backup_code_valid = backup_code.length === 64;
});
let backup_code_valid = $derived(backup_code.length === 64);
const continue_in_login = async () => {
const continue_in_login = async (e: Event) => {
e.preventDefault();
if (!backup_code_valid) {
return;
}
@@ -50,7 +46,7 @@ SPDX-License-Identifier: MPL-2.0
<div class="px-6 py-4">
<h2 class="text-3xl font-bold text-center text-gray-700 dark:text-white">ClassQuiz</h2>
<form onsubmit={preventDefault(continue_in_login)}>
<form onsubmit={continue_in_login}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
let {
@@ -20,7 +18,8 @@ SPDX-License-Identifier: MPL-2.0
let isSubmitting;
let password = $state();
const continue_in_login = async () => {
const continue_in_login = async (e: Event) => {
e.preventDefault();
if (!password) {
return;
}
@@ -60,7 +59,7 @@ SPDX-License-Identifier: MPL-2.0
<div class="px-6 py-4">
<h2 class="text-3xl font-bold text-center text-gray-700 dark:text-white">ClassQuiz</h2>
<form onsubmit={preventDefault(continue_in_login)}>
<form onsubmit={continue_in_login}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
@@ -4,8 +4,6 @@ SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run } from 'svelte/legacy';
let { session_data = {}, step, selected_method = $bindable() } = $props();
let available_methods = $state();
@@ -18,7 +16,7 @@ SPDX-License-Identifier: MPL-2.0
}
};
run(() => {
$effect(() => {
set_available_methods(step);
});
</script>
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
import OAuthBlock from './oauth_block.svelte';
@@ -14,14 +12,11 @@ SPDX-License-Identifier: MPL-2.0
const { t } = getLocalization();
let email = $state('');
let emailEmpty = $state(true);
let emailEmpty = $derived(email === '');
let isSubmitting = $state(false);
run(() => {
emailEmpty = email === '';
});
const start_login = async (): Promise<void> => {
const start_login = async (e: Event): Promise<void> => {
e.preventDefault();
if (emailEmpty) {
return;
}
@@ -50,7 +45,7 @@ SPDX-License-Identifier: MPL-2.0
{$t('login_page.login_or_create_account')}
</p>
<form onsubmit={preventDefault(start_login)}>
<form onsubmit={start_login}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
@@ -5,13 +5,9 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
interface Props {
// import { alertModal } from '$lib/stores';
session_data: any;
selected_method: any;
done: any;
@@ -26,16 +22,13 @@ SPDX-License-Identifier: MPL-2.0
}: Props = $props();
const { t } = getLocalization();
let isSubmitting;
let isSubmitting: boolean;
let totp = $state('');
let totp_valid = $state(false);
let totp_valid = $derived(totp.length === 6);
run(() => {
totp_valid = totp.length === 6;
});
const continue_in_login = async () => {
const continue_in_login = async (e: Event) => {
e.preventDefault();
if (!totp_valid) {
return;
}
@@ -84,7 +77,7 @@ SPDX-License-Identifier: MPL-2.0
<div class="px-6 py-4">
<h2 class="text-3xl font-bold text-center text-gray-700 dark:text-white">ClassQuiz</h2>
<form onsubmit={preventDefault(continue_in_login)}>
<form onsubmit={continue_in_login}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
@@ -5,13 +5,11 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
let { data } = $props();
let { token }: string = data;
let { token: string } = data;
let isSubmitting = $state(false);
interface PasswordData {
password1: string;
@@ -21,15 +19,12 @@ SPDX-License-Identifier: MPL-2.0
password1: '',
password2: ''
});
let passwordsValid = $state(false);
const checkIfPasswordsValid = (pwdata: PasswordData): void => {
passwordsValid = pwdata.password1 === pwdata.password2 && pwdata.password1.length >= 8;
};
run(() => {
checkIfPasswordsValid(passwordData);
});
let passwordsValid = $derived(
passwordData.password1 === passwordData.password2 && passwordData.password1.length >= 8
);
const submit = async () => {
const submit = async (e: Event) => {
e.preventDefault();
if (!passwordsValid) {
return;
}
@@ -77,7 +72,7 @@ SPDX-License-Identifier: MPL-2.0
{$t('password_reset_page.reset_password')}
</p>
<form onsubmit={preventDefault(submit)}>
<form onsubmit={submit}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
import { navbarVisible } from '$lib/stores.svelte.ts';
@@ -16,7 +14,8 @@ SPDX-License-Identifier: MPL-2.0
let isSubmitting = $state(false);
const submit = async () => {
const submit = async (e: Event) => {
e.preventDefault();
isSubmitting = true;
const res = await fetch('/api/v1/users/forgot-password', {
method: 'POST',
@@ -62,7 +61,7 @@ SPDX-License-Identifier: MPL-2.0
{$t('password_reset_page.reset_password')}
</p>
<form onsubmit={preventDefault(submit)}>
<form onsubmit={submit}>
<div class="w-full mt-4">
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
<div class="relative bg-inherit w-full">
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
import { DateTime } from 'luxon';
import { UAParser } from 'ua-parser-js';
@@ -39,18 +37,15 @@ SPDX-License-Identifier: MPL-2.0
let locationData;
let this_session = $state();
let passwordChangeDataValid = $state(false);
const checkPasswords = (data: ChangePasswordData): void => {
passwordChangeDataValid =
data.newPassword === data.newPasswordConfirm &&
data.newPassword.length >= 8 &&
data.oldPassword !== data.newPassword &&
data.oldPassword !== '';
};
run(() => {
checkPasswords(changePasswordData);
});
const changePassword = async () => {
let passwordChangeDataValid = $derived(
changePasswordData.newPassword === changePasswordData.newPasswordConfirm &&
changePasswordData.newPassword.length >= 8 &&
changePasswordData.oldPassword !== changePasswordData.newPassword &&
changePasswordData.oldPassword !== ''
);
const changePassword = async (e: Event) => {
e.preventDefault();
if (!passwordChangeDataValid) {
return;
}
@@ -184,7 +179,7 @@ SPDX-License-Identifier: MPL-2.0
</div>
</div>
<div>
<form class="flex flex-col md:flex-row" onsubmit={preventDefault(changePassword)}>
<form class="flex flex-col md:flex-row" onsubmit={changePassword}>
<label
>{$t('settings_page.old_password')}:<input
type="password"
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run } from 'svelte/legacy';
import BrownButton from '$lib/components/buttons/brown.svelte';
import { fade, fly } from 'svelte/transition';
import { bounceOut } from 'svelte/easing';
@@ -71,10 +69,6 @@ SPDX-License-Identifier: MPL-2.0
let image_url = $derived(get_image_url(data));
run(() => {
console.log('index', index);
});
const save_avatar = async () => {
save_finished = false;
const res = await fetch(`/api/v1/avatar/save?${new URLSearchParams(data).toString()}`, {
+11 -17
View File
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import type { QuizData } from '$lib/quiz_types';
import { socket } from '$lib/socket';
@@ -124,11 +122,12 @@ SPDX-License-Identifier: MPL-2.0
}
};
const request_answer_export = async () => {
await socket.emit('get_export_token');
const request_answer_export = (e: Event) => {
e.preventDefault();
socket.emit('get_export_token');
};
const save_quiz = async () => {
await socket.emit('save_quiz');
const save_quiz = () => {
socket.emit('save_quiz');
};
let darkMode = false;
@@ -143,10 +142,7 @@ SPDX-License-Identifier: MPL-2.0
let bg_image = $derived(quiz_data ? quiz_data.background_image : undefined);
let results_saved = $state(false);
let show_final_results = $state(false);
run(() => {
show_final_results = JSON.stringify(final_results) !== JSON.stringify([null]);
});
let show_final_results = $derived(JSON.stringify(final_results) !== JSON.stringify([null]));
</script>
<svelte:window onbeforeunload={confirmUnload} />
@@ -201,7 +197,7 @@ SPDX-License-Identifier: MPL-2.0
</div>
</div>
{/if}
<FinalResults bind:data={player_scores} bind:show_final_results />
<FinalResults bind:data={player_scores} {show_final_results} />
{/if}
{#if !success}
{#if errorMessage !== ''}
@@ -217,18 +213,16 @@ SPDX-License-Identifier: MPL-2.0
{:else}
<SomeAdminScreen
bind:final_results
{game_pin}
bind:game_token
{game_token}
bind:quiz_data
bind:game_mode
bind:bg_color
{bg_color}
bind:player_scores
bind:control_visible
{control_visible}
/>
{/if}
</div>
<a
onclick={preventDefault(request_answer_export)}
onclick={request_answer_export}
href="#"
target="_blank"
bind:this={dataexport_download_a}
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run } from 'svelte/legacy';
import DownloadQuiz from '$lib/components/DownloadQuiz.svelte';
import type { QuizData } from '$lib/quiz_types';
import { getLocalization } from '$lib/i18n';
@@ -50,23 +48,6 @@ SPDX-License-Identifier: MPL-2.0
let id_to_position_map = {};
const getData = async (): Promise<{ items: Array<QuizData>; fuse: Fuse<any> }> => {
/* items_to_show = [];
for (let i = 0; i < data.quizzes.length; i++) {
items_to_show.push({ ...data.quizzes[i], type: 'quiz' });
}
for (let i = 0; i < data.quiztivities.length; i++) {
items_to_show.push({ ...data.quiztivities[i], type: 'quiztivity' });
}
fuse = new Fuse(items_to_show, {
keys: ['title', 'description', 'questions.title'],
findAllMatches: true
});
all_items = items_to_show;
for (let i = 0; i < all_items.length; i++) {
id_to_position_map[all_items[i].id] = i;
}
return all_items;
*/
const items: any[] = [];
for (const q of data.quizzes) items.push({ ...q, type: 'quiz' });
+3 -4
View File
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { preventDefault } from 'svelte/legacy';
import type { PageData } from './$types';
import { fade } from 'svelte/transition';
// import MediaComponent from '$lib/editor/MediaComponent.svelte';
@@ -37,7 +35,8 @@ SPDX-License-Identifier: MPL-2.0
};
});
const save_image_metadata = async () => {
const save_image_metadata = async (e: Event) => {
e.preventDefault();
await fetch(`/api/v1/storage/meta/${edit_popup.id}`, {
method: 'PUT',
headers: {
@@ -131,7 +130,7 @@ SPDX-License-Identifier: MPL-2.0
>
<div class="w-auto h-auto m-auto rounded-sm bg-white dark:bg-gray-700 p-4">
<h1 class="text-2xl text-center">{$t('file_dashboard.edit_the_image')}</h1>
<form class="flex flex-col" onsubmit={preventDefault(save_image_metadata)}>
<form class="flex flex-col" onsubmit={save_image_metadata}>
<div class="flex flex-row">
<div class="flex flex-col mr-4">
<label for="name" class="m-auto">{$t('file_dashboard.filename_word')}</label
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run } from 'svelte/legacy';
import Spinner from '$lib/Spinner.svelte';
let uppyOpen = $state(false);
@@ -14,7 +12,7 @@ SPDX-License-Identifier: MPL-2.0
let selected_question = $state(undefined);
let data = $state({ cover_image: undefined });
run(() => {
$effect(() => {
if (data.cover_image) {
window.location.reload();
}
+8 -33
View File
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
import { navbarVisible } from '$lib/stores.svelte.ts';
import { onMount } from 'svelte';
@@ -17,16 +15,13 @@ SPDX-License-Identifier: MPL-2.0
const { t } = getLocalization();
let url_input = $state('');
let file_input: File[] = $state();
let url_valid = $state(false);
let kahoot_regex = /^https:\/\/create\.kahoot\.it\/details\/([a-zA-Z-\d]{36})\/?$/;
let url_valid = $derived(kahoot_regex.test(url_input));
let is_loading = $state(false);
run(() => {
url_valid = kahoot_regex.test(url_input);
});
const submit = async () => {
const submit = async (e: Event) => {
e.preventDefault();
if (!url_valid) {
return;
}
@@ -61,7 +56,8 @@ SPDX-License-Identifier: MPL-2.0
is_loading = false;
};
const file_submit = async () => {
const file_submit = async (e: Event) => {
e.preventDefault();
is_loading = true;
const formdata = new FormData();
formdata.append('file', file_input[0]);
@@ -95,10 +91,6 @@ SPDX-License-Identifier: MPL-2.0
is_loading = false;
};
run(() => {
console.log(file_input);
});
onMount(() => {
let url_from_path = page.url.searchParams.get('url');
if (url_from_path === '') {
@@ -112,23 +104,6 @@ SPDX-License-Identifier: MPL-2.0
<title>ClassQuiz - Import</title>
</svelte:head>
<!--{#if is_loading}
<svg class='h-8 w-8 animate-spin mx-auto my-20' viewBox='3 3 18 18'>
<path
class='fill-black'
d='M12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19C15.866 19 19 15.866 19 12C19 8.13401 15.866 5 12 5ZM3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12Z'
/>
<path
class='fill-blue-100'
d='M16.9497 7.05015C14.2161 4.31648 9.78392 4.31648 7.05025 7.05015C6.65973 7.44067 6.02656 7.44067 5.63604 7.05015C5.24551 6.65962 5.24551 6.02646 5.63604 5.63593C9.15076 2.12121 14.8492 2.12121 18.364 5.63593C18.7545 6.02646 18.7545 6.65962 18.364 7.05015C17.9734 7.44067 17.3403 7.44067 16.9497 7.05015Z'
/>
</svg>
{:else}-->
<!-- <form on:submit|preventDefault={submit}>
<input type='text' class="text-black w-2/5" bind:value={url_input} />
<button type='submit' disabled={!url_valid}>Submit</button>
</form>-->
<div class="flex items-center justify-center h-full px-4">
<div>
<span class="p-4"></span>
@@ -149,7 +124,7 @@ SPDX-License-Identifier: MPL-2.0
Login or create account
</p>-->
<div class="grid grid-cols-2">
<form onsubmit={preventDefault(submit)}>
<form onsubmit={submit}>
<div class="w-full mt-4 h-full flex flex-col">
<h2 class="text-center text-2xl">{$t('import_page.a_kahoot_quiz')}</h2>
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
@@ -208,7 +183,7 @@ SPDX-License-Identifier: MPL-2.0
</div>
</div>
</form>
<form onsubmit={preventDefault(file_submit)}>
<form onsubmit={file_submit}>
<div class="w-full mt-4 border-l-2 border-gray-600 h-full flex flex-col">
<h2 class="text-center text-2xl">{$t('import_page.classquiz_quiz')}</h2>
<div class="dark:bg-gray-800 bg-white p-4 rounded-lg">
+10 -27
View File
@@ -11,8 +11,7 @@ SPDX-License-Identifier: MPL-2.0
import type { Answer, Question as QuestionType } from '$lib/quiz_types';
import ShowTitle from '$lib/play/title.svelte';
import Question from '$lib/play/question.svelte';
// import ShowResults from '$lib/play/show_results.svelte';
import { navbarVisible} from '$lib/stores.svelte.ts';
import { navbarVisible } from '$lib/stores.svelte.ts';
import ShowEndScreen from '$lib/play/admin/final_results.svelte';
import KahootResults from '$lib/play/results_kahoot.svelte';
import { getLocalization } from '$lib/i18n';
@@ -44,8 +43,7 @@ SPDX-License-Identifier: MPL-2.0
// Variables init
let question_index = $state('');
let unique = $state({});
navbarVisible.visible=false;
let game_pin_valid: boolean;
navbarVisible.visible = false;
let answer_results: Array<Answer> = $state();
let gameData = $state();
let solution: QuestionType = $state();
@@ -55,7 +53,7 @@ SPDX-License-Identifier: MPL-2.0
started: false
});
let question = $state();
let question: Question = $state();
let preventReload = true;
@@ -64,7 +62,7 @@ SPDX-License-Identifier: MPL-2.0
unique = {};
}
const confirmUnload = () => {
const confirmUnload = (event: Event) => {
if (preventReload) {
event.preventDefault();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -76,9 +74,6 @@ SPDX-License-Identifier: MPL-2.0
socket.on('time_sync', (data) => {
socket.emit('echo_time_sync', data);
});
socket.on('session_id', (d) => {
const session_id = d.session_id;
});
socket.on('connect', async () => {
console.log('Connected!');
@@ -120,7 +115,6 @@ SPDX-License-Identifier: MPL-2.0
window.location.reload();
return;
}
game_pin_valid = false;
});
socket.on('set_question_number', (data) => {
@@ -169,13 +163,6 @@ SPDX-License-Identifier: MPL-2.0
<svelte:window onbeforeunload={confirmUnload} />
<svelte:head>
<title>ClassQuiz - Play</title>
<!-- {#if gameData !== undefined && game_mode !== 'kahoot'}
{#each gameData.questions as question}
{#if question.image !== undefined}
<link rel="preload" as="image" href={question.image} />
{/if}
{/each}
{/if}-->
</svelte:head>
<div
class="min-h-screen min-w-full"
@@ -186,17 +173,17 @@ SPDX-License-Identifier: MPL-2.0
{#if !gameMeta.started && gameData === undefined}
<JoinGame bind:game_pin bind:game_mode bind:username />
{:else if JSON.stringify(final_results) !== JSON.stringify([null])}
<ShowEndScreen bind:data={scores} show_final_results={true} bind:username />
<ShowEndScreen bind:data={scores} show_final_results={true} {username} />
{:else if gameData !== undefined && question_index === ''}
<ShowTitle
bind:title={gameData.title}
bind:description={gameData.description}
bind:cover_image={gameData.cover_image}
title={gameData.title}
description={gameData.description}
cover_image={gameData.cover_image}
/>
{:else if gameMeta.started && gameData !== undefined && question_index !== '' && answer_results === undefined}
{#key unique}
<div class="text-black dark:text-black">
<Question bind:game_mode bind:question bind:question_index bind:solution />
<Question bind:game_mode bind:question {question_index} {solution} />
</div>
{/key}
{:else if gameMeta.started && answer_results !== undefined}
@@ -209,11 +196,7 @@ SPDX-License-Identifier: MPL-2.0
<h2 class="text-center text-3xl mb-8">{$t('words.result', { count: 2 })}</h2>
</div>
{#key unique}
<KahootResults
bind:username
bind:question_results={answer_results}
bind:scores
/>
<KahootResults {username} question_results={answer_results} bind:scores />
{/key}
{/if}
{/if}
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run } from 'svelte/legacy';
import type { PageData } from './$types';
import type { QuizTivityPage } from '$lib/quiztivity/types';
import { QuizTivityTypes } from '$lib/quiztivity/types';
@@ -25,10 +23,7 @@ SPDX-License-Identifier: MPL-2.0
}
let current_slide_index = $state(0);
let current_slide: QuizTivityPage = $state(quiztivity.pages[current_slide_index]);
run(() => {
current_slide = quiztivity.pages[current_slide_index];
});
let current_slide: QuizTivityPage = $derived(quiztivity.pages[current_slide_index]);
</script>
<div class="w-full h-full flex flex-col overflow-scroll">
+16 -21
View File
@@ -5,8 +5,6 @@ SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { run, preventDefault } from 'svelte/legacy';
import { page } from '$app/state';
import { socket } from '$lib/socket';
import type { QuizData } from '$lib/quiz_types';
@@ -24,19 +22,19 @@ SPDX-License-Identifier: MPL-2.0
navbarVisible.visible = false;
const { t } = getLocalization();
let timer_interval;
let timer_interval: NodeJS.Timeout;
let timer_res = $state(undefined);
let selected_question = $state(-1);
let game_started = $state(false);
let question_results = $state();
let final_results = $state([null]);
let warnToLeave = true;
let dataexport_download_a = $state();
let dataexport_download_a: HTMLAnchorElement = $state();
let players: Array<{ sid: string; username: string }> = $state([]);
let game_data: QuizData = $state();
let shown_question_now;
let shown_question_now: number;
let control_visible = $state(false);
if (!data.game_id || !data.game_pin) {
@@ -90,12 +88,12 @@ SPDX-License-Identifier: MPL-2.0
socket.emit('get_final_results', {});
};
const request_answer_export = async () => {
await socket.emit('get_export_token');
const request_answer_export = async (e: Event) => {
e.preventDefault();
socket.emit('get_export_token');
};
const get_already_joined_players = async () => {
console.log('GETTING PLAYERS');
const res = await fetch(
`/api/v1/live/players?game_pin=${data.game_pin}&game_id=${data.game_id}`
);
@@ -103,15 +101,16 @@ SPDX-License-Identifier: MPL-2.0
players = await res.json();
}
};
let circular_progress = $state(0);
run(() => {
let circular_progress = $derived.by(() => {
try {
circular_progress =
return (
1 -
((100 / game_data.questions[selected_question].time) * parseInt(timer_res)) / 100;
((100 / parseInt(game_data.questions[selected_question].time)) *
parseInt(timer_res)) /
100
);
} catch {
circular_progress = 0;
return 0;
}
});
@@ -235,7 +234,7 @@ SPDX-License-Identifier: MPL-2.0
{#await import('$lib/play/admin/slide.svelte')}
<Spinner my_20={false} />
{:then c}
<c.default bind:question={game_data.questions[selected_question]} />
<c.default question={game_data.questions[selected_question]} />
{/await}
{:else}
<div class="flex flex-col justify-center w-screen h-1/6">
@@ -244,11 +243,7 @@ SPDX-License-Identifier: MPL-2.0
</h1>
<!-- <span class='text-center py-2 text-lg'>{$t('admin_page.time_left')}: {timer_res}</span>-->
<div class="mx-auto my-2">
<CircularTimer
bind:text={timer_res}
bind:progress={circular_progress}
color="#ef4444"
/>
<CircularTimer text={timer_res} progress={circular_progress} color="#ef4444" />
</div>
{#if game_data.questions[selected_question].image !== null}
<div>
@@ -328,7 +323,7 @@ SPDX-License-Identifier: MPL-2.0
</div>
<a
onclick={preventDefault(request_answer_export)}
onclick={request_answer_export}
href="#"
bind:this={dataexport_download_a}
class="absolute -top-3/4 -left-3/4 opacity-0 hidden">Download</a
+2 -2
View File
@@ -2,9 +2,9 @@
//
// SPDX-License-Identifier: MPL-2.0
// import type { PageLoad } from './$types';
import type { PageLoad } from './$types';
export const load = async ({ fetch }) => {
export const load: PageLoad = async ({ fetch }) => {
const res = await fetch('/api/v1/results/list?include_quiz=true');
let json;
if (res.ok) {
@@ -79,8 +79,6 @@ SPDX-License-Identifier: MPL-2.0
{#if selected_tab === SelectedTab.Overview}
<div in:fade|global={{ duration: 150 }}>
<GeneralOverview
questions={data.results.questions}
answers={data.results.answers}
scores={data.results.player_scores}
title={data.results.title}
timestamp={data.results.timestamp}
@@ -1,10 +1,9 @@
// SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
//
// SPDX-License-Identifier: MPL-2.0
import type { PageLoad } from './$types';
// import type { PageLoad } from './$types';
export const load = async ({ params, fetch }) => {
export const load: PageLoad = async ({ params, fetch }) => {
const res = await fetch(`/api/v1/results/${params.result_id}?include_quiz=true`);
let json;
if (res.ok) {
@@ -15,4 +14,4 @@ export const load = async ({ params, fetch }) => {
return {
results: json
};
}; //satisfies PageLoad;
};
@@ -11,14 +11,6 @@ SPDX-License-Identifier: MPL-2.0
const { t } = getLocalization();
interface Props {
questions: Question[];
answers: {
username: string;
answer: string;
right: boolean;
tike_taken: number;
score: number;
}[][];
scores: {
[key: string]: string;
};
@@ -26,7 +18,7 @@ SPDX-License-Identifier: MPL-2.0
timestamp: string;
}
let { questions, answers, scores, title, timestamp }: Props = $props();
let { scores, title, timestamp }: Props = $props();
const usernames = Object.keys(scores);
@@ -33,7 +33,6 @@ SPDX-License-Identifier: MPL-2.0
}
});
});
console.log(custom_field);
</script>
<div class="w-full">
@@ -7,7 +7,7 @@ SPDX-License-Identifier: MPL-2.0
<script lang="ts">
import type { Question } from '$lib/quiz_types';
import { fly } from 'svelte/transition';
import QuestionTab from './question_tab_thing.svelte';
import QuestionTab from './question_tab_dropdown.svelte';
import { QuizQuestionType } from '$lib/quiz_types';
import { getLocalization } from '$lib/i18n';
@@ -16,12 +16,12 @@ SPDX-License-Identifier: MPL-2.0
interface Props {
questions: Question[];
answers: {
username: string;
answer: string;
right: boolean;
tike_taken: number;
score: number;
}[][];
username: string;
answer: string;
right: boolean;
tike_taken: number;
score: number;
}[][];
}
let { questions, answers }: Props = $props();
@@ -57,7 +57,7 @@ SPDX-License-Identifier: MPL-2.0
</script>
<div class="w-full flex justify-center">
<div class="w-11/12 flex flex-col w-full gap-4">
<div class="flex flex-col w-full gap-4">
{#each questions as question, i}
<div class="transition-all">
<div
@@ -11,7 +11,6 @@ SPDX-License-Identifier: MPL-2.0
const { t } = getLocalization();
interface Answer {
username: string;
answer: string;
@@ -26,7 +25,6 @@ SPDX-License-Identifier: MPL-2.0
}
let { question, answers }: Props = $props();
// console.log(question);
const get_answer_count_for_answer = (answer: string): number => {
let count = 0;
+5 -3
View File
@@ -4,8 +4,6 @@ SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
SPDX-License-Identifier: MPL-2.0
-->
<script lang="ts">
import { preventDefault } from 'svelte/legacy';
import { getLocalization } from '$lib/i18n';
const { t } = getLocalization();
import SearchCard from '$lib/search-card.svelte';
@@ -52,7 +50,10 @@ SPDX-License-Identifier: MPL-2.0
<div class="mb-3 xl:w-96">
<form
class="input-group relative flex items-stretch flex-row w-full mb-4"
onsubmit={preventDefault(submit)}
onsubmit={(e: Event) => {
e.preventDefault();
submit();
}}
>
<input
type="search"
@@ -65,6 +66,7 @@ SPDX-License-Identifier: MPL-2.0
<button
class="px-6 py-2.5 bg-blue-600 text-white font-medium text-xs leading-tight uppercase rounded-sm shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700 focus:shadow-lg focus:outline-hidden focus:ring-0 active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out flex items-center disabled:opacity-50 disabled:cursor-not-allowed"
id="button-addon2"
aria-label="Search"
disabled={search_term.length <= 2}
type="submit"
>
@@ -13,7 +13,6 @@ SPDX-License-Identifier: MPL-2.0
import StartGamePopup from '$lib/dashboard/start_game.svelte';
const { t } = getLocalization();
// import { DateTime } from 'luxon';
let start_game = $state(null);
const tippy = createTippy({
@@ -71,12 +70,6 @@ SPDX-License-Identifier: MPL-2.0
class="rounded-lg border-2 border-black hover:outline transition-all outline-[#B07156] -outline-offset-2 outline-8"
>
<div class="grid grid-cols-6 h-[25vh]">
<!-- <p
style='writing-mode: vertical-lr'
class='text-center h-full text-xl p-2'
>
{@html quiz.title}
</p>-->
<div class="col-start-2 col-end-6">
<h3 class="text-center text-2xl">{@html quiz.title}</h3>
<p class="text-center">
@@ -95,15 +88,6 @@ SPDX-License-Identifier: MPL-2.0
</div>
{/if}
</div>
<!-- <div class='flex justify-end'>
<p
style='writing-mode: sideways-lr'
class='text-center text-xl p-2'
>
{@html quiz.title}
</p>
</div>-->
</div>
<div class="flex justify-center">
<a href="/view/{quiz.id}" class="action-button w-1/6"
@@ -166,6 +150,7 @@ SPDX-License-Identifier: MPL-2.0
>
<button
disabled
aria-label="Download"
class="action-button w-full flex justify-center"
>
<svg
+3 -3
View File
@@ -2,9 +2,9 @@
//
// SPDX-License-Identifier: MPL-2.0
// import type { PageLoad } from './$types';
import type { PageLoad } from './$types';
export const load = async ({ params, fetch }) => {
export const load: PageLoad = async ({ params, fetch }) => {
const user_req = await fetch(`/api/v1/community/user/${params.user_id}`);
const user = await user_req.json();
if (!user) {
@@ -24,4 +24,4 @@ export const load = async ({ params, fetch }) => {
user,
quizzes
};
}; // satisfies PageLoad;
};
@@ -3,8 +3,9 @@
// SPDX-License-Identifier: MPL-2.0
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = async ({ params, parent }) => {
export const load: PageServerLoad = async ({ params, parent }) => {
const { quiz_id } = params;
const res = await fetch(`${process.env.API_URL}/api/v1/quiz/get/public/${quiz_id}`);
const { email } = await parent();
@@ -245,10 +245,6 @@ SPDX-License-Identifier: MPL-2.0
<h3 class="text-3xl m-1 text-center">
{index_question + 1}: {@html question.question}
</h3>
<!-- <label class='m-1 flex flex-row gap-2 w-3/5'>-->
<!-- </label>-->
{#if question.image}
<span>
<MediaComponent
@@ -316,7 +312,7 @@ SPDX-License-Identifier: MPL-2.0
</ul>
{:else if question.type === QuizQuestionType.VOTING || question.type === QuizQuestionType.TEXT}
<div class="grid grid-cols-2 gap-4 m-4 p-6">
{#each question.answers as answer, index_answer}
{#each question.answers as _, index_answer}
<div class="p-1 rounded-lg py-4 dark:bg-gray-500 bg-gray-300">
<h4 class="text-center">
{quiz.questions[index_question].answers[index_answer]
@@ -327,10 +323,10 @@ SPDX-License-Identifier: MPL-2.0
</div>
{:else if question.type === QuizQuestionType.SLIDE}
{#await import('$lib/play/admin/slide.svelte')}
<Spinner my={false} />
<Spinner my_20={false} />
{:then c}
<div class="max-h-[90%] max-w-[90%]">
<c.default bind:question={questions[index_question]} />
<c.default question={quiz.questions[index_question]} />
</div>
{/await}
{/if}