102 lines
2.2 KiB
Svelte
102 lines
2.2 KiB
Svelte
<script lang="ts">
|
||
import Edit from '$lib/icons/Edit.svelte';
|
||
import Trash from '$lib/icons/Trash.svelte';
|
||
import { tick } from 'svelte';
|
||
|
||
interface ListItem {
|
||
name: string;
|
||
token?: string;
|
||
// add other properties as needed
|
||
}
|
||
let {
|
||
list,
|
||
editedName = $bindable(),
|
||
currentName,
|
||
onSave = () => {},
|
||
onDelete = () => {}
|
||
} = $props();
|
||
|
||
let names = list.map((l: ListItem) => l.name);
|
||
let localName = $state(currentName);
|
||
let wasCancelled = $state(false);
|
||
|
||
// Automatisch berechneter Fehler
|
||
let error: string = $derived(validateName(localName));
|
||
|
||
// Manuell steuerbarer Fehlerstatus
|
||
let manualError = $state('');
|
||
|
||
console.log('EditableItem: Beginn', names, editedName);
|
||
|
||
let isEditing = $state(false);
|
||
let inputRef: HTMLInputElement;
|
||
|
||
// Validierungsfunktion
|
||
function validateName(name: 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.';
|
||
|
||
return '';
|
||
}
|
||
|
||
// Speichern, wenn gültig und zurück an Eltern
|
||
function commitIfValid() {
|
||
if (!error && !wasCancelled && localName != currentName) {
|
||
editedName = localName.trim();
|
||
onSave(editedName, currentName); //Eltern benachrichtigen
|
||
} else {
|
||
localName = currentName;
|
||
resetEdit();
|
||
}
|
||
}
|
||
|
||
// Abbrechen – Eingabe zurücksetzen
|
||
function resetEdit() {
|
||
wasCancelled = false;
|
||
manualError = '';
|
||
inputRef?.blur();
|
||
isEditing = false;
|
||
}
|
||
|
||
// Tastatursteuerung
|
||
function handleKeydown(event: KeyboardEvent) {
|
||
if (event.key === 'Enter') {
|
||
event.preventDefault();
|
||
commitIfValid();
|
||
} else if (event.key === 'Escape') {
|
||
event.preventDefault();
|
||
localName = currentName;
|
||
resetEdit();
|
||
}
|
||
}
|
||
|
||
async function startEdit() {
|
||
isEditing = true;
|
||
await tick();
|
||
inputRef?.focus();
|
||
}
|
||
</script>
|
||
|
||
<div>
|
||
<input
|
||
bind:this={inputRef}
|
||
bind:value={localName}
|
||
onblur={commitIfValid}
|
||
onkeydown={handleKeydown}
|
||
/>
|
||
<button onclick={startEdit}><Edit /></button>
|
||
<button onclick={() => onDelete(currentName)}><Trash /></button>
|
||
{#if manualError || error}
|
||
<p style="color: red;">{manualError || error}</p>
|
||
{/if}
|
||
</div>
|