mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 14:15:28 +00:00
feat: add fuse.js search module
This commit is contained in:
@@ -1,24 +1,51 @@
|
||||
<script lang="ts">
|
||||
import type { Event } from '$lib/types';
|
||||
import type { Event, EventType } from '$lib/types';
|
||||
import { goto } from '$app/navigation';
|
||||
import type { PageData } from '../$types';
|
||||
import { formatTime, formatDate } from '$lib/dateFormatter';
|
||||
import Fuse from 'fuse.js';
|
||||
|
||||
let publicEvents: Event[] = [];
|
||||
let error = '';
|
||||
let searchQuery = '';
|
||||
let selectedEventType: EventType | 'all' = 'all';
|
||||
let fuse: Fuse<Event>;
|
||||
|
||||
export let data: PageData;
|
||||
// Use the server-side data
|
||||
$: publicEvents = data.events;
|
||||
|
||||
// Filter events based on search query
|
||||
$: filteredEvents =
|
||||
searchQuery.trim() === ''
|
||||
? publicEvents
|
||||
: publicEvents.filter((event) =>
|
||||
event.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
// Initialize Fuse.js with search options
|
||||
$: fuse = new Fuse(publicEvents, {
|
||||
keys: [
|
||||
{ name: 'name', weight: 0.7 },
|
||||
{ name: 'location', weight: 0.3 }
|
||||
],
|
||||
threshold: 0.3, // Lower threshold = more strict matching
|
||||
includeScore: true,
|
||||
includeMatches: true
|
||||
});
|
||||
|
||||
// Filter events based on search query and event type using Fuse.js
|
||||
$: filteredEvents = (() => {
|
||||
let events = publicEvents;
|
||||
|
||||
// First filter by event type
|
||||
if (selectedEventType !== 'all') {
|
||||
events = events.filter((event) => event.type === selectedEventType);
|
||||
}
|
||||
|
||||
// Then apply search query
|
||||
if (searchQuery.trim() !== '') {
|
||||
events = fuse.search(searchQuery).map((result) => result.item);
|
||||
// Re-apply type filter after search
|
||||
if (selectedEventType !== 'all') {
|
||||
events = events.filter((event) => event.type === selectedEventType);
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
})();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -61,45 +88,79 @@
|
||||
<p class="text-slate-500">Discover events created by the community</p>
|
||||
</div>
|
||||
|
||||
<!-- Search Bar -->
|
||||
<!-- Search and Filter Section -->
|
||||
<div class="mb-8">
|
||||
<div class="relative mx-auto max-w-md">
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<svg
|
||||
class="h-5 w-5 text-slate-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={searchQuery}
|
||||
placeholder="Search events by title..."
|
||||
class="w-full rounded-lg border border-slate-600 bg-slate-800 px-4 py-3 pl-10 text-white placeholder-slate-400 focus:border-violet-500 focus:ring-2 focus:ring-violet-500/20 focus:outline-none"
|
||||
/>
|
||||
{#if searchQuery}
|
||||
<button
|
||||
on:click={() => (searchQuery = '')}
|
||||
class="absolute inset-y-0 right-0 flex items-center pr-3 text-slate-400 hover:text-slate-300"
|
||||
>
|
||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-center">
|
||||
<!-- Search Bar -->
|
||||
<div class="relative mx-auto max-w-md sm:mx-0">
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||
<svg
|
||||
class="h-5 w-5 text-slate-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
bind:value={searchQuery}
|
||||
placeholder="Search events by name, location..."
|
||||
class="w-full rounded-lg border border-slate-600 bg-slate-800 px-4 py-3 pl-10 text-white placeholder-slate-400 focus:border-violet-500 focus:ring-2 focus:ring-violet-500/20 focus:outline-none"
|
||||
/>
|
||||
{#if searchQuery}
|
||||
<button
|
||||
on:click={() => (searchQuery = '')}
|
||||
class="absolute inset-y-0 right-0 flex items-center pr-3 text-slate-400 hover:text-slate-300"
|
||||
>
|
||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Event Type Filter -->
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
<button
|
||||
on:click={() => (selectedEventType = 'all')}
|
||||
class="rounded-sm border px-3 py-2 text-sm font-medium transition-colors {selectedEventType ===
|
||||
'all'
|
||||
? 'border-violet-500 bg-violet-500/20 text-violet-400'
|
||||
: 'border-slate-600 text-slate-400 hover:border-slate-500 hover:text-slate-300'}"
|
||||
>
|
||||
All
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
on:click={() => (selectedEventType = 'limited')}
|
||||
class="rounded-sm border px-3 py-2 text-sm font-medium transition-colors {selectedEventType ===
|
||||
'limited'
|
||||
? 'border-amber-600 bg-amber-600/20 text-amber-600'
|
||||
: 'border-slate-600 text-slate-400 hover:border-slate-500 hover:text-slate-300'}"
|
||||
>
|
||||
Limited
|
||||
</button>
|
||||
<button
|
||||
on:click={() => (selectedEventType = 'unlimited')}
|
||||
class="rounded-sm border px-3 py-2 text-sm font-medium transition-colors {selectedEventType ===
|
||||
'unlimited'
|
||||
? 'border-teal-500 bg-teal-500/20 text-teal-500'
|
||||
: 'border-slate-600 text-slate-400 hover:border-slate-500 hover:text-slate-300'}"
|
||||
>
|
||||
Unlimited
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user