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">
|
<script lang="ts">
|
||||||
import type { Entry, Image, Tag } from '$lib/server/db/schema';
|
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';
|
import EntryCard from './EntryCard.svelte';
|
||||||
|
|
||||||
interface EntryWithData extends Entry {
|
interface EntryWithData extends Entry {
|
||||||
@@ -10,27 +13,50 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
entries: EntryWithData[];
|
entries: EntryWithData[];
|
||||||
availableTags: Tag[];
|
availableTags: Tag[];
|
||||||
|
filters: SearchFilters;
|
||||||
|
searchQuery: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { entries, availableTags }: Props = $props();
|
let { entries, availableTags, filters, searchQuery }: Props = $props();
|
||||||
|
|
||||||
// Separate entries into pinned and unpinned
|
// Apply filtering
|
||||||
let pinnedEntries = $derived(entries.filter(e => e.pinned));
|
let filteredEntries = $derived(filterEntries(entries, filters));
|
||||||
let unpinnedEntries = $derived(entries.filter(e => !e.pinned));
|
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>
|
</script>
|
||||||
|
|
||||||
{#if entries.length === 0}
|
{#if filteredEntries.length === 0}
|
||||||
<div class="text-center py-12 text-gray-500">
|
{#if isFiltering}
|
||||||
<p class="text-lg">No entries yet</p>
|
<div class="text-center py-12 text-gray-500">
|
||||||
<p class="text-sm mt-1">Use the capture bar below to add your first entry</p>
|
<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>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
|
<!-- Normal view with pinned/unpinned separation -->
|
||||||
{#if pinnedEntries.length > 0}
|
{#if pinnedEntries.length > 0}
|
||||||
<div class="mb-4">
|
<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">
|
<div class="divide-y divide-gray-100 md:divide-y-0 md:space-y-3">
|
||||||
{#each pinnedEntries as entry (entry.id)}
|
{#each pinnedEntries as entry (entry.id)}
|
||||||
<EntryCard {entry} {availableTags} />
|
<EntryCard {entry} {availableTags} {searchQuery} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -39,7 +65,7 @@
|
|||||||
{#if unpinnedEntries.length > 0}
|
{#if unpinnedEntries.length > 0}
|
||||||
<div class="divide-y divide-gray-100 md:divide-y-0 md:space-y-3">
|
<div class="divide-y divide-gray-100 md:divide-y-0 md:space-y-3">
|
||||||
{#each unpinnedEntries as entry (entry.id)}
|
{#each unpinnedEntries as entry (entry.id)}
|
||||||
<EntryCard {entry} {availableTags} />
|
<EntryCard {entry} {availableTags} {searchQuery} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user