add feedback and report things
All checks were successful
deploy / build-and-deploy (/testvaro, /opt/website-test, website-test) (push) Successful in 22s
deploy / build-and-deploy (/varo, /opt/website, website) (push) Successful in 21s

This commit is contained in:
2025-06-21 14:45:39 +02:00
parent 9c49585873
commit ee8f595ecc
25 changed files with 898 additions and 57 deletions

View File

@@ -8,9 +8,9 @@
required?: boolean;
mustMatch?: boolean;
requestSuggestions: (query: string, limit: number) => Promise<string[]>;
requestSuggestions: (query: string, limit: number) => Promise<{ name: string; value: string }[]>;
onSubmit?: (value: string | null) => void;
onSubmit?: (value: { name: string; value: string } | null) => void;
}
// html bindings
@@ -21,7 +21,7 @@
// states
let inputValue = $derived(value);
let suggestions = $state<string[]>([]);
let suggestions = $state<{ name: string; value: string }[]>([]);
let matched = $state(false);
// callbacks
@@ -34,9 +34,9 @@
suggestions = await requestSuggestions(inputValue ?? '', 5);
let suggestion = suggestions.find((s) => s === inputValue);
let suggestion = suggestions.find((s) => s.name === inputValue);
if (suggestion != null) {
inputValue = value = suggestion;
inputValue = value = suggestion.name;
matched = true;
onSubmit?.(suggestion);
} else if (!mustMatch) {
@@ -49,8 +49,10 @@
}
}
function onSuggestionClick(suggestion: string) {
inputValue = value = suggestion;
function onSuggestionClick(name: string) {
const suggestion = suggestions.find((s) => s.name === name)!;
inputValue = value = suggestion.name;
suggestions = [];
onSubmit?.(suggestion);
}
@@ -77,7 +79,7 @@
bind:value={inputValue}
oninput={() => onSearchInput()}
onfocusin={() => onSearchInput()}
pattern={mustMatch && matched ? `^(${suggestions.join('|')})$` : undefined}
pattern={mustMatch && matched ? `^(${suggestions.map((s) => s.name).join('|')})$` : undefined}
/>
{#if suggestions.length > 0}
<ul class="absolute bg-base-200 w-full z-20 menu menu-sm rounded-box">
@@ -85,8 +87,8 @@
<li class="w-full text-left">
<button
class="block w-full overflow-hidden text-ellipsis whitespace-nowrap"
title={suggestion}
onclick={() => onSuggestionClick(suggestion)}>{suggestion}</button
title={suggestion.name}
onclick={() => onSuggestionClick(suggestion.name)}>{suggestion.name}</button
>
</li>
{/each}

View File

@@ -20,9 +20,6 @@
// inputs
let { id, value = $bindable(), label, readonly, required, mustMatch, onSubmit }: Props = $props();
// states
let teamSuggestionCache = $state<Teams>([]);
// functions
async function getSuggestions(query: string, limit: number) {
const { data, error } = await actions.team.teams({
@@ -35,17 +32,7 @@
return [];
}
teamSuggestionCache = data.teams;
return teamSuggestionCache.map((team) => team.name);
}
async function getTeamByTeamName(teamName: string) {
let team = teamSuggestionCache.find((team) => team.name === teamName);
if (!team) {
await getSuggestions(teamName, 5);
return await getTeamByTeamName(teamName);
}
return team;
return data.teams.map((team) => ({ name: team.name, value: team }));
}
</script>
@@ -57,5 +44,5 @@
{required}
{mustMatch}
requestSuggestions={async (teamName) => getSuggestions(teamName, 5)}
onSubmit={async (teamName) => onSubmit?.(teamName != null ? await getTeamByTeamName(teamName) : null)}
onSubmit={async (suggestion) => onSubmit?.(suggestion != null ? suggestion.value : null)}
/>

View File

@@ -20,9 +20,6 @@
// inputs
let { id, value = $bindable(), label, readonly, required, mustMatch, onSubmit }: Props = $props();
// states
let userSuggestionCache = $state<Users>([]);
// functions
async function getSuggestions(query: string, limit: number) {
const { data, error } = await actions.user.users({
@@ -35,17 +32,7 @@
return [];
}
userSuggestionCache = data.users;
return userSuggestionCache.map((user) => user.username);
}
async function getUserByUsername(username: string) {
let user = userSuggestionCache.find((user) => user.username === username);
if (!user) {
await getSuggestions(username, 5);
return await getUserByUsername(username);
}
return user;
return data.users.map((user) => ({ name: user.username, value: user }));
}
</script>
@@ -57,5 +44,5 @@
{required}
{mustMatch}
requestSuggestions={async (username) => getSuggestions(username, 5)}
onSubmit={async (username) => onSubmit?.(username != null ? await getUserByUsername(username) : null)}
onSubmit={async (suggestion) => onSubmit?.(suggestion != null ? suggestion.value : null)}
/>