move components

This commit is contained in:
2025-05-20 20:34:50 +02:00
parent b610b30a78
commit 7e6a09563a
14 changed files with 16 additions and 27 deletions

View File

@@ -0,0 +1,102 @@
<script lang="ts">
import { registeredPopupState } from '@app/website/signup/RegisteredPopup.ts';
import Input from '@components/input/Input.svelte';
interface Props {
discordLink: string;
paypalLink: string;
teamspeakLink: string;
startDate: string;
}
let { discordLink, paypalLink, teamspeakLink, startDate }: Props = $props();
let skin: string | null = $state(null);
let modal: HTMLDialogElement;
registeredPopupState.subscribe(async (value) => {
if (!value) return;
modal.show();
const skinview3d = await import('skinview3d');
const skinViewer = new skinview3d.SkinViewer({
width: 200,
height: 300,
renderPaused: true
});
skinViewer.camera.rotation.x = -0.62;
skinViewer.camera.rotation.y = 0.534;
skinViewer.camera.rotation.z = 0.348;
skinViewer.camera.position.x = 30.5;
skinViewer.camera.position.y = 22.0;
skinViewer.camera.position.z = 42.0;
await skinViewer.loadSkin(`https://mc-heads.net/skin/${value.username}`);
skinViewer.render();
skin = skinViewer.canvas.toDataURL();
skinViewer.dispose();
});
</script>
<dialog class="modal" bind:this={modal} onclose={($registeredPopupState = null)}>
<form method="dialog" class="modal-box xl:w-5/12 max-w-10/12 z-10">
<h1 class="text-center text-xl sm:text-3xl mb-8">Registrierung erfolgreich</h1>
<p class="text-center font-bold">
<span>Du hast Dich erfolgreich mit dem Team&nbsp;&nbsp;</span>
<span class="inline-flex rounded-sm w-3 h-3" style="background-color: {$registeredPopupState?.teamColor}"></span>
<span>{$registeredPopupState?.team}</span>
<span>&nbsp;&nbsp;für Varo 4 registriert</span>. Spielstart ist am
<i>
{new Date(startDate).toLocaleString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' })}
</i>
um
<i>
{new Date(startDate).toLocaleString('de-DE', { hour: '2-digit', minute: '2-digit' })} Uhr
</i>.
</p>
<p class="text-center">Alle weiteren Informationen werden in der Whatsapp-Gruppe bekannt gegeben.</p>
<p class="mt-2">
Falls du uns unterstützen möchtest, kannst du dies ganz einfach über
<a class="link" href={paypalLink} target="_blank">PayPal</a>
tun. Antworten auf häufig gestellte Fragen findest du in unserer
<a class="link" href="faq" target="_blank">FAQ</a>. Außerdem freuen wir uns, dich auf unserem
<a class="link" href={teamspeakLink} target="_blank">TeamSpeak</a>
oder in unserem
<a class="link" href={discordLink} target="_blank">Discord</a>
begrüßen zu dürfen!
</p>
<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 type="text" value={$registeredPopupState?.firstname} label="Vorname" disabled />
<Input type="text" value={$registeredPopupState?.lastname} label="Nachname" disabled />
<Input
type="date"
value={$registeredPopupState?.birthday.toISOString().substring(0, 10)}
label="Geburtstag"
size="sm"
disabled
/>
<Input type="tel" value={$registeredPopupState?.phone} label="Telefonnummer" disabled />
<Input type="text" value={$registeredPopupState?.username} label="Spielername" disabled />
<Input type="text" value={$registeredPopupState?.teamMember} label="Mitspieler" disabled />
</div>
<div class="relative hidden md:flex justify-center w-[200px] my-4">
{#if skin}
<img class="absolute" src={skin} alt="" />
{:else}
<span class="loading loading-spinner loading-lg"></span>
{/if}
</div>
</div>
<div class="divider"></div>
<div class="flex justify-center gap-8">
<button class="btn">Weitere Person anmelden</button>
</div>
</form>
<div class="absolute w-full h-full bg-black/50"></div>
</dialog>

View File

@@ -0,0 +1,12 @@
import { atom } from 'nanostores';
export const registeredPopupState = atom<{
firstname: string;
lastname: string;
birthday: Date;
phone: string;
username: string;
team: string;
teamMember: string;
teamColor: string;
} | null>(null);

View File

@@ -0,0 +1,85 @@
<script lang="ts">
import { rulesPopupState, rulesPopupRead } from './RulesPopup.ts';
import { rules } from '../../../rules.ts';
const modalTimeoutSeconds = 30;
let modalElem: HTMLDialogElement;
let modalTimer = $state(null);
let modalSecondsOpen = $state(import.meta.env.PROD ? 0 : modalTimeoutSeconds);
rulesPopupState.listen((value) => {
if (value == 'open') {
modalElem.show();
setInterval(() => modalSecondsOpen++, 1000);
} else if (value == 'closed') {
clearInterval(modalTimer!);
}
});
</script>
<dialog
id="rules-popup"
class="modal"
onclose={() => {
if ($rulesPopupState !== 'accepted') $rulesPopupState = 'closed';
}}
bind:this={modalElem}
>
<form method="dialog" class="modal-box flex flex-col max-h-[90%] max-w-[95%] md:max-w-[90%] lg:max-w-[75%]">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
<div class="overflow-auto mt-5">
<div class="mb-4">
<div class="collapse collapse-arrow">
<input type="checkbox" autocomplete="off" checked />
<div class="collapse-title">
<p>0. Vorwort</p>
</div>
<div class="collapse-content">
<p>{rules.header}</p>
<p class="mt-1 text-[.75rem]">{rules.footer}</p>
</div>
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600"></span>
</div>
{#each rules.sections as section, i (section.title)}
<div class="collapse collapse-arrow">
<input type="checkbox" autocomplete="off" />
<div class="collapse-title">
<p>{i + 1}. {section.title}</p>
</div>
<div class="collapse-content">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html section.content}
</div>
</div>
<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600"></span>
{/each}
</div>
</div>
<div
class="relative w-min"
title={modalSecondsOpen < modalTimeoutSeconds
? `Regeln können in ${Math.max(modalTimeoutSeconds - modalSecondsOpen, 0)} Sekunden akzeptiert werden`
: ''}
>
<!--div class="absolute top-0 left-0 h-full w-full overflow-hidden rounded-lg">
<div
style="width: {Math.min((modalSecondsOpen / modalTimeoutSeconds) * 100, 100)}%"
class="h-full bg-base-300"
></div>
</div-->
<button
class="btn btn-neutral"
disabled={modalSecondsOpen < modalTimeoutSeconds}
onclick={() => {
$rulesPopupRead = true;
$rulesPopupState = 'accepted';
}}>Akzeptieren</button
>
</div>
</form>
<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]">
<button class="!cursor-default">close</button>
</form>
</dialog>

View File

@@ -0,0 +1,4 @@
import { atom } from 'nanostores';
export const rulesPopupState = atom<'open' | 'closed' | 'accepted'>('closed');
export const rulesPopupRead = atom(false);

View File

@@ -0,0 +1,30 @@
<script lang="ts">
import { teamPopupOpen, teamPopupName } from '@app/website/signup/TeamPopup.ts';
let modal: HTMLDialogElement;
let form: HTMLFormElement;
teamPopupOpen.subscribe((value) => {
if (value) modal.show();
else form?.reset();
});
</script>
<dialog class="modal" bind:this={modal} onclose={() => ($teamPopupOpen = false)}>
<div class="modal-box">
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"></button>
</form>
<form method="dialog" bind:this={form} onsubmit={() => ($teamPopupName = form.teamName.value)}>
<h3 class="text-lg font-geist">Team erstellen</h3>
<p class="py-4">Es wurde noch kein Team für dich und deinen Mitspieler erstellt.</p>
<fieldset class="fieldset">
<legend class="fieldset-legend">
<span>Teamname <span class="text-red-700">*</span></span>
</legend>
<input id="teamName" name="teamName" class="input validator" type="text" required />
</fieldset>
<button class="mt-4 btn btn-neutral">Team registrieren</button>
</form>
</div>
</dialog>

View File

@@ -0,0 +1,4 @@
import { atom } from 'nanostores';
export const teamPopupOpen = atom(false);
export const teamPopupName = atom<string | null>(null);