From 7d1991eb9460d3456418d2b4fb7cad74fa4bbba2 Mon Sep 17 00:00:00 2001 From: Levente Orban Date: Mon, 1 Sep 2025 15:10:13 +0200 Subject: [PATCH] feat: add a filter toggle --- src/lib/dateFormatter.ts | 12 -- src/lib/dateHelpers.ts | 40 ++++++ src/routes/discover/+page.svelte | 224 ++++++++++++++++------------- src/routes/event/+page.svelte | 2 +- src/routes/event/[id]/+page.svelte | 2 +- 5 files changed, 168 insertions(+), 112 deletions(-) delete mode 100644 src/lib/dateFormatter.ts create mode 100644 src/lib/dateHelpers.ts diff --git a/src/lib/dateFormatter.ts b/src/lib/dateFormatter.ts deleted file mode 100644 index a68d3b9..0000000 --- a/src/lib/dateFormatter.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const formatDate = (dateString: string): string => { - const date = new Date(dateString); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - return `${year}/${month}/${day}`; -}; - -export const formatTime = (timeString: string): string => { - const [hours, minutes] = timeString.split(':'); - return `${hours}:${minutes}`; -}; diff --git a/src/lib/dateHelpers.ts b/src/lib/dateHelpers.ts new file mode 100644 index 0000000..d9536c5 --- /dev/null +++ b/src/lib/dateHelpers.ts @@ -0,0 +1,40 @@ +import type { Event } from './types'; + +export const formatDate = (dateString: string): string => { + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}/${month}/${day}`; +}; + +export const formatTime = (timeString: string): string => { + const [hours, minutes] = timeString.split(':'); + return `${hours}:${minutes}`; +}; + +// Helper function to check if an event is within a time range +export const isEventInTimeRange = (event: Event, timeFilter: string): boolean => { + if (timeFilter === 'any') return true; + + const eventDate = new Date(`${event.date}T${event.time}`); + const now = new Date(); + + // Handle temporal status filters + if (timeFilter === 'upcoming') { + return eventDate >= now; + } + + if (timeFilter === 'past') { + return eventDate < now; + } + + // Handle time range filters + const ranges: Record = { + 'next-week': new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000), + 'next-month': new Date(new Date(now).setMonth(now.getMonth() + 1)) + }; + + const endDate = ranges[timeFilter]; + return endDate ? eventDate >= now && eventDate <= endDate : true; +}; diff --git a/src/routes/discover/+page.svelte b/src/routes/discover/+page.svelte index 5b16181..a2b2cd1 100644 --- a/src/routes/discover/+page.svelte +++ b/src/routes/discover/+page.svelte @@ -2,7 +2,7 @@ import type { Event, EventType } from '$lib/types'; import { goto } from '$app/navigation'; import type { PageData } from '../$types'; - import { formatTime, formatDate } from '$lib/dateFormatter'; + import { formatTime, formatDate, isEventInTimeRange } from '$lib/dateHelpers'; import Fuse from 'fuse.js'; let publicEvents: Event[] = []; @@ -10,7 +10,9 @@ let searchQuery = ''; let selectedEventType: EventType | 'all' = 'all'; let selectedTimeFilter: 'any' | 'next-week' | 'next-month' = 'any'; + let selectedTemporalStatus: 'all' | 'upcoming' | 'past' = 'all'; let selectedSortOrder: 'asc' | 'desc' = 'asc'; + let showFilters = false; let fuse: Fuse; export let data: PageData; @@ -28,29 +30,7 @@ includeMatches: true }); - // Helper function to check if an event is within a time range - function isEventInTimeRange(event: Event, timeFilter: string): boolean { - if (timeFilter === 'any') return true; - - const eventDate = new Date(`${event.date}T${event.time}`); - const now = new Date(); - - if (timeFilter === 'next-week') { - const nextWeek = new Date(now); - nextWeek.setDate(now.getDate() + 7); - return eventDate >= now && eventDate <= nextWeek; - } - - if (timeFilter === 'next-month') { - const nextMonth = new Date(now); - nextMonth.setMonth(now.getMonth() + 1); - return eventDate >= now && eventDate <= nextMonth; - } - - return true; - } - - // Filter events based on search query, event type, and time filter using Fuse.js + // Filter events based on search query, event type, time filter, and temporal status $: filteredEvents = (() => { let events = publicEvents; @@ -59,6 +39,11 @@ events = events.filter((event) => event.type === selectedEventType); } + // Then filter by temporal status (past/upcoming/all) + if (selectedTemporalStatus !== 'all') { + events = events.filter((event) => isEventInTimeRange(event, selectedTemporalStatus)); + } + // Then filter by time range if (selectedTimeFilter !== 'any') { events = events.filter((event) => isEventInTimeRange(event, selectedTimeFilter)); @@ -67,10 +52,13 @@ // Then apply search query if (searchQuery.trim() !== '') { events = fuse.search(searchQuery).map((result) => result.item); - // Re-apply type and time filters after search + // Re-apply all filters after search if (selectedEventType !== 'all') { events = events.filter((event) => event.type === selectedEventType); } + if (selectedTemporalStatus !== 'all') { + events = events.filter((event) => isEventInTimeRange(event, selectedTemporalStatus)); + } if (selectedTimeFilter !== 'any') { events = events.filter((event) => isEventInTimeRange(event, selectedTimeFilter)); } @@ -134,90 +122,130 @@
- -
-
- - - -
- - {#if searchQuery} - - {/if} +
+ + {#if searchQuery} + + {/if} +
+ + + -
- -
- - -
- -
- - -
+ {#if showFilters} +
+ +
+ + +
+ +
+ + +
+ +
+ + +
- -
- - + +
+ + +
-
+ {/if}
diff --git a/src/routes/event/+page.svelte b/src/routes/event/+page.svelte index 213f8c1..cd78948 100644 --- a/src/routes/event/+page.svelte +++ b/src/routes/event/+page.svelte @@ -1,7 +1,7 @@