Make better autocomplete selections

This commit is contained in:
2024-11-08 09:05:50 +01:00
parent 24546a4ef5
commit cb0d8860ed

View File

@@ -23,9 +23,8 @@
let nameElement: HTMLTableCellElement;
let autocompleteList: HTMLUListElement;
let foodSearch: main.Food[] = [];
let hiLiteIndex: number = -1;
// Maybe it would be a good idea to use $ instead of update down there...
// Maybe it's a topic for another day
$: {
name = name.trim();
if (!name) {
@@ -38,16 +37,37 @@
function updateAutocomplete() {
if (!per100Edited)
GetLastPer100(name.trim()).then((res) => {
// Prevent search when there's nothing to search
// Sometimes we get search results after deleting name
if (res.success && res.data && name) {
foodSearch = res.data;
hiLiteIndex = -1;
} else {
foodSearch = [];
}
});
}
async function handleSubmit() {
item.food = name;
item.description = description;
item.amount = parseInt(amount);
item.per100 = parseInt(per100);
const res = await CreateFood(item);
name = "";
amount = "";
per100 = "";
per100Edited = false;
if (!res.success) {
toast.error(`failed to create item with error ${res.error}`);
return;
}
foodStore.update((value) => [res.data, ...value]);
nameElement.focus();
foodSearch = [];
}
async function update(event: KeyboardEvent & { currentTarget: EventTarget & HTMLTableCellElement }) {
name = name.trim();
amount = amount.trim();
@@ -61,53 +81,48 @@
if (!per100Edited && event.currentTarget == per100Element) per100Edited = true;
if (event.key == "Enter") {
if (event.key === "Enter") {
event.preventDefault();
item.food = name;
item.description = description;
item.amount = parseInt(amount);
item.per100 = parseInt(per100);
const res = await CreateFood(item);
name = "";
amount = "";
// description = ''
per100 = "";
per100Edited = false;
if (!res.success) {
toast.error(`failed to create item with error ${res.error}`);
// If suggestions are visible and we have a highlighted item or at least one suggestion
if (foodSearch.length > 0) {
const selectedFood = hiLiteIndex >= 0 ? foodSearch[hiLiteIndex] : foodSearch[0];
setInputVal(selectedFood);
return;
}
foodStore.update((value) => [res.data, ...value]);
nameElement.focus();
foodSearch = [];
// Only submit if we have no suggestions visible
if (name && amount && per100) {
await handleSubmit();
}
}
}
function navigateList(e: KeyboardEvent) {
if (!foodSearch.length) return;
switch (e.key) {
case "ArrowDown":
e.preventDefault();
hiLiteIndex = Math.min(hiLiteIndex + 1, foodSearch.length - 1);
break;
case "ArrowUp":
e.preventDefault();
hiLiteIndex = Math.max(hiLiteIndex - 1, -1);
break;
case "Escape":
e.preventDefault();
foodSearch = [];
hiLiteIndex = -1;
break;
}
}
let hiLiteIndex: number | null = null;
// function navigateList(e: KeyboardEvent) {
// console.log(foodSearch, hiLiteIndex);
// // @ts-ignore shut the fuck up
// if (e.key == "ArrowDown" && hiLiteIndex <= foodSearch.length - 2) {
// hiLiteIndex == null ? (hiLiteIndex = 0) : (hiLiteIndex += 1);
// } else if (e.key == "ArrowUp" && hiLiteIndex !== null) {
// hiLiteIndex == 0 ? 0 : (hiLiteIndex -= 1);
// } else if (e.key == "Enter") {
// // @ts-ignore ITS NOT NULL YOU ASSHAT
// // WE CHECKED
// // ITS NOT
// setInputVal(foodSearch[hiLiteIndex]);
// } else {
// return;
// }
// }
function setInputVal(food: main.Food) {
name = food.food;
per100 = String(food.per100);
amount = String(food.amount);
hiLiteIndex = null;
hiLiteIndex = -1;
foodSearch = [];
}
@@ -123,6 +138,7 @@
function handleFocusOut() {
timeout = setTimeout(() => {
foodSearch = [];
hiLiteIndex = -1;
}, 100);
}
@@ -132,7 +148,7 @@
}
</script>
<!-- <svelte:window on:keydown={navigateList} /> -->
<svelte:window on:keydown={navigateList} />
<template>
<tr class="border-b border-gray-200 dark:border-gray-700 text-lg font-bold relative">
@@ -180,7 +196,7 @@
{#if foodSearch.length > 0}
<ul bind:this={autocompleteList} class="z-50 fixed top-0 left-0 w-3/12 border border-x-gray-800">
{#each foodSearch as f, i}
<FoodSearchEntry itemLabel={f.food} highlighted={i == hiLiteIndex} on:click={() => setInputVal(f)} />
<FoodSearchEntry itemLabel={f.food} highlighted={i === hiLiteIndex} on:click={() => setInputVal(f)} />
{/each}
</ul>
{/if}