add strike reason admin panel

This commit is contained in:
2025-05-22 00:25:22 +02:00
parent 45f984e4da
commit a21d3d283a
11 changed files with 250 additions and 5 deletions

View File

@ -1,7 +1,7 @@
<script lang="ts">
import Icon from '@iconify/svelte';
import CrudPopup from '@components/admin/popup/CrudPopup.svelte';
import { fetchBlockedUsers, addBlockedUser } from '@app/admin/usersBlocked/usersBlocked.ts';
import { fetchBlockedUsers, addBlockedUser } from '@app/admin/blockedUsers/blockedUsers.ts';
// states
let createPopupOpen = $state(false);

View File

@ -0,0 +1,36 @@
<script>
import Icon from '@iconify/svelte';
import CrudPopup from '@components/admin/popup/CrudPopup.svelte';
import { addStrikeReason, fetchStrikeReasons } from '@app/admin/strikeReasons/strikeReasons.js';
// states
let createPopupOpen = $state(false);
// lifecycle
$effect(() => {
fetchStrikeReasons();
});
</script>
<div>
<button class="btn btn-soft w-full" onclick={() => (createPopupOpen = true)}>
<Icon icon="heroicons:plus-16-solid" />
<span>Neuer Strikegrund</span>
</button>
</div>
<CrudPopup
texts={{
title: 'Strikegrund erstellen',
submitButtonTitle: 'Erstellen',
confirmPopupTitle: 'Strikegrund erstellen?',
confirmPopupMessage: 'Soll der Strikegrund erstellt werden?'
}}
target={null}
keys={[
[{ key: 'name', type: 'text', label: 'Name', options: { required: true, dynamicWidth: true } }],
[{ key: 'weight', type: 'number', label: 'Gewichtung', options: { required: true, dynamicWidth: true } }]
]}
onSubmit={addStrikeReason}
bind:open={createPopupOpen}
/>

View File

@ -0,0 +1,56 @@
<script lang="ts">
import DataTable from '@components/admin/table/DataTable.svelte';
import {
deleteStrikeReason,
editStrikeReason,
type StrikeReason,
strikeReasons
} from '@app/admin/strikeReasons/strikeReasons.ts';
import { confirmPopupState } from '@components/popup/ConfirmPopup.ts';
import CrudPopup from '@components/admin/popup/CrudPopup.svelte';
// state
let editPopupStrikeReason = $state(null);
let editPopupOpen = $derived(!!editPopupStrikeReason);
// lifecycle
$effect(() => {
if (!editPopupOpen) editPopupStrikeReason = null;
});
// callback
function onBlockedUserDelete(strikeReason: StrikeReason) {
$confirmPopupState = {
title: 'Nutzer entblockieren?',
message: 'Soll der Nutzer wirklich entblockiert werden?\nDieser kann sich danach wieder registrieren.',
onConfirm: () => deleteStrikeReason(strikeReason)
};
}
</script>
<DataTable
data={strikeReasons}
count={true}
keys={[
{ key: 'name', label: 'Name', width: 20 },
{ key: 'weight', label: 'Gewichtung', width: 70, sortable: true }
]}
onDelete={onBlockedUserDelete}
onEdit={(strikeReason) => (editPopupStrikeReason = strikeReason)}
/>
<CrudPopup
texts={{
title: 'Strikegrund bearbeiten',
submitButtonTitle: 'Speichern',
confirmPopupTitle: 'Änderungen speichern',
confirmPopupMessage: 'Sollen die Änderungen gespeichert werden?'
}}
target={editPopupStrikeReason}
keys={[
[{ key: 'name', type: 'text', label: 'Name', options: { required: true, dynamicWidth: true } }],
[{ key: 'weight', type: 'number', label: 'Gewichtung', options: { required: true, dynamicWidth: true } }]
]}
onSubmit={editStrikeReason}
bind:open={editPopupOpen}
/>

View File

@ -0,0 +1,55 @@
import { type ActionReturnType, actions } from 'astro:actions';
import { writable } from 'svelte/store';
import { actionErrorPopup } from '@util/action.ts';
import { addToWritableArray, deleteFromWritableArray, updateWritableArray } from '@util/state.ts';
// types
export type StrikeReasons = Exclude<
ActionReturnType<typeof actions.report.strikeReasons>['data'],
undefined
>['strikeReasons'];
export type StrikeReason = StrikeReasons[0];
// state
export const strikeReasons = writable<StrikeReasons>([]);
// actions
export async function fetchStrikeReasons() {
const { data, error } = await actions.report.strikeReasons();
if (error) {
actionErrorPopup(error);
return;
}
strikeReasons.set(data.strikeReasons);
}
export async function addStrikeReason(strikeReason: StrikeReason) {
const { data, error } = await actions.report.addStrikeReason(strikeReason);
if (error) {
actionErrorPopup(error);
return;
}
addToWritableArray(strikeReasons, Object.assign(strikeReason, { id: data.id }));
}
export async function editStrikeReason(strikeReason: StrikeReason) {
const { error } = await actions.report.editStrikeReason(strikeReason);
if (error) {
actionErrorPopup(error);
return;
}
updateWritableArray(strikeReasons, strikeReason, (t) => t.id == strikeReason.id);
}
export async function deleteStrikeReason(strikeReason: StrikeReason) {
const { error } = await actions.report.deleteStrikeReason(strikeReason);
if (error) {
actionErrorPopup(error);
return;
}
deleteFromWritableArray(strikeReasons, (t) => t.id == strikeReason.id);
}