✨ Added custom alert-component
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
<!--
|
||||||
|
By Flowbite, but changed: https://flowbite.com/docs/components/modal/#default-modal
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
export let title: string;
|
||||||
|
export let body: string;
|
||||||
|
export let open: boolean;
|
||||||
|
console.log(open, title, body);
|
||||||
|
open = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Main modal -->
|
||||||
|
{#if open}
|
||||||
|
<div tabindex="-1" class="overflow-y-auto overflow-x-hidden md:inset-0 lg:w-2/6 w-5/6">
|
||||||
|
<div class="relative p-4 w-full max-w-2xl h-full md:h-auto">
|
||||||
|
<!-- Modal content -->
|
||||||
|
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||||
|
<!-- Modal header -->
|
||||||
|
<div
|
||||||
|
class="flex justify-between items-start p-4 rounded-t border-b dark:border-gray-600"
|
||||||
|
>
|
||||||
|
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"
|
||||||
|
on:click={() => {
|
||||||
|
open = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="w-5 h-5"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<!-- Modal body -->
|
||||||
|
<div class="p-6 space-y-6">
|
||||||
|
<p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">
|
||||||
|
{body}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- Modal footer -->
|
||||||
|
<div
|
||||||
|
class="flex items-center p-6 space-x-2 rounded-b border-t border-gray-200 dark:border-gray-600"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
data-modal-toggle="defaultModal"
|
||||||
|
type="button"
|
||||||
|
on:click={() => {
|
||||||
|
open = false;
|
||||||
|
}}
|
||||||
|
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
|
||||||
|
>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav
|
<nav
|
||||||
class="w-screen px-4 lg:px-10 py-2 flex flex-col lg:flex-row lg:items-center fixed backdrop-blur-2xl bg-white/70 shadow-md z-50 top-0"
|
class="w-screen px-4 lg:px-10 py-2 flex flex-col lg:flex-row lg:items-center fixed backdrop-blur-2xl bg-white/70 shadow-md z-30 top-0"
|
||||||
>
|
>
|
||||||
<section class="w-full lg:w-max flex justify-between">
|
<section class="w-full lg:w-max flex justify-between">
|
||||||
<a href="/" class="font-black tracking-tight text-xl text-black marck-script link-hover"
|
<a href="/" class="font-black tracking-tight text-xl text-black marck-script link-hover"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { browser } from '$app/env';
|
import { browser } from '$app/env';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
|
import { alertModal } from '../stores';
|
||||||
|
|
||||||
export let game_pin: string;
|
export let game_pin: string;
|
||||||
|
|
||||||
@@ -50,12 +51,20 @@
|
|||||||
captcha_enabled = (await res.json()).enabled;
|
captcha_enabled = (await res.json()).enabled;
|
||||||
}
|
}
|
||||||
if (res.status === 404) {
|
if (res.status === 404) {
|
||||||
alert('Game not found');
|
alertModal.set({
|
||||||
|
open: true,
|
||||||
|
title: 'Game not found',
|
||||||
|
body: 'The game pin you entered seems invalid.'
|
||||||
|
});
|
||||||
game_pin = '';
|
game_pin = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
alert('Unknown error!');
|
alertModal.set({
|
||||||
|
open: true,
|
||||||
|
body: `Unknown error with response-code ${res.status}`,
|
||||||
|
title: 'Unknown Error'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +78,17 @@
|
|||||||
if (import.meta.env.VITE_SENTRY !== null) {
|
if (import.meta.env.VITE_SENTRY !== null) {
|
||||||
Sentry.captureException(e);
|
Sentry.captureException(e);
|
||||||
}
|
}
|
||||||
alert('Captcha failed, reloading the page probably helps!');
|
alertModal.set({
|
||||||
|
open: true,
|
||||||
|
body: "The captcha failed, which is normal, but most of the time it's fixed by reloading!",
|
||||||
|
title: 'Captcha failed'
|
||||||
|
});
|
||||||
|
alertModal.subscribe((data) => {
|
||||||
|
if (!data.open) {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
socket.emit('join_game', {
|
socket.emit('join_game', {
|
||||||
username: username,
|
username: username,
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ import { writable } from 'svelte/store';
|
|||||||
export const navbarVisible = writable(true);
|
export const navbarVisible = writable(true);
|
||||||
export const signedIn = writable(false);
|
export const signedIn = writable(false);
|
||||||
export const pathname = writable('/');
|
export const pathname = writable('/');
|
||||||
|
|
||||||
|
export const alertModal = writable({ open: false, title: '', body: '' });
|
||||||
|
|||||||
@@ -12,11 +12,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
import Navbar from '$lib/navbar.svelte';
|
import Navbar from '$lib/navbar.svelte';
|
||||||
import { navbarVisible, pathname } from '$lib/stores';
|
import { navbarVisible, pathname, alertModal } from '$lib/stores';
|
||||||
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/env';
|
||||||
|
import Alert from '$lib/modals/alert.svelte';
|
||||||
|
|
||||||
if (browser) {
|
if (browser) {
|
||||||
pathname.set(window.location.pathname);
|
pathname.set(window.location.pathname);
|
||||||
@@ -64,6 +65,17 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<slot />
|
<slot />
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $alertModal.open}
|
||||||
|
<div
|
||||||
|
class="fixed inset-0 h-screen w-screen bg-black z-30 bg-opacity-60 flex items-center justify-center content-center"
|
||||||
|
>
|
||||||
|
<Alert
|
||||||
|
bind:title={$alertModal.title}
|
||||||
|
bind:body={$alertModal.body}
|
||||||
|
bind:open={$alertModal.open}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
:global(html:not(.dark)) {
|
:global(html:not(.dark)) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
import { navbarVisible } from '$lib/stores';
|
import { navbarVisible, alertModal } from '$lib/stores';
|
||||||
|
|
||||||
navbarVisible.set(true);
|
navbarVisible.set(true);
|
||||||
|
|
||||||
@@ -50,9 +50,17 @@
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
window.location.href = '/overview';
|
window.location.href = '/overview';
|
||||||
} else if (res.status === 400) {
|
} else if (res.status === 400) {
|
||||||
alert("This quiz isn't (yet) supported!");
|
alertModal.set({
|
||||||
|
open: true,
|
||||||
|
title: 'Import failed',
|
||||||
|
body: "This quiz isn't (yet) supported!"
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alert('Error importing quiz');
|
alertModal.set({
|
||||||
|
open: true,
|
||||||
|
title: 'Import failed',
|
||||||
|
body: 'Unknown error while importing the quiz!'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
is_loading = false;
|
is_loading = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { getLocalization } from '$lib/i18n';
|
import { getLocalization } from '$lib/i18n';
|
||||||
import Footer from '$lib/footer.svelte';
|
import Footer from '$lib/footer.svelte';
|
||||||
import { navbarVisible, signedIn } from '$lib/stores';
|
import { alertModal, navbarVisible, signedIn } from '$lib/stores';
|
||||||
|
|
||||||
interface QuizData {
|
interface QuizData {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -60,9 +60,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
alert('Failed to start game!');
|
alertModal.set({
|
||||||
console.error(`Failed to start game, ${await res.text()}`);
|
open: true,
|
||||||
|
title: 'Start failed',
|
||||||
|
body: `Failed to start game, ${await res.text()}`
|
||||||
|
});
|
||||||
|
alertModal.subscribe((_) => {
|
||||||
window.location.replace('/account/login?returnTo=/overview');
|
window.location.replace('/account/login?returnTo=/overview');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
|
|||||||
Reference in New Issue
Block a user