118 lines
3.7 KiB
Svelte
118 lines
3.7 KiB
Svelte
<script lang="ts">
|
|
import UserSearch from '@components/admin/search/UserSearch.svelte';
|
|
import Input from '@components/input/Input.svelte';
|
|
import type { Team } from '@app/admin/teams/types.ts';
|
|
import { confirmPopupState } from '@components/popup/ConfirmPopup.ts';
|
|
|
|
// html bindings
|
|
let modal: HTMLDialogElement;
|
|
let modalForm: HTMLFormElement;
|
|
|
|
// types
|
|
interface Props {
|
|
popupTitle: string;
|
|
submitButtonTitle: string;
|
|
confirmPopupTitle: string;
|
|
confirmPopupMessage: string;
|
|
|
|
team: Team | null;
|
|
|
|
open: boolean;
|
|
|
|
onSubmit: (team: Team) => void;
|
|
onClose?: () => void;
|
|
}
|
|
|
|
// inputs
|
|
let { popupTitle, submitButtonTitle, confirmPopupTitle, confirmPopupMessage, team, open, onSubmit, onClose }: Props =
|
|
$props();
|
|
|
|
// states
|
|
let name = $state<string | null>(team?.name ?? null);
|
|
let color = $state<string | null>(team?.color ?? '#000000');
|
|
let lastJoined = $state<string | null>(team?.lastJoined ?? null);
|
|
let memberOne = $state<Team['memberOne']>(team?.memberOne ?? ({ username: null } as unknown as Team['memberOne']));
|
|
let memberTwo = $state<Team['memberOne']>(team?.memberTwo ?? ({ username: null } as unknown as Team['memberOne']));
|
|
|
|
let submitEnabled = $derived(!!(name && color && memberOne.username && memberTwo.username));
|
|
|
|
// lifecycle
|
|
$effect(() => {
|
|
if (open) modal.show();
|
|
});
|
|
|
|
// callbacks
|
|
async function onSaveButtonClick(e: Event) {
|
|
e.preventDefault();
|
|
$confirmPopupState = {
|
|
title: confirmPopupTitle,
|
|
message: confirmPopupMessage,
|
|
onConfirm: () => {
|
|
modalForm.submit();
|
|
onSubmit({
|
|
id: team?.id ?? -1,
|
|
name: name!,
|
|
color: color!,
|
|
lastJoined: lastJoined!,
|
|
memberOne: memberOne!,
|
|
memberTwo: memberTwo!
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
function onCancelButtonClick(e: Event) {
|
|
e.preventDefault();
|
|
modalForm.submit();
|
|
}
|
|
</script>
|
|
|
|
<dialog class="modal" bind:this={modal} onclose={() => setTimeout(() => onClose?.(), 300)}>
|
|
<form method="dialog" class="modal-box overflow-visible" bind:this={modalForm}>
|
|
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2" onclick={onCancelButtonClick}>✕</button>
|
|
<div class="space-y-5">
|
|
<h3 class="text-xl font-geist font-bold">{popupTitle}</h3>
|
|
<div class="w-full flex flex-col">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<Input type="color" label="Farbe" bind:value={color} required />
|
|
<Input type="text" label="Name" bind:value={name} required />
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<UserSearch
|
|
label="Spieler 1"
|
|
onSubmit={(user) => {
|
|
if (user) memberOne = user;
|
|
}}
|
|
bind:value={memberOne.username}
|
|
required
|
|
mustMatch
|
|
/>
|
|
<UserSearch
|
|
label="Spieler 2"
|
|
onSubmit={(user) => {
|
|
if (user) memberTwo = user;
|
|
}}
|
|
bind:value={memberTwo.username}
|
|
required
|
|
/>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<Input type="datetime-local" label="Zuletzt gejoined" bind:value={lastJoined}></Input>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<button
|
|
class="btn btn-success"
|
|
class:disabled={!submitEnabled}
|
|
disabled={!submitEnabled}
|
|
onclick={onSaveButtonClick}>{submitButtonTitle}</button
|
|
>
|
|
<button class="btn btn-error" type="button" onclick={onCancelButtonClick}>Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]">
|
|
<button class="!cursor-default">close</button>
|
|
</form>
|
|
</dialog>
|