95 lines
1.9 KiB
Svelte
95 lines
1.9 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 localName = $state(currentName);
|
|
let wasCancelled = $state(false);
|
|
|
|
let error: string = $derived(validateName(localName));
|
|
|
|
let manualError = $state('');
|
|
|
|
let isEditing = $state(false);
|
|
let inputRef: HTMLInputElement;
|
|
|
|
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 '';
|
|
}
|
|
|
|
function commitIfValid() {
|
|
if (!error && !wasCancelled && localName != currentName) {
|
|
editedName = localName.trim();
|
|
inputRef?.blur();
|
|
isEditing = false;
|
|
onSave(editedName, currentName);
|
|
} else {
|
|
localName = currentName;
|
|
resetEdit();
|
|
}
|
|
}
|
|
|
|
function resetEdit() {
|
|
wasCancelled = false;
|
|
manualError = '';
|
|
inputRef?.blur();
|
|
isEditing = false;
|
|
}
|
|
|
|
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>
|