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 nameElement: HTMLTableCellElement;
let autocompleteList: HTMLUListElement; let autocompleteList: HTMLUListElement;
let foodSearch: main.Food[] = []; 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(); name = name.trim();
if (!name) { if (!name) {
@@ -38,16 +37,37 @@
function updateAutocomplete() { function updateAutocomplete() {
if (!per100Edited) if (!per100Edited)
GetLastPer100(name.trim()).then((res) => { 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) { if (res.success && res.data && name) {
foodSearch = res.data; foodSearch = res.data;
hiLiteIndex = -1;
} else { } else {
foodSearch = []; 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 }) { async function update(event: KeyboardEvent & { currentTarget: EventTarget & HTMLTableCellElement }) {
name = name.trim(); name = name.trim();
amount = amount.trim(); amount = amount.trim();
@@ -61,53 +81,48 @@
if (!per100Edited && event.currentTarget == per100Element) per100Edited = true; if (!per100Edited && event.currentTarget == per100Element) per100Edited = true;
if (event.key == "Enter") { if (event.key === "Enter") {
event.preventDefault(); event.preventDefault();
item.food = name;
item.description = description;
item.amount = parseInt(amount);
item.per100 = parseInt(per100);
const res = await CreateFood(item); // If suggestions are visible and we have a highlighted item or at least one suggestion
name = ""; if (foodSearch.length > 0) {
amount = ""; const selectedFood = hiLiteIndex >= 0 ? foodSearch[hiLiteIndex] : foodSearch[0];
// description = '' setInputVal(selectedFood);
per100 = "";
per100Edited = false;
if (!res.success) {
toast.error(`failed to create item with error ${res.error}`);
return; return;
} }
foodStore.update((value) => [res.data, ...value]); // Only submit if we have no suggestions visible
nameElement.focus(); if (name && amount && per100) {
foodSearch = []; 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) { function setInputVal(food: main.Food) {
name = food.food; name = food.food;
per100 = String(food.per100); per100 = String(food.per100);
amount = String(food.amount); amount = String(food.amount);
hiLiteIndex = null; hiLiteIndex = -1;
foodSearch = []; foodSearch = [];
} }
@@ -123,6 +138,7 @@
function handleFocusOut() { function handleFocusOut() {
timeout = setTimeout(() => { timeout = setTimeout(() => {
foodSearch = []; foodSearch = [];
hiLiteIndex = -1;
}, 100); }, 100);
} }
@@ -132,7 +148,7 @@
} }
</script> </script>
<!-- <svelte:window on:keydown={navigateList} /> --> <svelte:window on:keydown={navigateList} />
<template> <template>
<tr class="border-b border-gray-200 dark:border-gray-700 text-lg font-bold relative"> <tr class="border-b border-gray-200 dark:border-gray-700 text-lg font-bold relative">
@@ -180,7 +196,7 @@
{#if foodSearch.length > 0} {#if foodSearch.length > 0}
<ul bind:this={autocompleteList} class="z-50 fixed top-0 left-0 w-3/12 border border-x-gray-800"> <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} {#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} {/each}
</ul> </ul>
{/if} {/if}