127 lines
2.9 KiB
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>
|