feat(isac): add searchable gear assignments

This commit is contained in:
JB
2026-07-25 14:31:42 -04:00
parent e30d4e4598
commit ff7f3a6d34
4 changed files with 29 additions and 14 deletions
+15 -7
View File
@@ -1,17 +1,25 @@
<script lang="ts">
type Item = { id: string; name: string };
type Item = { id: string; name: string; pending?: boolean; proposerName?: string };
let {
items,
selected = $bindable<string[]>([]),
excludedIds = [],
fieldName,
emptyLabel = 'NO MATCHING RECORDS'
emptyLabel = 'NO MATCHING RECORDS',
subjectLabel = 'TALENTS',
searchLabel = `FILTER AVAILABLE ${subjectLabel}`,
searchPlaceholder = `Search ${subjectLabel.toLocaleLowerCase()}…`,
emptySelectionLabel = `NO ${subjectLabel} ASSIGNED`
}: {
items: Item[];
selected?: string[];
excludedIds?: string[];
fieldName: string;
emptyLabel?: string;
subjectLabel?: string;
searchLabel?: string;
searchPlaceholder?: string;
emptySelectionLabel?: string;
} = $props();
let query = $state('');
const normalizedQuery = $derived(query.normalize('NFKC').trim().toLocaleLowerCase());
@@ -32,18 +40,18 @@
<div class="assignment-summary"><span>ASSIGNED</span><b>{selected.length}</b></div>
<div class="assignment-chips">
{#each selectedItems as item}
<button type="button" onclick={() => toggle(item.id)} aria-label={`Remove ${item.name}`}><span>{item.name}</span><b>×</b></button>
<button type="button" class:pending-reference={item.pending} onclick={() => toggle(item.id)} aria-label={`Remove ${item.name}`}><span>{item.name}{#if item.pending}<small>PENDING</small>{/if}</span><b>×</b></button>
{:else}
<small>NO TALENTS ASSIGNED</small>
<small>{emptySelectionLabel}</small>
{/each}
</div>
</div>
<label class="assignment-search"><span>FILTER AVAILABLE TALENTS</span><input type="search" bind:value={query} placeholder="Search by talent name…" autocomplete="off"/></label>
<label class="assignment-search"><span>{searchLabel}</span><input type="search" bind:value={query} placeholder={searchPlaceholder} autocomplete="off"/></label>
<div class="assignment-results-head"><span>{available.length} MATCHES</span>{#if available.length > visible.length}<b>SHOWING FIRST {visible.length}</b>{/if}</div>
<div class="assignment-results" role="list">
{#each visible as item}
<button type="button" class:selected={selected.includes(item.id)} aria-pressed={selected.includes(item.id)} onclick={() => toggle(item.id)}>
<span>{item.name}</span><b>{selected.includes(item.id) ? 'ASSIGNED' : 'ADD +'}</b>
<button type="button" class:selected={selected.includes(item.id)} class:pending-reference={item.pending} aria-pressed={selected.includes(item.id)} onclick={() => toggle(item.id)}>
<span>{item.name}{#if item.pending}<small>PENDING · {item.proposerName ?? 'CONTRIBUTOR'}</small>{/if}</span><b>{selected.includes(item.id) ? 'ASSIGNED' : 'ADD +'}</b>
</button>
{:else}
<p>{emptyLabel}</p>