initial commit
Some checks failed
deploy / build-and-deploy (push) Failing after 21s

This commit is contained in:
2025-05-18 13:16:20 +02:00
commit 60f3f8a096
148 changed files with 17900 additions and 0 deletions

226
src/pages/signup.astro Normal file
View File

@@ -0,0 +1,226 @@
---
import SignupLayout from '@layouts/website/SignupLayout.astro';
import Checkbox from '@components/input/Checkbox.svelte';
import Input from '@components/input/Input.svelte';
import RulesPopup from '@components/website/signup/RulesPopup.svelte';
import Popup from '@components/popup/Popup.svelte';
import TeamPopup from '@components/website/signup/TeamPopup.svelte';
import RegisteredPopup from '@components/website/signup/RegisteredPopup.svelte';
import { getSettings, SettingKey } from '@util/settings';
import { db } from '@db/database.ts';
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] ?? '';
---
<SignupLayout signupEnabled={signupEnabled}>
<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: '^\\w{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: '^\\w{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>
</SignupLayout>
<RulesPopup client:idle />
<Popup client:idle />
<TeamPopup client:idle />
<RegisteredPopup client:idle />
{
!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 '@components/website/signup/RulesPopup';
import { teamPopupName, teamPopupOpen } from '@components/website/signup/TeamPopup';
import { registeredPopupState } from '@components/website/signup/RegisteredPopup';
/* ----- client validation ----- */
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'));
/* send signup */
const form = document.getElementById('signup')! as HTMLFormElement;
async function sendSignup() {
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();
});
</script>