From 19d451fa8e462494b4b63749341d6dc60a3dd8f4 Mon Sep 17 00:00:00 2001 From: TadiosT Date: Tue, 10 Jun 2025 05:24:15 +0100 Subject: [PATCH 1/6] 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 -- 2.49.1 From 201467c73a6014dea7f23d41cfe6ae5e689f64bd Mon Sep 17 00:00:00 2001 From: TadiosT Date: Tue, 10 Jun 2025 05:37:52 +0100 Subject: [PATCH 2/6] feat: Added filtering by compulsory tags and changed filtering logic. Co-Authored By: Caspar Asaam --- src/lib/components/inputs/TagFilter.svelte | 10 +------- src/routes/+page.svelte | 30 ++++++++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/lib/components/inputs/TagFilter.svelte b/src/lib/components/inputs/TagFilter.svelte index ae68a2d..5d82fc8 100644 --- a/src/lib/components/inputs/TagFilter.svelte +++ b/src/lib/components/inputs/TagFilter.svelte @@ -76,15 +76,7 @@ color: #ffffff; margin-top: 0.5rem; } - .submit { - position: sticky; - display: flex; - flex-direction: column; - margin-top: 0.5rem; - bottom: 0; - margin-left: -0.5rem; - width: calc(100% + 1rem); - } + .tagDisplay { display: flex; gap: 0.4rem; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 882797f..84356a1 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -5,6 +5,7 @@ import Navbar from "$lib/components/Navbar.svelte"; import TagFilter from "$lib/components/inputs/TagFilter.svelte"; import {availableStudySpaceTags} from "$lib" + import {allTags} from "$lib" const { data } = $props(); const { studySpaces, supabase } = $derived(data); @@ -13,20 +14,25 @@ let tagFilter = $state(""); let tagFilterElem = $state() let filteredTags = $derived( - availableStudySpaceTags + allTags .filter((tag) => tag.toLowerCase().includes(tagFilter.toLowerCase())) - .filter((tag) => availableStudySpaceTags.includes(tag)) + .filter((tag) => allTags.includes(tag)) ) let filteredStudySpaces = $derived(() => - selectedTags.length == 0 + selectedTags.length === 0 ? studySpaces - : studySpaces.filter(space => - selectedTags.every(tag => - (space.tags || []).includes(tag) - ) - ) - ); + : studySpaces.filter(space => { + const allTags = [ + ...(space.tags || []), + space.volume, + space.wifi, + space.power + ].filter(Boolean); + + return selectedTags.every(tag => allTags.includes(tag)); + }) + ); let dropdownVisible = $state(false) @@ -62,10 +68,8 @@ deleteTag={deleteTag} addTag={addTag} /> - {#each studySpaces.filter(space => - selectedTags.length === 0 || - selectedTags.every(tag => (space.tags || []).includes(tag)) - ) as studySpace (studySpace.id)} + + {#each filteredStudySpaces() as studySpace (studySpace.id)} {@const imgUrl = studySpace.study_space_images.length > 0 ? supabase.storage -- 2.49.1 From 61da21b7db60244be174287eb39b4a368ca30fc6 Mon Sep 17 00:00:00 2001 From: TadiosT Date: Tue, 10 Jun 2025 05:45:29 +0100 Subject: [PATCH 3/6] fix: Style and type check changes. Co-Authored By: Caspar Asaam --- src/lib/components/inputs/TagFilter.svelte | 48 +------------------ src/lib/index.ts | 2 +- src/routes/+page.svelte | 55 +++++++++++----------- 3 files changed, 30 insertions(+), 75 deletions(-) diff --git a/src/lib/components/inputs/TagFilter.svelte b/src/lib/components/inputs/TagFilter.svelte index 5d82fc8..4648fd1 100644 --- a/src/lib/components/inputs/TagFilter.svelte +++ b/src/lib/components/inputs/TagFilter.svelte @@ -1,6 +1,6 @@
-
+
{#each selectedTags as tagName (tagName)}
{/if}
-
diff --git a/src/lib/index.ts b/src/lib/index.ts index f209ffe..3264a9e 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -25,4 +25,4 @@ 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] +export const allTags = [...availableStudySpaceTags, ...volumeTags, ...wifiTags, ...powerOutletTags]; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 84356a1..3160ef7 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,37 +4,36 @@ 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" - import {allTags} from "$lib" + import { allTags } from "$lib"; const { data } = $props(); - const { studySpaces, supabase } = $derived(data); - - let selectedTags = $state([]) + const { studySpaces, supabase } = $derived(data); + + let selectedTags = $state([]); let tagFilter = $state(""); - let tagFilterElem = $state() + let tagFilterElem = $state(); let filteredTags = $derived( allTags .filter((tag) => tag.toLowerCase().includes(tagFilter.toLowerCase())) .filter((tag) => allTags.includes(tag)) - ) + ); let filteredStudySpaces = $derived(() => selectedTags.length === 0 ? studySpaces - : studySpaces.filter(space => { - const allTags = [ - ...(space.tags || []), - space.volume, - space.wifi, - space.power - ].filter(Boolean); + : studySpaces.filter((space) => { + const allTags = [ + ...(space.tags || []), + space.volume, + space.wifi, + space.power + ].filter(Boolean); - return selectedTags.every(tag => allTags.includes(tag)); - }) + return selectedTags.every((tag) => allTags.includes(tag)); + }) ); - let dropdownVisible = $state(false) + let dropdownVisible = $state(false); function deleteTag(tagName: string) { return () => { @@ -52,24 +51,24 @@ } - + new - +
- - {#each filteredStudySpaces() as studySpace (studySpace.id)} + {#each filteredStudySpaces() as studySpace (studySpace.id)} {@const imgUrl = studySpace.study_space_images.length > 0 ? supabase.storage -- 2.49.1 From 5eb7a9f58ca48c50b833c6b30c60770c3a4cb49a Mon Sep 17 00:00:00 2001 From: TadiosT Date: Tue, 10 Jun 2025 15:00:12 +0100 Subject: [PATCH 4/6] feat: Centred the filtering bar in the main page. Co-Authored By: Caspar Asaam --- src/routes/+page.svelte | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3160ef7..8267264 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -58,15 +58,17 @@
- +
+ +
{#each filteredStudySpaces() as studySpace (studySpace.id)} {@const imgUrl = @@ -100,6 +102,13 @@ transform: rotate(45deg); } + .tag-filter-container { + grid-column: 1 / -1; + display: flex; + justify-content: center; + margin-bottom: 1rem; + } + @media (max-width: 20rem) { main { grid-template-columns: 1fr; -- 2.49.1 From e9d6db605ac26981cb6212042bbcca6a906183ac Mon Sep 17 00:00:00 2001 From: TadiosT Date: Wed, 11 Jun 2025 03:22:19 +0100 Subject: [PATCH 5/6] fix: Fix to filteredTags in main page. Removed use of TagFilter component. Co-Authored By: Caspar Asaam --- src/lib/components/inputs/TagFilter.svelte | 150 --------------------- src/routes/+page.svelte | 146 ++++++++++++++++++-- 2 files changed, 136 insertions(+), 160 deletions(-) diff --git a/src/lib/components/inputs/TagFilter.svelte b/src/lib/components/inputs/TagFilter.svelte index 4648fd1..e69de29 100644 --- a/src/lib/components/inputs/TagFilter.svelte +++ b/src/lib/components/inputs/TagFilter.svelte @@ -1,150 +0,0 @@ - - -
-
- {#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/routes/+page.svelte b/src/routes/+page.svelte index 8267264..cd0cd98 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -3,7 +3,6 @@ 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 { allTags } from "$lib"; const { data } = $props(); @@ -59,15 +58,54 @@
- +
+
+ {#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="Search by tags..." + /> + {#if dropdownVisible} +
+ {#each filteredTags as avaliableTag (avaliableTag)} + + {/each} +
+ {/if} +
+
{#each filteredStudySpaces() as studySpace (studySpace.id)} @@ -109,6 +147,94 @@ margin-bottom: 1rem; } + form { + display: flex; + flex-direction: column; + padding: 1.5rem; + gap: 0.5rem; + max-width: 32rem; + margin: 0 auto; + } + + .tagDisplay { + display: flex; + gap: 0.4rem; + flex-wrap: wrap; + align-items: left; + justify-content: left; + position: relative; + width: 100%; + height: auto; + padding: 0.5rem; + border-radius: 0.5rem; + border: 2px solid #eaffeb; + background: none; + color: #eaffeb; + font-size: 1rem; + } + .tagInput { + width: 100%; + height: 100%; + background: none; + color: #eaffeb; + font-size: 1rem; + border: none; + outline: none; + } + ::placeholder { + color: #859a90; + opacity: 1; + } + .tag { + display: flex; + align-items: center; + border-radius: 0.25rem; + background-color: #2e4653; + color: #eaffeb; + font-size: 0.9rem; + cursor: pointer; + border-width: 0rem; + } + .tag img { + width: 1rem; + height: 1rem; + margin-left: 0.2rem; + } + + .tagDropdown { + width: 100%; + display: flex; + gap: 0.4rem; + flex-wrap: wrap; + position: absolute; + background-color: #2e4653; + box-shadow: 1px 1px 0.5rem rgba(0, 0, 0, 0.5); + border-radius: 0.5rem; + overflow-y: auto; + max-height: 10rem; + top: 100%; + left: 50%; + transform: translateX(-50%); + } + + .avaliableTag { + width: 100%; + text-align: left; + background: none; + border: none; + color: #eaffeb; + font-size: 0.9rem; + margin: 0%; + padding: 0 0.8rem 0.4rem; + } + .avaliableTag:first-child { + padding-top: 0.6rem; + background-color: hsl(201, 26%, 60%); + } + .avaliableTag:last-child { + padding-bottom: 0.6rem; + } + @media (max-width: 20rem) { main { grid-template-columns: 1fr; -- 2.49.1 From 3d95ea376367079338fb916f1ed0a96a41321465 Mon Sep 17 00:00:00 2001 From: TadiosT Date: Wed, 11 Jun 2025 03:40:20 +0100 Subject: [PATCH 6/6] fix: Changed filteredStudySpaces from function to string[]. Co-Authored By: Caspar Asaam caspar@dyn3159-95.wlan.ic.ac.uk --- src/routes/+page.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index cd0cd98..19f132f 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -17,7 +17,7 @@ .filter((tag) => allTags.includes(tag)) ); - let filteredStudySpaces = $derived(() => + let filteredStudySpaces = $derived( selectedTags.length === 0 ? studySpaces : studySpaces.filter((space) => { @@ -108,7 +108,7 @@ - {#each filteredStudySpaces() as studySpace (studySpace.id)} + {#each filteredStudySpaces as studySpace (studySpace.id)} {@const imgUrl = studySpace.study_space_images.length > 0 ? supabase.storage -- 2.49.1