Make better autocomplete selections
This commit is contained in:
@@ -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}
|
||||||
|
Reference in New Issue
Block a user