This commit is contained in:
@@ -2,17 +2,16 @@
|
||||
import { fly } from 'svelte/transition';
|
||||
import RegistrationComplete from './RegistrationComplete.svelte';
|
||||
import Register from './Register.svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
let registered = false;
|
||||
let firstname: string | null = null;
|
||||
let lastname: string | null = null;
|
||||
let birthday: Date | null = null;
|
||||
let phone: string | null = null;
|
||||
let username: string | null = null;
|
||||
let edition: string | null = null;
|
||||
let { data } = $props();
|
||||
|
||||
export let data: PageData;
|
||||
let registered = $state(false);
|
||||
let firstname: string | null = $state(null);
|
||||
let lastname: string | null = $state(null);
|
||||
let birthday: Date | null = $state(null);
|
||||
let phone: string | null = $state(null);
|
||||
let username: string | null = $state(null);
|
||||
let edition: string | null = $state(null);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -36,15 +35,15 @@
|
||||
{#if !registered}
|
||||
<div class="col-[1] row-[1]" transition:fly={{ x: -200, duration: 300 }}>
|
||||
<Register
|
||||
on:submit={(e) => {
|
||||
submit={(e) => {
|
||||
registered = true;
|
||||
firstname = e.detail.firstname;
|
||||
lastname = e.detail.lastname;
|
||||
birthday = e.detail.birthday;
|
||||
phone = e.detail.phone;
|
||||
phone = e.detail.phone;
|
||||
username = e.detail.username;
|
||||
edition = e.detail.edition;
|
||||
firstname = e.firstname;
|
||||
lastname = e.lastname;
|
||||
birthday = e.birthday;
|
||||
phone = e.phone;
|
||||
phone = e.phone;
|
||||
username = e.username;
|
||||
edition = e.edition;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -57,7 +56,7 @@
|
||||
{phone}
|
||||
{username}
|
||||
{edition}
|
||||
on:close={() => (registered = false)}
|
||||
close={() => (registered = false)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -17,6 +17,7 @@ export const POST = (async ({ request }) => {
|
||||
}
|
||||
|
||||
try {
|
||||
// eslint-disable-next-line no-var
|
||||
var data = RegisterSchema.parse(await request.json());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
@@ -1,27 +1,54 @@
|
||||
<script lang="ts">
|
||||
import Select from '$lib/components/Input/Select.svelte';
|
||||
import Input from '$lib/components/Input/Input.svelte';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { rulesShort } from '$lib/rules';
|
||||
import { RegisterSchema } from './schema';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let {
|
||||
submit
|
||||
}: {
|
||||
submit: ({
|
||||
firstname,
|
||||
lastname,
|
||||
birthday,
|
||||
phone,
|
||||
username,
|
||||
edition
|
||||
}: {
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
birthday: Date;
|
||||
phone: string;
|
||||
username: string;
|
||||
edition: string;
|
||||
}) => void;
|
||||
} = $props();
|
||||
|
||||
const modalTimeoutSeconds = dev ? 0 : 30;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
let checkInputs = () => {};
|
||||
let playertype = 'java';
|
||||
let firstnameInput: HTMLInputElement;
|
||||
let lastnameInput: HTMLInputElement;
|
||||
let birthdayInput: HTMLInputElement;
|
||||
let phoneInput: HTMLInputElement;
|
||||
let usernameInput: HTMLInputElement;
|
||||
let privacyInput: HTMLInputElement;
|
||||
let logsInput: HTMLInputElement;
|
||||
let rulesInput: HTMLInputElement;
|
||||
let checkInputs = $state(() => {});
|
||||
let playertype = $state('java');
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
// @ts-ignore
|
||||
let firstnameInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let lastnameInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let birthdayInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let phoneInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let usernameInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let privacyInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let logsInput: HTMLInputElement = $state();
|
||||
// @ts-ignore
|
||||
let rulesInput: HTMLInputElement = $state();
|
||||
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
||||
onMount(() => {
|
||||
checkInputs = () => {
|
||||
let allInputs = [
|
||||
@@ -58,10 +85,10 @@
|
||||
body: JSON.stringify(Object.fromEntries(new FormData(document.forms[0])))
|
||||
});
|
||||
if (response.ok) {
|
||||
dispatch('submit', {
|
||||
submit({
|
||||
firstname: firstnameInput.value,
|
||||
lastname: lastnameInput.value,
|
||||
birthday: birthdayInput.valueAsDate,
|
||||
birthday: birthdayInput.valueAsDate!,
|
||||
phone: phoneInput.value,
|
||||
username: usernameInput.value,
|
||||
edition: playertype == 'java' ? 'Java (PC)' : 'Bedrock (Konsolen und Handys)'
|
||||
@@ -80,17 +107,24 @@
|
||||
|
||||
let rulesAccepted = false;
|
||||
let rulesModal: HTMLDialogElement;
|
||||
let rulesModalSecondsOpened = 0;
|
||||
let rulesModalSecondsOpened = $state(0);
|
||||
// eslint-disable-next-line no-undef
|
||||
let rulesModalTimer: number | NodeJS.Timeout | undefined = undefined;
|
||||
|
||||
let inputsInvalidMessage: string | null = 'Bitte fülle alle erforderlichen Felder aus';
|
||||
let registerRequest: Promise<void> | null = null;
|
||||
|
||||
let errorMessage: string = '';
|
||||
let inputsInvalidMessage: string | null = $state('Bitte fülle alle erforderlichen Felder aus');
|
||||
let registerRequest: Promise<void> | null = $state(null);
|
||||
let errorMessage: string = $state('');
|
||||
</script>
|
||||
|
||||
<h1 class="text-center text-3xl lg:text-5xl">Anmeldung</h1>
|
||||
<form id="form" on:input={checkInputs} on:submit|preventDefault={sendRegister}>
|
||||
<form
|
||||
id="form"
|
||||
oninput={checkInputs}
|
||||
onsubmit={(e) => {
|
||||
e.preventDefault();
|
||||
sendRegister();
|
||||
}}
|
||||
>
|
||||
<div class="divider">Persönliche Angaben</div>
|
||||
<div class="mx-2 grid grid-cols-1 sm:grid-cols-2 gap-y-4">
|
||||
<Input
|
||||
@@ -100,7 +134,9 @@
|
||||
required={true}
|
||||
bind:inputElement={firstnameInput}
|
||||
>
|
||||
<span slot="label">Vorname</span>
|
||||
{#snippet label()}
|
||||
<span>Vorname</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Input
|
||||
id="lastname"
|
||||
@@ -109,7 +145,9 @@
|
||||
required={true}
|
||||
bind:inputElement={lastnameInput}
|
||||
>
|
||||
<span slot="label">Nachname</span>
|
||||
{#snippet label()}
|
||||
<span>Nachname</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Input
|
||||
id="birthday"
|
||||
@@ -118,8 +156,12 @@
|
||||
required={true}
|
||||
bind:inputElement={birthdayInput}
|
||||
>
|
||||
<span slot="label">Geburtstag</span>
|
||||
<span slot="notice">Die Angabe hat keine Auswirkungen auf das Spielgeschehen</span>
|
||||
{#snippet label()}
|
||||
<span>Geburtstag</span>
|
||||
{/snippet}
|
||||
{#snippet notice()}
|
||||
<span>Die Angabe hat keine Auswirkungen auf das Spielgeschehen</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Input
|
||||
id="telephone"
|
||||
@@ -128,12 +170,16 @@
|
||||
bind:inputElement={phoneInput}
|
||||
pattern={new RegExp(/^[+()\s/\d]+$/)}
|
||||
>
|
||||
<span slot="label">Telefonnummer</span>
|
||||
<p slot="notice">
|
||||
Diese nutzen wir, um Dich in der Whatsapp-Gruppe zuzuordnen und kontaktieren zu können.
|
||||
<br />
|
||||
<b>Die Angabe ist freiwillig, hilft den Administratoren jedoch sehr!</b>
|
||||
</p>
|
||||
{#snippet label()}
|
||||
<span>Telefonnummer</span>
|
||||
{/snippet}
|
||||
{#snippet notice()}
|
||||
<p>
|
||||
Diese nutzen wir, um Dich in der Whatsapp-Gruppe zuzuordnen und kontaktieren zu können.
|
||||
<br />
|
||||
<b>Die Angabe ist freiwillig, hilft den Administratoren jedoch sehr!</b>
|
||||
</p>
|
||||
{/snippet}
|
||||
</Input>
|
||||
</div>
|
||||
<div class="divider">Spiel</div>
|
||||
@@ -145,7 +191,9 @@
|
||||
required={true}
|
||||
bind:inputElement={usernameInput}
|
||||
>
|
||||
<span slot="label">Minecraft-Spielername</span>
|
||||
{#snippet label()}
|
||||
<span>Minecraft-Spielername</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Select
|
||||
id="playertype"
|
||||
@@ -158,7 +206,7 @@
|
||||
<option value="bedrock">Bedrock Edition (Konsolen und Handys)</option>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="divider" />
|
||||
<div class="divider"></div>
|
||||
<div class="mx-2 grid gap-y-3 mb-6">
|
||||
<div class="flex gap-4">
|
||||
<Input
|
||||
@@ -199,9 +247,9 @@
|
||||
name="rules"
|
||||
type="checkbox"
|
||||
required={true}
|
||||
on:input={(e) => {
|
||||
oninput={(e) => {
|
||||
if (!rulesAccepted) {
|
||||
e.detail.target.checked = false;
|
||||
e.currentTarget.checked = false;
|
||||
rulesModal.show();
|
||||
rulesModalTimer = setInterval(() => rulesModalSecondsOpened++, 1000);
|
||||
}
|
||||
@@ -211,7 +259,8 @@
|
||||
<label for="rules">
|
||||
Ich bin mit den <button
|
||||
class="link"
|
||||
on:click|preventDefault={() => {
|
||||
onclick={(e) => {
|
||||
e.preventDefault();
|
||||
rulesModal.show();
|
||||
rulesModalTimer = setInterval(() => rulesModalSecondsOpened++, 1000);
|
||||
}}>Regeln</button
|
||||
@@ -238,7 +287,7 @@
|
||||
{#await registerRequest}
|
||||
<span
|
||||
class="relative top-[calc(50%-12px)] left-[calc(50%-12px)] row-[1] col-[1] loading loading-ring"
|
||||
/>
|
||||
></span>
|
||||
{/await}
|
||||
{/if}
|
||||
{/key}
|
||||
@@ -247,7 +296,7 @@
|
||||
|
||||
<dialog
|
||||
class="modal"
|
||||
on:close={() => {
|
||||
onclose={() => {
|
||||
clearInterval(rulesModalTimer);
|
||||
rulesModalTimer = undefined;
|
||||
}}
|
||||
@@ -266,7 +315,7 @@
|
||||
<p>{rulesShort.header}</p>
|
||||
<p class="mt-1 text-[.75rem]">{rulesShort.footer}</p>
|
||||
</div>
|
||||
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" />
|
||||
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600"></span>
|
||||
</div>
|
||||
{#each rulesShort.sections as section, i}
|
||||
<div class="collapse collapse-arrow">
|
||||
@@ -278,10 +327,10 @@
|
||||
<p>{section.content}</p>
|
||||
</div>
|
||||
</div>
|
||||
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" />
|
||||
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600"></span>
|
||||
{/each}
|
||||
</div>
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
|
||||
<div
|
||||
class="relative w-min"
|
||||
title={rulesModalSecondsOpened < modalTimeoutSeconds
|
||||
@@ -290,7 +339,7 @@
|
||||
0
|
||||
)} Sekunden akzeptiert werden`
|
||||
: ''}
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
if (rulesModalSecondsOpened < modalTimeoutSeconds) {
|
||||
errorMessage =
|
||||
'Bitte lies die Regeln aufmerksam durch. Du kannst erst in einigen Sekunden fortfahren.';
|
||||
@@ -301,7 +350,7 @@
|
||||
<div
|
||||
style="width: {Math.min((rulesModalSecondsOpened / modalTimeoutSeconds) * 100, 100)}%"
|
||||
class="h-full bg-base-300"
|
||||
/>
|
||||
></div>
|
||||
</div>
|
||||
<Input
|
||||
id="rules-accept"
|
||||
@@ -309,7 +358,7 @@
|
||||
value="Akzeptieren"
|
||||
disabled={rulesModalSecondsOpened < modalTimeoutSeconds}
|
||||
containerClass="bg-transparent z-[1] relative"
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
rulesAccepted = true;
|
||||
rulesInput.checked = true;
|
||||
checkInputs();
|
||||
@@ -324,7 +373,7 @@
|
||||
</dialog>
|
||||
|
||||
{#if errorMessage}
|
||||
<dialog class="modal" on:close={() => setTimeout(() => (errorMessage = ''), 200)} open>
|
||||
<dialog class="modal" onclose={() => setTimeout(() => (errorMessage = ''), 200)} open>
|
||||
<form method="dialog" class="modal-box z-50">
|
||||
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
||||
<h3 class="font-bold text-2xl">Achtung</h3>
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import Input from '$lib/components/Input/Input.svelte';
|
||||
import Select from '$lib/components/Input/Select.svelte';
|
||||
|
||||
export let firstname: string;
|
||||
export let lastname: string;
|
||||
export let birthday: Date;
|
||||
export let phone: string | null;
|
||||
export let username: string;
|
||||
export let edition: string;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let {
|
||||
firstname,
|
||||
lastname,
|
||||
birthday,
|
||||
phone,
|
||||
username,
|
||||
edition,
|
||||
close
|
||||
}: {
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
birthday: Date;
|
||||
phone?: string;
|
||||
username: string;
|
||||
edition: string;
|
||||
close: () => void;
|
||||
} = $props();
|
||||
|
||||
let startDayOptions: Intl.DateTimeFormatOptions = {
|
||||
day: '2-digit',
|
||||
@@ -22,7 +31,7 @@
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
};
|
||||
let skin: string | null = null;
|
||||
let skin: string | null = $state(null);
|
||||
|
||||
onMount(async () => {
|
||||
let skinview3d = await import('skinview3d');
|
||||
@@ -70,16 +79,34 @@
|
||||
uns, dich auf unserem <a class="link" href={env.PUBLIC_TS_LINK} target="_blank">TeamSpeak</a> oder
|
||||
in unserem <a class="link" href={env.PUBLIC_DISCORD_LINK} target="_blank">Discord</a> begrüßen zu dürfen!
|
||||
</p>
|
||||
<div class="divider" />
|
||||
<div class="divider"></div>
|
||||
<div class="flex justify-around mt-2 mb-4">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 w-full sm:w-fit gap-x-4 gap-y-2">
|
||||
<Input value={firstname} size="sm" readonly><span slot="label">Vorname</span></Input>
|
||||
<Input value={lastname} size="sm" readonly><span slot="label">Nachname</span></Input>
|
||||
<Input value={birthday.toISOString().substring(0, 10)} type="date" size="sm" readonly
|
||||
><span slot="label">Geburtstag</span></Input
|
||||
<Input value={firstname} size="sm" readonly>
|
||||
{#snippet label()}
|
||||
<span>Vorname</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Input value={lastname} size="sm" readonly>
|
||||
{#snippet label()}
|
||||
<span>Nachname</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Input value={birthday.toISOString().substring(0, 10)} type="date" size="sm" readonly>
|
||||
{#snippet label()}
|
||||
<span>Geburtstag</span>
|
||||
{/snippet}</Input
|
||||
>
|
||||
<Input value={phone} size="sm" readonly><span slot="label">Telefonnummer</span></Input>
|
||||
<Input value={username} size="sm" readonly><span slot="label">Spielername</span></Input>
|
||||
<Input value={phone} size="sm" readonly>
|
||||
{#snippet label()}
|
||||
<span>Telefonnummer</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Input value={username} size="sm" readonly>
|
||||
{#snippet label()}
|
||||
<span>Spielername</span>
|
||||
{/snippet}
|
||||
</Input>
|
||||
<Select value="edition" size="sm" disabled label="Edition">
|
||||
<option value="edition">{edition}</option>
|
||||
</Select>
|
||||
@@ -88,11 +115,11 @@
|
||||
{#if skin}
|
||||
<img class="absolute" src={skin} alt="" />
|
||||
{:else}
|
||||
<span class="loading loading-spinner loading-lg" />
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider" />
|
||||
<div class="divider"></div>
|
||||
<div class="flex justify-center gap-8">
|
||||
<button class="btn" on:click={() => dispatch('close')}>Weitere Person anmelden</button>
|
||||
<button class="btn" onclick={close}>Weitere Person anmelden</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user