fixed tests and Code edit and delete Name in TatortList

This commit is contained in:
2025-09-11 16:52:54 +02:00
parent 47ca05f2d4
commit bcf24122bc
4 changed files with 139 additions and 128 deletions

View File

@@ -8,35 +8,33 @@
interface ListItem {
name: string;
token?: string;
// add other properties as needed
}
let { list, currentName, onSave = () => {}, onDelete = () => {} } = $props();
let localName = $state(currentName);
let isEditing = $state(false);
export let list: ListItem[] = [];
export let currentName: string = '';
export let onSave: (n: string, o: string) => unknown = () => {};
export let onDelete: (n: string) => unknown = () => {};
let error = $derived(() => validateName(localName));
// lokaler State
let localName = currentName;
let isEditing = false;
let inputRef: HTMLInputElement | null = null;
let inputRef = $state<HTMLInputElement | null>(null);
function validateName(name: string | undefined | null) {
if (!name) return 'Name darf nicht leer sein.';
const trimmed = name.trim();
$: error = validateName(localName);
function validateName(name: string): string {
const trimmed = name?.trim() ?? '';
if (!trimmed) return 'Name darf nicht leer sein.';
const duplicate = list.some(
(item: ListItem) => item.name === trimmed && item.name !== currentName
);
if (duplicate) return 'Name existiert bereits.';
if (list.some((item) => item.name === trimmed && item.name !== currentName)) {
return 'Name existiert bereits.';
}
return '';
}
function startEdit() {
async function startEdit() {
isEditing = true;
tick().then(() => inputRef?.focus());
await tick();
inputRef?.focus();
}
function cancelEdit() {
@@ -45,7 +43,7 @@
}
function commitEdit() {
if (!error() && localName != currentName) onSave(localName, currentName);
if (!error && localName != currentName) onSave(localName, currentName);
isEditing = false;
}
@@ -54,6 +52,10 @@
if (event.key === 'Enter') commitEdit();
if (event.key === 'Escape') cancelEdit();
}
function handleDeleteClick() {
onDelete(currentName);
}
</script>
<div data-testid="test-nameItemEditor">
@@ -64,14 +66,18 @@
bind:value={localName}
onkeydown={handleKeydown}
/>
<button data-testid="commit-button" onclick={commitEdit}><Check /></button>
<button
data-testid="commit-button"
disabled={!!error || localName === currentName}
onclick={commitEdit}><Check /></button
>
<button data-testid="cancel-button" onclick={cancelEdit}><X /></button>
{:else}
<span>{localName}</span>
<button data-testid="edit-button" onclick={startEdit}><Edit /></button>
<button data-testid="delete-button" onclick={() => onDelete(currentName)}><Trash /></button>
<button data-testid="delete-button" onclick={handleDeleteClick}><Trash /></button>
{/if}
{#if error()}
<p class="text-red-500">{error()}</p>
{#if error}
<p class="text-red-500">{error}</p>
{/if}
</div>

View File

@@ -26,11 +26,12 @@
// add other properties as needed
}
// 2) Lokaler, reaktiver State mit $state
let crimesList = $state<ListItem[]>(data.crimesList);
let vorgangName: string = data.vorgang.vorgangName;
let crimesList: ListItem[] = $state(data.crimesList);
const vorgangPIN: string = data.vorgang.vorgangPIN;
let vorgangToken: string = data.vorgang.vorgangToken;
let isEmptyList = $derived(crimesList && crimesList.length === 0);
let isEmptyList = $derived(crimesList.length === 0);
//Variablen für Modal
let open = $state(false);
@@ -38,11 +39,12 @@
let isError = $state(false);
//Variable um nur admin UI anzuzeigen
let admin = data?.user?.admin;
let admin = $state(data?.user?.admin);
async function handleSave(newName: string, oldName: string) {
open = true;
inProgress = true;
isError = false;
console.log('debug handleSave', newName, oldName);
try {
@@ -54,20 +56,15 @@
body: JSON.stringify({ vorgangToken, oldName, newName })
});
if (res.ok) {
inProgress = false;
invalidateAll();
data.crimesList = newName;
open = false;
} else {
inProgress = false;
isError = true;
if (!res.ok) {
throw new Error('Fehler beim Speichern');
}
await invalidateAll();
open = false;
} catch (err) {
console.error('⚠️ Netzwerkfehler beim Speichern', err);
isError = true;
inProgress = false;
console.error('⚠️ Netzwerkfehler:', err);
} finally {
inProgress = false;
}
}
@@ -75,32 +72,31 @@
async function handleDelete(tatort: string) {
open = true;
inProgress = true;
let url = new URL(data.url);
url.pathname += `/${tatort}`;
isError = false;
let path = new URL(data.url).pathname;
path += `/${tatort}`;
try {
const res = await fetch(`/api${url.pathname}`, {
const res = await fetch(`/api${path}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ vorgangToken, tatort })
})
.then(() => {
inProgress = false;
console.log('🗑️ Erfolgreich gelöscht:', url.pathname);
invalidateAll();
crimesList = data.crimesList;
})
.catch((err) => {
isError = true;
inProgress = false;
console.error('ERROR', err);
});
});
if (!res.ok) {
throw new Error('Fehler beim Löschen');
}
crimesList = crimesList.filter((i) => i.name !== tatort);
await invalidateAll();
console.log('🗑️ Erfolgreich gelöscht:', path);
open = false;
} catch (err) {
console.error('⚠️ Netzwerkfehler beim Speichern', err);
isError = true;
} finally {
inProgress = false;
console.error('⚠️ Netzwerkfehler beim Löschen:', err);
}
}
@@ -129,7 +125,7 @@ Mit freundlichen Grüßen,
}
</script>
{#if data.vorgang && data.crimesList}
{#if data.vorgang && crimesList}
<div class="-z-10 bg-white">
<div class="flex flex-col items-center justify-center w-full">
<h1 class="text-xl">Vorgang {vorgangName}</h1>
@@ -146,7 +142,7 @@ Mit freundlichen Grüßen,
{#if isEmptyList}
<EmptyList></EmptyList>
{:else}
{#each data.crimesList as item}
{#each crimesList as item (item.name)}
<li data-testid="test-list-item">
<div class=" flex gap-x-4">
<a
@@ -161,7 +157,7 @@ Mit freundlichen Grüßen,
<div class="min-w-0 flex-auto">
{#if admin}
<NameItemEditor
list={data.crimesList}
list={crimesList}
currentName={item.name}
onSave={handleSave}
onDelete={handleDelete}