Files
tatort/src/lib/components/EditableItem.svelte

127 lines
2.9 KiB
Svelte

<script lang="ts">
import Edit from '$lib/icons/Edit.svelte';
import Trash from '$lib/icons/Trash.svelte';
import { validateInput } from '$lib/helper/error-utils';
interface ListItem {
name: string;
token?: string;
// add other properties as needed
}
type Variant = '' | 'casename' | 'crimename';
export let inputValue: string = '';
export let variant: Variant = '';
export let existings: ListItem[];
export let id: number;
export let editable: boolean = true;
export let editing: boolean;
//CustomEvents:
export let editStart: (payload: {
id: number;
inputValue: string;
variant: Variant;
editing: boolean;
}) => void;
export let save: (payload: { newValue: string; oldValue: string; variant: Variant }) => void;
export let deleteItem: (payload: {
inputValue: string;
variant: Variant;
customEvent: Event;
}) => void;
export let cancel: () => void = () => {};
const existingNames = existings.map((item) => item.name);
export { classNames as class };
let internalValue = inputValue;
let oldValue = inputValue;
let showWarning = false;
$: errors = validateInput(oldValue, internalValue, { minLength: 3, existingNames });
function startEdit() {
oldValue = inputValue;
internalValue = inputValue;
editing = true;
editStart({ id, inputValue, variant, editing });
}
function cancelEdit() {
internalValue = oldValue;
editing = false;
showWarning = false;
console.log('Abgebrochen');
cancel();
}
function saveEdit(ev?: MouseEvent | KeyboardEvent) {
ev?.preventDefault();
ev?.stopPropagation();
const name = internalValue.trim();
if (errors.length !== 0) {
showWarning = true;
console.log('Abgebrochen', errors);
return;
}
if (!name) {
showWarning = true;
console.log('Abgebrochen', showWarning);
return;
}
if (existingNames.includes(name) && name !== oldValue.trim()) {
showWarning = true;
console.log('Abgebrochen', showWarning);
return;
}
editing = false;
showWarning = false;
save({ newValue: internalValue, oldValue, variant });
}
function handleKey(e: KeyboardEvent) {
if (e.key === 'Enter') saveEdit(e);
if (e.key === 'Escape') cancelEdit();
}
</script>
<div class="">
<div class="flex gap-x-2">
{#if editing}
<input
bind:value={internalValue}
on:keydown|preventDefault={handleKey}
on:blur|preventDefault|stopPropagation={cancelEdit}
class=""
class:bg-red-200={(showWarning && editing) || errors.length !== 0}
/>
{:else}
<span>{inputValue}</span>
{#if !editing && editable}
<button on:click|preventDefault|stopPropagation={startEdit}>
<Edit />
</button>
<button
on:click|preventDefault={(e: Event) => {
deleteItem({ inputValue, variant, customEvent: e });
}}
>
<Trash />
</button>
{/if}
{/if}
</div>
{#if editing && errors}
<p class="text-red-600 text-sm mt-1 font-medium">{errors[0]}</p>
{/if}
</div>