diff --git a/src/lib/components/OpeningTimes.svelte b/src/lib/components/OpeningTimes.svelte new file mode 100644 index 0000000..fbd3242 --- /dev/null +++ b/src/lib/components/OpeningTimes.svelte @@ -0,0 +1,40 @@ + + +
+ Today's Opening Times: + {openingDisplay} +
+ + diff --git a/src/lib/components/SpaceCard.svelte b/src/lib/components/SpaceCard.svelte index 0c1bf04..b5c1a19 100644 --- a/src/lib/components/SpaceCard.svelte +++ b/src/lib/components/SpaceCard.svelte @@ -1,15 +1,17 @@ @@ -24,6 +26,7 @@ {/each} {/if} +
diff --git a/src/lib/index.ts b/src/lib/index.ts index ce66b97..b709d5c 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -8,7 +8,6 @@ export type Enum = Database["public export const availableStudySpaceTags = [ "Crowded", "Group study", - "24/7", "Food allowed", "No food allowed", "Well lit", @@ -43,3 +42,20 @@ export async function gmapsLoader() { libraries: ["places"] }); } + +export function formatTime(time: string) { + const [h, m] = time.split(":").map(Number); + const date = new Date(); + date.setHours(h, m); + return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); +} + +export const daysOfWeek = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +]; diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index b364832..7f2ccd5 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -5,7 +5,7 @@ export const load: PageServerLoad = async ({ depends, locals: { supabase } }) => depends("db:study_spaces"); const { data: studySpaces, error: err } = await supabase .from("study_spaces") - .select("*, study_space_images(*)"); + .select("*, study_space_images(*), study_space_hours(*)"); if (err) error(500, "Failed to load study spaces"); return { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 094cf78..850aa58 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -137,6 +137,7 @@ href="/space/{studySpace.id}" imgSrc={imgUrl} space={studySpace} + hours={studySpace.study_space_hours} /> {/each} diff --git a/src/routes/space/[id]/+page.server.ts b/src/routes/space/[id]/+page.server.ts index b89b2db..daa172e 100644 --- a/src/routes/space/[id]/+page.server.ts +++ b/src/routes/space/[id]/+page.server.ts @@ -4,7 +4,7 @@ import type { PageServerLoad } from "./$types"; export const load: PageServerLoad = async ({ params, locals: { supabase } }) => { const { data: space, error: err } = await supabase .from("study_spaces") - .select("*, study_space_images(*)") + .select("*, study_space_images(*), study_space_hours(*)") .eq("id", params.id) .single(); if (err) error(500, "Failed to load study space"); diff --git a/src/routes/space/[id]/+page.svelte b/src/routes/space/[id]/+page.svelte index a3f151b..91d0699 100644 --- a/src/routes/space/[id]/+page.svelte +++ b/src/routes/space/[id]/+page.svelte @@ -6,7 +6,7 @@ import CompulsoryTags from "$lib/components/CompulsoryTags.svelte"; import Report from "$lib/components/Report.svelte"; import { onMount } from "svelte"; - import { gmapsLoader } from "$lib"; + import { gmapsLoader, daysOfWeek, formatTime } from "$lib"; const { data } = $props(); const { space, supabase } = $derived(data); @@ -45,6 +45,13 @@ map }); }); + + const hoursByDay = $derived(new Map(space.study_space_hours.map((h) => [h.day_of_week, h]))); + + const openingEntries = daysOfWeek.map((day, idx) => ({ + day, + entry: hoursByDay.get(idx) + })); @@ -77,6 +84,22 @@ {/if}
+
Opening Times:
+ {#each openingEntries as { day, entry } (entry)} +
+ {day}: + + {#if entry} + {entry.is_24_7 + ? "Open All Day" + : `${formatTime(entry.opens_at)} – ${formatTime(entry.closes_at)}`} + {:else} + Closed + {/if} + +
+ {/each} +
Where it is:

{#if place.name} @@ -220,4 +243,24 @@ text-decoration: none; text-align: center; } + + .opening-entry { + display: grid; + grid-template-columns: auto 1fr; + gap: 0.75rem; + padding: 0.5rem 1.4rem; + align-items: center; + } + .opening-entry .day { + font-weight: bold; + color: #ffffff; + white-space: nowrap; + } + .opening-entry .times { + font-family: monospace; + background-color: rgba(255, 255, 255, 0.1); + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + color: #eaffeb; + } diff --git a/src/routes/space/[id]/edit/+page.svelte b/src/routes/space/[id]/edit/+page.svelte index bcf02ac..5302a2c 100644 --- a/src/routes/space/[id]/edit/+page.svelte +++ b/src/routes/space/[id]/edit/+page.svelte @@ -11,7 +11,8 @@ wifiTags, powerOutletTags, volumeTags, - gmapsLoader + gmapsLoader, + daysOfWeek } from "$lib"; import { onMount } from "svelte"; import type { Json } from "$lib/database.js"; @@ -20,16 +21,6 @@ const { supabase } = $derived(data); const { space, images } = $derived(data); - // Days of week for opening times - const daysOfWeek = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" - ]; const studySpaceData = $state({ opening_times: daysOfWeek.map((_, index) => ({ day_of_week: index, @@ -205,6 +196,20 @@ }); spaceImgs = dt.files; }); + + // --- Helper functions for opening times --- + function toggle247(index: number) { + const ot = studySpaceData.opening_times[index]; + if (ot.is_24_7) { + ot.opens_at = "00:00"; + ot.closes_at = "00:00"; + } + } + + function updateTimes(index: number) { + const ot = studySpaceData.opening_times[index]; + ot.is_24_7 = ot.opens_at === "00:00" && ot.closes_at === "00:00"; + } @@ -308,6 +313,7 @@ type="time" bind:value={studySpaceData.opening_times[index].opens_at} required + onchange={() => updateTimes(index)} /> to updateTimes(index)} /> {/each} @@ -562,4 +570,36 @@ .additionalImages input { display: none; } + + /* Opening times layout and inputs styling */ + .opening-times { + display: flex; + flex-direction: column; + gap: 0.5rem; + } + + .opening-time-item { + display: flex; + align-items: center; + gap: 0.5rem; + } + + .opening-time-item label { + margin-top: 0; + width: 6rem; + } + + .opening-time-item input[type="time"] { + padding: 0.5rem; + height: 2.5rem; + border-radius: 0.5rem; + border: 2px solid #eaffeb; + background: none; + color: #eaffeb; + } + + .opening-time-item span { + margin: 0 0.5rem; + color: #eaffeb; + }