refactor admin crud popups
All checks were successful
deploy / build-and-deploy (push) Successful in 23s

This commit is contained in:
2025-05-21 17:22:20 +02:00
parent 8b18623232
commit e47268111a
46 changed files with 889 additions and 1041 deletions

View File

@@ -1,65 +1,72 @@
<script lang="ts">
import { teams } from './state.ts';
import type { Team } from './types.ts';
import { editTeam } from './actions.ts';
import Icon from '@iconify/svelte';
import SortableTr from '@components/admin/table/SortableTr.svelte';
import SortableTh from '@components/admin/table/SortableTh.svelte';
import CreateOrEditPopup from '@app/admin/teams/CreateOrEditPopup.svelte';
import { addTeam, teams } from '@app/admin/teams/teams.ts';
import DataTable from '@components/admin/table/DataTable.svelte';
import CrudPopup from '@components/admin/popup/CrudPopup.svelte';
// state
let editTeamPopupTeam = $state<Team | null>(null);
let editPopupTeam = $state(null);
let editPopupOpen = $derived(!!editPopupTeam);
// lifecycle
$effect(() => {
if (!editPopupOpen) editPopupTeam = null;
});
</script>
<div class="h-screen overflow-x-auto">
<table class="table table-pin-rows">
<thead>
<SortableTr data={teams}>
<SortableTh style="width: 5%">#</SortableTh>
<SortableTh style="width: 5%">Farbe</SortableTh>
<SortableTh style="width: 25%" key="name">Name</SortableTh>
<SortableTh style="width: 30%" key="memberOne.username">Spieler 1</SortableTh>
<SortableTh style="width: 30%" key="memberTwo.username">Spieler 2</SortableTh>
<SortableTh style="width: 5%"></SortableTh>
</SortableTr>
</thead>
<tbody>
{#each $teams as team, i (team.id)}
<tr class="hover:bg-base-200">
<td>{i + 1}</td>
<td>
<div class="rounded-sm w-3 h-3" style="background-color: {team.color}"></div>
</td>
<td>{team.name}</td>
{#if team.memberOne.id != null}
<td>{team.memberOne.username}</td>
{:else}
<td class="text-base-content/30">{team.memberOne.username}</td>
{/if}
{#if team.memberTwo.id != null}
<td>{team.memberTwo.username}</td>
{:else}
<td class="text-base-content/30">{team.memberTwo.username}</td>
{/if}
<td>
<button class="cursor-pointer" onclick={() => (editTeamPopupTeam = team)}>
<Icon icon="heroicons:pencil-square" />
</button>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{#snippet color(value: string)}
<div class="rounded-sm w-3 h-3" style="background-color: {value}"></div>
{/snippet}
{#key editTeamPopupTeam}
<CreateOrEditPopup
popupTitle="Team bearbeiten"
submitButtonTitle="Team bearbeiten"
confirmPopupTitle="Team bearbeiten"
confirmPopupMessage="Bist du sicher, dass du das Team bearbeiten möchtest?"
team={editTeamPopupTeam}
open={editTeamPopupTeam != null}
onSubmit={editTeam}
/>
{/key}
<DataTable
data={teams}
count={true}
keys={[
{ key: 'color', label: 'Farbe', width: 5, transform: color },
{ key: 'name', label: 'Name', width: 25 },
{ key: 'memberOne.username', label: 'Spieler 1', width: 30 },
{ key: 'memberTwo.username', label: 'Spieler 2', width: 30 }
]}
onEdit={(team) => (editPopupTeam = team)}
/>
<CrudPopup
texts={{
title: 'Team bearbeiten',
submitButtonTitle: 'Speichern',
confirmPopupTitle: 'Änderungen speichern?',
confirmPopupMessage: 'Sollen die Änderungen gespeichert werden?'
}}
target={editPopupTeam}
keys={[
[
{ key: 'name', type: 'text', label: 'Name', options: { required: true } },
{ key: 'color', type: 'color', label: 'Farbe', options: { required: true } }
],
[
{
key: 'memberOne',
type: 'user-search',
label: 'Spieler 1',
options: { required: true, validate: (user) => !!user.username }
},
{
key: 'memberTwo',
type: 'user-search',
label: 'Spieler 2',
default: { id: null, username: null },
options: { required: true, validate: (user) => !!user.username }
}
],
[
{
key: 'lastJoined',
type: 'datetime-local',
label: 'Zuletzt gejoined',
default: { id: null, username: null },
options: { convert: (date) => (date ? date : null) }
}
]
]}
onSubmit={addTeam}
bind:open={editPopupOpen}
/>