From 268392deedd0830e8c873cd454d8231572d79b16 Mon Sep 17 00:00:00 2001 From: Barf-Vader <47476490+Barf-Vader@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:18:53 +0100 Subject: [PATCH] refactor: open timings --- src/lib/components/SpaceCard.svelte | 52 ++++++++++++++++++++++----- src/lib/index.ts | 18 ++++++++++ src/routes/+page.svelte | 54 +++++++++++++++++++++++++++-- src/routes/space/[id]/+page.svelte | 17 ++------- 4 files changed, 116 insertions(+), 25 deletions(-) diff --git a/src/lib/components/SpaceCard.svelte b/src/lib/components/SpaceCard.svelte index a2d5901..f8c9f3e 100644 --- a/src/lib/components/SpaceCard.svelte +++ b/src/lib/components/SpaceCard.svelte @@ -6,19 +6,22 @@ interface Props { space: Table<"study_spaces">; - hours: Table<"study_space_hours">[]; alt: string; imgSrc: string; href?: string; isFavourite: boolean; - + isAvailable?: boolean; onToggleFavourite?: () => void; + footer?: string; } - const { space, hours, alt, imgSrc, href, isFavourite, onToggleFavourite }: Props = $props(); + const { space, alt, imgSrc, href, isFavourite, onToggleFavourite, isAvailable, footer }: Props = + $props(); + + console.log(isAvailable); - +
@@ -34,11 +37,14 @@ {#if space.tags.length > 0}
{#each space.tags as tag (tag)} - {tag} + {tag} {/each}
{/if} -
+
+ {#if footer} + + {/if}
@@ -46,14 +52,25 @@ .card { display: flex; flex-direction: column; - background-color: #49bd85; width: 100%; max-width: 20rem; border-radius: 0.5rem; overflow: hidden; text-decoration: none; } + .green { + background-color: #49bd85; + } + .grey { + background-color: #2e4653; + } + .spacer { + flex: 1; + } .description { + flex: 1; + display: flex; + flex-direction: column; padding: 0.5rem; color: #edebe9; } @@ -83,13 +100,20 @@ justify-content: center; text-align: center; border-radius: 0.25rem; - background-color: #2e4653; color: #eaffeb; font-size: 0.875rem; cursor: pointer; padding: 0.2rem 0.6rem; } + .tagGreen { + background-color: #2e4653; + } + + .tagGrey { + background-color: #49bd85; + } + .compulsoryContainer { display: grid; grid-template-columns: repeat(auto-fit, minmax(3.75rem, 1fr)); @@ -109,4 +133,16 @@ padding: 0.25rem; z-index: 1; } + + .footer { + width: 100%; + color: #2e4653; + background-color: #eaffeb; + align-self: flex-end; + border-radius: 0.5rem; + padding: 0.1rem; + text-align: center; + font-weight: bold; + margin-top: 0.4rem; + } diff --git a/src/lib/index.ts b/src/lib/index.ts index d9029c9..41d52c4 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -84,3 +84,21 @@ export function haversineDistance( Math.pow(Math.sin(deltaLng / 2), 2) * Math.cos(lat1) * Math.cos(lat2); return radius * 2 * Math.asin(Math.sqrt(e1)); } + +export function collectTimings(study_space_hours: Table<"study_space_hours">[]) { + // Collect all timing entries + const timingsPerDay: Record[]> = { + 0: [], + 1: [], + 2: [], + 3: [], + 4: [], + 5: [], + 6: [] + }; + + for (const entry of study_space_hours) { + timingsPerDay[entry.day_of_week].push(entry); + } + return timingsPerDay; +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 921b00e..7c7920a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,10 +4,19 @@ import crossUrl from "$lib/assets/cross.svg"; import searchUrl from "$lib/assets/search.svg"; import Navbar from "$lib/components/Navbar.svelte"; - import { haversineDistance, timeToMins } from "$lib"; + import { + allTags, + volumeTags, + wifiTags, + powerOutletTags, + collectTimings, + timeToMins, + haversineDistance + } from "$lib"; import Button from "$lib/components/Button.svelte"; import { urldecodeSortFilter } from "$lib/filter.js"; import { invalidateAll } from "$app/navigation"; + import type { Table } from "$lib"; const { data } = $props(); const { @@ -123,6 +132,42 @@ }) : filteredStudySpaces ); + + // Open now + function isOpenNow(all_study_space_hours: Table<"study_space_hours">[]) { + const now = new Date(); + const time = now.toTimeString().slice(0, 5); + const day = now.getDay(); + + const timingsPerDay = collectTimings(all_study_space_hours); + for (const timing of timingsPerDay[day]) { + if (timing.open_today_status === true) { + return { isOpen: true, message: `Open all day` }; + } else if (timing.open_today_status === false) { + return { isOpen: false, message: `Closed today` }; + } else { + const opensFor = timeUntilClosing(timing.opens_at, timing.closes_at, time); + if (opensFor) { + return { isOpen: true, message: `Open now for: ${minsToReadableHours}` }; + } + } + } + + return { isOpen: false, message: "Closed today" }; + } + + function timeUntilClosing(openingTime: string, closingTime: string, currentTime: string) { + const currTimeInMins = timeToMins(currentTime); + const OpeningTimeInMins = timeToMins(openingTime); + const closingTimeInMins = timeToMins(closingTime); + if (currTimeInMins >= OpeningTimeInMins && currTimeInMins < closingTimeInMins) { + return closingTimeInMins - currTimeInMins; + } + } + + function minsToReadableHours(mins: number) { + return `${Math.floor(mins / 60)} hrs, ${mins % 60} mins`; + } @@ -161,9 +206,14 @@ href="/space/{studySpace.id}" imgSrc={imgUrl} space={studySpace} - hours={studySpace.study_space_hours} isFavourite={favouriteIds.includes(studySpace.id)} onToggleFavourite={session ? () => handleToggleFavourite(studySpace.id) : undefined} + isAvailable={studySpace.study_space_hours.length === 0 + ? undefined + : isOpenNow(studySpace.study_space_hours).isOpen} + footer={studySpace.study_space_hours.length === 0 + ? undefined + : isOpenNow(studySpace.study_space_hours).message} /> {/each} diff --git a/src/routes/space/[id]/+page.svelte b/src/routes/space/[id]/+page.svelte index 52ed34b..514e43a 100644 --- a/src/routes/space/[id]/+page.svelte +++ b/src/routes/space/[id]/+page.svelte @@ -7,7 +7,7 @@ import Report from "$lib/components/Report.svelte"; import Feedback from "$lib/components/Feedback.svelte"; import { onMount } from "svelte"; - import { gmapsLoader, daysOfWeek, formatTime, type Table } from "$lib"; + import { gmapsLoader, daysOfWeek, formatTime, collectTimings, type Table } from "$lib"; import Button from "$lib/components/Button.svelte"; import Favourite from "$lib/components/Favourite.svelte"; @@ -52,20 +52,7 @@ }); }); - // Collect all timing entries - let timingsPerDay: Record[]> = { - 0: [], - 1: [], - 2: [], - 3: [], - 4: [], - 5: [], - 6: [] - }; - - for (const entry of space.study_space_hours) { - timingsPerDay[entry.day_of_week].push(entry); - } + let timingsPerDay = collectTimings(space.study_space_hours); let isFavourite = $state(false); onMount(async () => {