feat(05-03): integrate filtering into EntryList with flat list mode
- Add filters and searchQuery props to EntryList - Apply filterEntries via $derived for reactive filtering - Display flat list (no pinned separation) when filtering - Show search-specific empty state when no matches - Pass searchQuery to EntryCard for highlighting
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type { Entry, Image, Tag } from '$lib/server/db/schema';
|
||||
import type { SearchFilters } from '$lib/types/search';
|
||||
import { filterEntries } from '$lib/utils/filterEntries';
|
||||
import { hasActiveFilters } from '$lib/types/search';
|
||||
import EntryCard from './EntryCard.svelte';
|
||||
|
||||
interface EntryWithData extends Entry {
|
||||
@@ -10,27 +13,50 @@
|
||||
interface Props {
|
||||
entries: EntryWithData[];
|
||||
availableTags: Tag[];
|
||||
filters: SearchFilters;
|
||||
searchQuery: string;
|
||||
}
|
||||
|
||||
let { entries, availableTags }: Props = $props();
|
||||
let { entries, availableTags, filters, searchQuery }: Props = $props();
|
||||
|
||||
// Separate entries into pinned and unpinned
|
||||
let pinnedEntries = $derived(entries.filter(e => e.pinned));
|
||||
let unpinnedEntries = $derived(entries.filter(e => !e.pinned));
|
||||
// Apply filtering
|
||||
let filteredEntries = $derived(filterEntries(entries, filters));
|
||||
let isFiltering = $derived(hasActiveFilters(filters));
|
||||
|
||||
// Separate entries into pinned and unpinned (only used when not filtering)
|
||||
let pinnedEntries = $derived(filteredEntries.filter((e) => e.pinned));
|
||||
let unpinnedEntries = $derived(filteredEntries.filter((e) => !e.pinned));
|
||||
</script>
|
||||
|
||||
{#if entries.length === 0}
|
||||
<div class="text-center py-12 text-gray-500">
|
||||
<p class="text-lg">No entries yet</p>
|
||||
<p class="text-sm mt-1">Use the capture bar below to add your first entry</p>
|
||||
{#if filteredEntries.length === 0}
|
||||
{#if isFiltering}
|
||||
<div class="text-center py-12 text-gray-500">
|
||||
<p class="text-lg">No entries match your search</p>
|
||||
<p class="text-sm mt-1">Try adjusting your filters or search term</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-center py-12 text-gray-500">
|
||||
<p class="text-lg">No entries yet</p>
|
||||
<p class="text-sm mt-1">Use the capture bar below to add your first entry</p>
|
||||
</div>
|
||||
{/if}
|
||||
{:else if isFiltering}
|
||||
<!-- Flat list when filtering (no pinned/unpinned separation) -->
|
||||
<div class="divide-y divide-gray-100 md:divide-y-0 md:space-y-3">
|
||||
{#each filteredEntries as entry (entry.id)}
|
||||
<EntryCard {entry} {availableTags} {searchQuery} />
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Normal view with pinned/unpinned separation -->
|
||||
{#if pinnedEntries.length > 0}
|
||||
<div class="mb-4">
|
||||
<h2 class="text-sm font-medium text-gray-500 uppercase tracking-wide mb-2 px-4 md:px-0">Pinned</h2>
|
||||
<h2 class="text-sm font-medium text-gray-500 uppercase tracking-wide mb-2 px-4 md:px-0">
|
||||
Pinned
|
||||
</h2>
|
||||
<div class="divide-y divide-gray-100 md:divide-y-0 md:space-y-3">
|
||||
{#each pinnedEntries as entry (entry.id)}
|
||||
<EntryCard {entry} {availableTags} />
|
||||
<EntryCard {entry} {availableTags} {searchQuery} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@@ -39,7 +65,7 @@
|
||||
{#if unpinnedEntries.length > 0}
|
||||
<div class="divide-y divide-gray-100 md:divide-y-0 md:space-y-3">
|
||||
{#each unpinnedEntries as entry (entry.id)}
|
||||
<EntryCard {entry} {availableTags} />
|
||||
<EntryCard {entry} {availableTags} {searchQuery} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user