frontend/src/lib/components/ContactSelector.svelte (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
<script>
import { global } from "$lib/global.svelte.js";
let { onselect, exclude } = $props();
let contacts = $derived(global.contacts.filter(c => c.Emails.length));
let search = $state("");
let show = $state(false);
function searchText(contact) {
const parts = [
contact.Firstname,
contact.Lastname,
contact.Association,
contact.Job,
...contact.Emails.map(e => e.Value),
...contact.PhoneNumbers.map(p => p.Value),
...contact.Urls.map(u => u.Value),
...contact.StreetAddresses.map(s => `${s.Street1} ${s.Street2} ${s.City} ${s.State}`),
...contact.Dates.map(d => d.Value.slice(0,10)),
...contact.Other.map(o => o.Value),
];
const result = parts.join(" ").toLowerCase();
return result;
}
let filtered = $derived(
search
? contacts.filter(c => {
return searchText(c).includes(search.toLowerCase())
}) : contacts
);
let named = $derived(filtered.filter(c => c.Firstname || c.Lastname || c.Association));
let nameless = $derived(filtered.filter(c => !(c.Firstname || c.Lastname || c.Association)));
function pick(email) {
if (onselect) onselect(email);
show = false;
search = "";
}
function hide() {
setTimeout(() => { show = false; }, 200);
}
</script>
<div class="relative">
<input
class="w-full bg-header text-primary text-xs border-b-1 border-primary focus:outline-none"
type="text"
autofocus
bind:value={search}
onfocus={() => (show = true)}
onblur={hide}/>
{#if show && filtered.length > 0}
<ul class="flex flex-col absolute p-2 z-10 w-fit bg-header max-h-60 overflow-y-auto text-xs">
{#each named as contact}
<li class="border-b-1 border-primary">
<div class="px-2 py-1 font-semibold text-primary bg-header">
{contact.Firstname} {contact.Lastname}
{#if contact.Association}
<span class="text-primary">({contact.Association})</span>
{/if}
</div>
{#each contact.Emails as email}
<button
class="w-full text-left px-3 py-1 hover:bg-input focus:bg-selected"
onclick={() => pick(email)}>
{email.Value} ({email.Key})
</button>
{/each}
</li>
{/each}
{#each nameless as contact}
{#each contact.Emails as email}
<button
class="w-full text-left px-3 py-1 hover:bg-input focus:bg-selected"
onclick={() => pick(email)}>
{email.Value}
</button>
{/each}
{/each}
</ul>
{/if}
</div>
|