rewrite website
This commit is contained in:
54
src/app/admin/users/SidebarActions.svelte
Normal file
54
src/app/admin/users/SidebarActions.svelte
Normal file
@@ -0,0 +1,54 @@
|
||||
<script lang="ts">
|
||||
import Icon from '@iconify/svelte';
|
||||
import Input from '@components/input/Input.svelte';
|
||||
import CrudPopup from '@components/admin/popup/CrudPopup.svelte';
|
||||
import { addUser, fetchUsers } from '@app/admin/users/users.ts';
|
||||
|
||||
// states
|
||||
let usernameFilter = $state<string | null>(null);
|
||||
|
||||
let createPopupOpen = $state(false);
|
||||
|
||||
// lifecycle
|
||||
$effect(() => {
|
||||
fetchUsers({ username: usernameFilter });
|
||||
});
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<fieldset class="fieldset border border-base-content/50 rounded-box p-2">
|
||||
<legend class="fieldset-legend">Filter</legend>
|
||||
<Input bind:value={usernameFilter} label="Username" />
|
||||
</fieldset>
|
||||
<div class="divider my-1"></div>
|
||||
<button class="btn btn-soft w-full" onclick={() => (createPopupOpen = true)}>
|
||||
<Icon icon="heroicons:plus-16-solid" />
|
||||
<span>Neuer Nutzer</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<CrudPopup
|
||||
texts={{
|
||||
title: 'Nutzer erstellen',
|
||||
submitButtonTitle: 'Erstellen',
|
||||
confirmPopupTitle: 'Nutzer erstellen?',
|
||||
confirmPopupMessage: 'Sollen der neue Nutzer erstellt werden?'
|
||||
}}
|
||||
target={null}
|
||||
keys={[
|
||||
[
|
||||
{ key: 'firstname', type: 'text', label: 'Vorname', options: { required: true } },
|
||||
{ key: 'lastname', type: 'text', label: 'Nachname', options: { required: true } }
|
||||
],
|
||||
[
|
||||
{ key: 'birthday', type: 'date', label: 'Geburtstag', options: { required: true } },
|
||||
{ key: 'telephone', type: 'tel', label: 'Telefonnummer', default: null }
|
||||
],
|
||||
[
|
||||
{ key: 'username', type: 'text', label: 'Spielername', options: { required: true } },
|
||||
{ key: 'uuid', type: 'text', label: 'UUID', default: null }
|
||||
]
|
||||
]}
|
||||
onSubmit={addUser}
|
||||
bind:open={createPopupOpen}
|
||||
/>
|
||||
65
src/app/admin/users/Users.svelte
Normal file
65
src/app/admin/users/Users.svelte
Normal file
@@ -0,0 +1,65 @@
|
||||
<script lang="ts">
|
||||
import DataTable from '@components/admin/table/DataTable.svelte';
|
||||
import { deleteUser, editUser, type User, users } from '@app/admin/users/users.ts';
|
||||
import CrudPopup from '@components/admin/popup/CrudPopup.svelte';
|
||||
import { confirmPopupState } from '@components/popup/ConfirmPopup.ts';
|
||||
|
||||
// state
|
||||
let editPopupUser = $state(null);
|
||||
let editPopupOpen = $derived(!!editPopupUser);
|
||||
|
||||
// lifecycle
|
||||
$effect(() => {
|
||||
if (!editPopupOpen) editPopupUser = null;
|
||||
});
|
||||
|
||||
// callback
|
||||
function onUserDelete(user: User) {
|
||||
$confirmPopupState = {
|
||||
title: 'Nutzer löschen?',
|
||||
message: 'Soll der Nutzer wirklich gelöscht werden?',
|
||||
onConfirm: () => deleteUser(user)
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<DataTable
|
||||
data={users}
|
||||
count={true}
|
||||
keys={[
|
||||
{ key: 'firstname', label: 'Vorname', width: 15, sortable: true },
|
||||
{ key: 'lastname', label: 'Nachname', width: 15, sortable: true },
|
||||
{ key: 'birthday', label: 'Geburtstag', width: 5, sortable: true },
|
||||
{ key: 'telephone', label: 'Telefon', width: 12, sortable: true },
|
||||
{ key: 'username', label: 'Username', width: 20, sortable: true },
|
||||
{ key: 'uuid', label: 'UUID', width: 23 }
|
||||
]}
|
||||
onEdit={(user) => (editPopupUser = user)}
|
||||
onDelete={onUserDelete}
|
||||
/>
|
||||
|
||||
<CrudPopup
|
||||
texts={{
|
||||
title: 'Nutzer bearbeiten',
|
||||
submitButtonTitle: 'Speichern',
|
||||
confirmPopupTitle: 'Änderungen speichern?',
|
||||
confirmPopupMessage: 'Sollen die Änderungen gespeichert werden?'
|
||||
}}
|
||||
target={editPopupUser}
|
||||
keys={[
|
||||
[
|
||||
{ key: 'firstname', type: 'text', label: 'Vorname', options: { required: true } },
|
||||
{ key: 'lastname', type: 'text', label: 'Nachname', options: { required: true } }
|
||||
],
|
||||
[
|
||||
{ key: 'birthday', type: 'date', label: 'Geburtstag', options: { required: true } },
|
||||
{ key: 'telephone', type: 'tel', label: 'Telefonnummer' }
|
||||
],
|
||||
[
|
||||
{ key: 'username', type: 'text', label: 'Spielername', options: { required: true } },
|
||||
{ key: 'uuid', type: 'text', label: 'UUID' }
|
||||
]
|
||||
]}
|
||||
onSubmit={editUser}
|
||||
bind:open={editPopupOpen}
|
||||
/>
|
||||
69
src/app/admin/users/users.ts
Normal file
69
src/app/admin/users/users.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import { type ActionReturnType, actions } from 'astro:actions';
|
||||
import { actionErrorPopup } from '@util/action.ts';
|
||||
import { addToWritableArray, deleteFromWritableArray, updateWritableArray } from '@util/state.ts';
|
||||
|
||||
// types
|
||||
export type Users = Exclude<ActionReturnType<typeof actions.user.users>['data'], undefined>['users'];
|
||||
export type User = Users[0];
|
||||
|
||||
// state
|
||||
export const users = writable<Users>([]);
|
||||
|
||||
// actions
|
||||
export async function fetchUsers(options?: { username?: string | null }) {
|
||||
const { data, error } = await actions.user.users({ username: options?.username });
|
||||
if (error) {
|
||||
actionErrorPopup(error);
|
||||
return;
|
||||
}
|
||||
|
||||
users.set(data.users);
|
||||
}
|
||||
|
||||
export async function addUser(user: User) {
|
||||
const { data, error } = await actions.user.addUser({
|
||||
firstname: user.firstname,
|
||||
lastname: user.lastname,
|
||||
birthday: user.birthday,
|
||||
telephone: user.telephone,
|
||||
username: user.username,
|
||||
edition: user.edition,
|
||||
uuid: user.uuid
|
||||
});
|
||||
if (error) {
|
||||
actionErrorPopup(error);
|
||||
return;
|
||||
}
|
||||
|
||||
addToWritableArray(users, Object.assign(user, { id: data.id }));
|
||||
}
|
||||
|
||||
export async function editUser(user: User) {
|
||||
const { error } = await actions.user.editUser({
|
||||
id: user.id,
|
||||
firstname: user.firstname,
|
||||
lastname: user.lastname,
|
||||
birthday: user.birthday,
|
||||
telephone: user.telephone,
|
||||
username: user.username,
|
||||
edition: user.edition,
|
||||
uuid: user.uuid
|
||||
});
|
||||
if (error) {
|
||||
actionErrorPopup(error);
|
||||
return;
|
||||
}
|
||||
|
||||
updateWritableArray(users, user, (t) => t.id == user.id);
|
||||
}
|
||||
|
||||
export async function deleteUser(user: User) {
|
||||
const { error } = await actions.user.deleteUser({ id: user.id });
|
||||
if (error) {
|
||||
actionErrorPopup(error);
|
||||
return;
|
||||
}
|
||||
|
||||
deleteFromWritableArray(users, (t) => t.id == user.id);
|
||||
}
|
||||
Reference in New Issue
Block a user