Files
varo-website/src/pages/signup.astro

254 lines
9.0 KiB
Plaintext

---
import WebsiteLayout from '@layouts/website/WebsiteLayout.astro';
import Checkbox from '@components/input/Checkbox.svelte';
import Input from '@components/input/Input.svelte';
import RulesPopup from '@app/website/signup/RulesPopup.svelte';
import Popup from '@components/popup/Popup.svelte';
import TeamPopup from '@app/website/signup/TeamPopup.svelte';
import RegisteredPopup from '@app/website/signup/RegisteredPopup.svelte';
import { getSettings, SettingKey } from '@util/settings';
import { db } from '@db/database.ts';
import { DISCORD_LINK, PAYPAL_LINK, START_DATE, TEAMSPEAK_LINK } from 'astro:env/server';
const signupSetting = await getSettings(db, [
SettingKey.SignupEnabled,
SettingKey.SignupDisabledMessage,
SettingKey.SignupDisabledSubMessage
]);
const signupEnabled = signupSetting[SettingKey.SignupEnabled] ?? false;
const signupDisabledMessage = signupSetting[SettingKey.SignupDisabledMessage] ?? 'Anmeldung deaktiviert';
const signupDisabledSubMessage = signupSetting[SettingKey.SignupDisabledSubMessage] ?? '';
---
<WebsiteLayout title="Anmeldung" footer={false}>
<div
class="flex justify-center w-full min-h-screen bg-base-200"
class:list={[!signupEnabled ? 'max-h-screen overflow-hidden' : undefined]}
>
<div class="relative grid card w-11/12 xl:w-2/3 2xl:w-1/2 p-6 my-12 bg-base-100 shadow-lg h-min">
<h1 class="text-center text-3xl lg:text-5xl">Anmeldung</h1>
<form id="signup">
<div class="divider">Persönliche Angaben</div>
<div class="mx-2 grid grid-cols-1 sm:grid-cols-2 gap-x-4">
<Input
id="firstname"
type="text"
label="Vorname"
required
validation={{
pattern: '^\\p{L}{2,}',
hint: 'Bitte gib Deinen vollständigen Vornamen an, dieser muss mindestens aus 2 Zeichen bestehen.'
}}
dynamicWidth
/>
<Input
id="lastname"
type="text"
label="Nachname"
required
validation={{
pattern: '^\\p{L}{2,}',
hint: 'Bitte gib Deinen vollständigen Nachnamen an, dieser muss mindestens aus 2 Zeichen bestehen.'
}}
dynamicWidth
/>
<Input
id="birthday"
type="date"
label="Geburtstag"
required
validation={{
max: new Date(Date.now() - 1000 * 60 * 60 * 24 * 365 * 6).toLocaleDateString('sv-SE'),
hint: 'Bitte gib Deinen vollständigen Geburtstag und die korrekte Jahreszahl an. Du musst mindestens 6 Jahre alt sein.'
}}
dynamicWidth
>
<span slot="notice">Die Angabe hat keine Auswirkungen auf das Spielgeschehen.</span>
</Input>
<Input
id="phone"
type="tel"
label="Telefonnummer"
validation={{
pattern: '^[+\\(\\)\\s\\d]+$',
hint: 'Bitte gib Deine vollständige Telefonnummer an, diese darf keine ungültigen Zeichen enthalten'
}}
dynamicWidth
>
<span 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>
</span>
</Input>
</div>
<div class="divider">Spiel</div>
<div class="mx-2 grid grid-cols-1 sm:grid-cols-2 gap-x-4">
<Input id="username" type="text" label="Minecraft-Spielername" required dynamicWidth />
<Input id="teamMember" type="text" label="Mitspieler" required dynamicWidth>
<span slot="notice"
>Trage hier den Minecraft-Spielername des Mitspieler ein, mit dem du in ein Team möchtest. Auch dieser
muss bei seiner Anmeldung deinen Namen eintragen. Nur wenn ihr beide eure Namen gegenseitig eingetragen
habt, kann ein Team erstellt werden.</span
>
</Input>
</div>
<div class="divider"></div>
<div class="mx-2 grid gap-y-3 mb-6">
<Checkbox id="checkbox" required>
<span slot="label">
Ich bin mit der Speicherung meiner in der Anmeldung angegebenen, persönlichen Daten einverstanden. Siehe <a
class="link"
href="https://mhsl.eu/id.html"
target="_blank">Datenschutz</a
>
</span>
</Checkbox>
<Checkbox id="logs" required>
<span slot="label">
Ich bin mit der Speicherung in Form von Logs aller meiner, beim Spielen anfallenden, persönlichen Daten
durch den Server einverstanden
</span>
<span slot="notice" class="text-[.65rem]">
Dies betrifft jede Interaktion im Spiel und zugehörige Daten wie z.B. Chatnachrichten welche vom Minecraft
Client an den Server übermittelt werden
</span>
</Checkbox>
<Checkbox id="rules" required>
<span slot="label">
Ich bin mit den <a class="link" onclick="">Regeln</a> einverstanden und achte sie
</span>
</Checkbox>
</div>
<button class="btn btn-neutral">Anmeldung absenden</button>
</form>
</div>
</div>
</WebsiteLayout>
<RulesPopup client:idle />
<Popup client:idle />
<TeamPopup client:idle />
<RegisteredPopup
client:idle
discordLink={DISCORD_LINK}
paypalLink={PAYPAL_LINK}
teamspeakLink={TEAMSPEAK_LINK}
startDate={START_DATE}
/>
{
!signupEnabled && (
<div class="absolute top-0 left-0 w-full h-full bg-black/50 backdrop-blur-sm z-10 rounded-xl flex justify-center items-center flex-col pt-20 lg:pt-0 text-2xl sm:text-4xl">
<h1>{signupDisabledMessage}</h1>
<h3>{signupDisabledSubMessage}</h3>
</div>
)
}
<script>
import { actions } from 'astro:actions';
import { popupState } from '@components/popup/Popup';
import { rulesPopupState, rulesPopupRead } from '@app/website/signup/RulesPopup';
import { teamPopupName, teamPopupOpen } from '@app/website/signup/TeamPopup';
import { registeredPopupState } from '@app/website/signup/RegisteredPopup';
function setupClientValidation() {
const rulesCheckbox = document.getElementById('rules') as HTMLInputElement;
const rulesCheckboxRulesLink = rulesCheckbox.nextElementSibling!.querySelector('.link') as HTMLAnchorElement;
// add popup state subscriber to check when the accepted button is clicked
rulesPopupState.subscribe((value) => {
if (value == 'accepted') rulesCheckbox.checked = true;
});
// add click handler to open rules popup to rules checkbox
rulesCheckbox.addEventListener('click', (e) => {
if (!rulesPopupRead.get()) {
e.preventDefault();
rulesPopupState.set('open');
}
});
// add click handler to open rules popup when clicking the rules link in the rules checkbox label
rulesCheckboxRulesLink!.addEventListener('click', () => rulesPopupState.set('open'));
}
function setupForm() {
const form = document.getElementById('signup')! as HTMLFormElement;
// reset form on site (re-)load
form.reset();
const sendSignup = async () => {
const { data, error } = await actions.signup.signup({
firstname: form.firstname.value,
lastname: form.lastname.value,
birthday: form.birthday.value,
phone: form.phone.value,
username: form.username.value,
teamMember: form.teamMember.value,
teamName: teamPopupName.get()
});
// must be done in order to show the team popup again if it's closed or an error occurs
teamPopupName.set(null);
if (error) {
if (error.code == 'BAD_REQUEST') {
teamPopupOpen.set(true);
const close = teamPopupName.listen(() => {
close();
sendSignup();
});
} else if (error.code == 'CONFLICT' || error.code == 'FORBIDDEN') {
popupState.set({
type: 'error',
title: 'Fehler',
message: error.message
});
} else {
popupState.set({
type: 'error',
title: 'Fehler',
message: error.message
});
}
return;
}
registeredPopupState.set({
firstname: form.firstname.value,
lastname: form.lastname.value,
birthday: form.birthday.value,
phone: form.phone.value,
username: form.username.value,
team: data.team.name,
teamMember: form.teamMember.value,
teamColor: data.team.color
});
const cancel = registeredPopupState.subscribe((value) => {
if (value) return;
cancel();
form.reset();
});
};
form.addEventListener('submit', (e) => {
e.preventDefault();
sendSignup();
});
}
const pathname = document.location.pathname;
document.addEventListener('astro:page-load', () => {
if (document.location.pathname !== pathname) return;
setupClientValidation();
setupForm();
});
</script>