Unassigned items filter

This commit is contained in:
2026-03-18 17:29:54 -05:00
parent c5b750bd08
commit 41803f4efa
@@ -1,6 +1,6 @@
import type { Component, Accessor } from 'solid-js';
import { Show, For } from 'solid-js';
import { ListTree } from 'lucide-solid';
import { Show, For, createSignal, createMemo } from 'solid-js';
import { ListTree, Search, X } from 'lucide-solid';
import ItemRow from '../ItemRow';
import LazyItem from '../LazyItem';
import type { EstimateItem } from '../../types';
@@ -20,6 +20,16 @@ interface UnassignedItemsSectionProps {
}
export const UnassignedItemsSection: Component<UnassignedItemsSectionProps> = (props) => {
const [filterText, setFilterText] = createSignal('');
const filteredItems = createMemo(() => {
const text = filterText().toLowerCase().trim();
if (!text) return props.unassignedItems;
return props.unassignedItems.filter(item =>
(item.description || '').toLowerCase().includes(text)
);
});
return (
<Show when={props.unassignedItems.length > 0}>
<div
@@ -39,9 +49,29 @@ export const UnassignedItemsSection: Component<UnassignedItemsSectionProps> = (p
<p class="text-muted-foreground text-sm">Drag these items into scopes to begin your estimate.</p>
</div>
</div>
<span class="px-4 py-1.5 bg-card border border-border text-primary rounded-full text-[10px] font-black uppercase tracking-widest shadow-sm">
{props.unassignedItems.length} Items Pending
</span>
<div class="flex items-center gap-4">
<div class="relative group/search">
<Search class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/40 group-focus-within/search:text-primary transition-colors" />
<input
type="text"
value={filterText()}
onInput={(e) => setFilterText(e.currentTarget.value)}
placeholder="Filter unassigned items..."
class="pl-10 pr-10 py-2 bg-card border border-border rounded-xl text-sm focus:border-primary focus:ring-4 focus:ring-primary/10 outline-none transition-all w-64 shadow-sm"
/>
<Show when={filterText()}>
<button
onClick={() => setFilterText('')}
class="absolute right-3 top-1/2 -translate-y-1/2 p-1 hover:bg-muted rounded-lg transition-all text-muted-foreground/40 hover:text-foreground"
>
<X class="w-3 h-3" />
</button>
</Show>
</div>
<span class="px-4 py-1.5 bg-card border border-border text-primary rounded-full text-[10px] font-black uppercase tracking-widest shadow-sm">
{filteredItems().length} of {props.unassignedItems.length} Items
</span>
</div>
</div>
<div
onClick={(e) => { if (e.target === e.currentTarget) props.clearSelection(e); }}
@@ -64,7 +94,7 @@ export const UnassignedItemsSection: Component<UnassignedItemsSectionProps> = (p
</div>
<div class="grid gap-2">
<For each={props.unassignedItems}>
<For each={filteredItems()}>
{(item) => (
<LazyItem estimatedHeight={60}>
<ItemRow