From 19d451fa8e462494b4b63749341d6dc60a3dd8f4 Mon Sep 17 00:00:00 2001 From: TadiosT Date: Tue, 10 Jun 2025 05:24:15 +0100 Subject: [PATCH] feat: Added filtering by optional tags in the main page. Created TagFilter component for modularisation. Co-Authored By: Caspar Asaam --- src/lib/components/inputs/TagFilter.svelte | 202 +++++++++++++++++++++ src/lib/index.ts | 2 + src/routes/+page.svelte | 58 +++++- 3 files changed, 258 insertions(+), 4 deletions(-) create mode 100644 src/lib/components/inputs/TagFilter.svelte diff --git a/src/lib/components/inputs/TagFilter.svelte b/src/lib/components/inputs/TagFilter.svelte new file mode 100644 index 0000000..ae68a2d --- /dev/null +++ b/src/lib/components/inputs/TagFilter.svelte @@ -0,0 +1,202 @@ + + +
+
+ {#each selectedTags as tagName (tagName)} + + {/each} + { + dropdownVisible = true; + }} + onblur={() => { + dropdownVisible = false; + }} + onkeypress={(event) => { + if (event.key === "Enter") { + const tag = filteredTags[0]; + if (tag) addTag(tag)(); + } + }} + placeholder="Filter by tags..." + /> + {#if dropdownVisible} +
+ {#each filteredTags as avaliableTag (avaliableTag)} + + {/each} +
+ {/if} +
+ +
+ + diff --git a/src/lib/index.ts b/src/lib/index.ts index 2e36564..f209ffe 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -24,3 +24,5 @@ export const availableStudySpaceTags = [ export const volumeTags = ["Silent", "Quiet", "Some Noise", "Loud"]; export const wifiTags = ["Good WiFi", "Moderate WiFi", "Bad WiFi", "No WiFi"]; export const powerOutletTags = ["Many Outlets", "Some Outlets", "No Outlets"]; + +export const allTags = [...availableStudySpaceTags, ...volumeTags, ...wifiTags, ...powerOutletTags] diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 6e717f7..882797f 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -3,19 +3,69 @@ import defaultImg from "$lib/assets/study_space.png"; import crossUrl from "$lib/assets/cross.svg"; import Navbar from "$lib/components/Navbar.svelte"; + import TagFilter from "$lib/components/inputs/TagFilter.svelte"; + import {availableStudySpaceTags} from "$lib" const { data } = $props(); - const { studySpaces, supabase } = $derived(data); + const { studySpaces, supabase } = $derived(data); + + let selectedTags = $state([]) + let tagFilter = $state(""); + let tagFilterElem = $state() + let filteredTags = $derived( + availableStudySpaceTags + .filter((tag) => tag.toLowerCase().includes(tagFilter.toLowerCase())) + .filter((tag) => availableStudySpaceTags.includes(tag)) + ) + + let filteredStudySpaces = $derived(() => + selectedTags.length == 0 + ? studySpaces + : studySpaces.filter(space => + selectedTags.every(tag => + (space.tags || []).includes(tag) + ) + ) + ); + + let dropdownVisible = $state(false) + + function deleteTag(tagName: string) { + return () => { + selectedTags = selectedTags.filter((tag) => tag !== tagName); + }; + } + + function addTag(tagName: string) { + return () => { + if (!selectedTags.includes(tagName)) { + selectedTags.push(tagName); + } + tagFilter = ""; + }; + } - + new - +
- {#each studySpaces as studySpace (studySpace.id)} + + {#each studySpaces.filter(space => + selectedTags.length === 0 || + selectedTags.every(tag => (space.tags || []).includes(tag)) + ) as studySpace (studySpace.id)} {@const imgUrl = studySpace.study_space_images.length > 0 ? supabase.storage