From 7117f85ef76ec25cec2a986ca387c92520b0ac96 Mon Sep 17 00:00:00 2001 From: Caspar Jojo Asaam Date: Thu, 12 Jun 2025 10:10:41 +0100 Subject: [PATCH] feat: added migration for a study_space_hours table and allowed for the user to make time inputs when submitting a new space Co-Authored-By: Tadios Temesgen --- src/lib/database.d.ts | 41 ++++++++++ src/routes/space/[id]/edit/+page.server.ts | 13 ++++ src/routes/space/[id]/edit/+page.svelte | 78 ++++++++++++++++++- ...20250612032104_study_space_hours_table.sql | 14 ++++ supabase/schemas/0001_study_spaces.sql | 16 ++++ 5 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 supabase/migrations/20250612032104_study_space_hours_table.sql diff --git a/src/lib/database.d.ts b/src/lib/database.d.ts index cb19ff3..ca1da1d 100644 --- a/src/lib/database.d.ts +++ b/src/lib/database.d.ts @@ -140,6 +140,47 @@ export type Database = { } Relationships: [] } + study_space_hours: { + Row: { + id: string + study_space_id: string + day_of_week: number + opens_at: string + closes_at: string + is_24_7: boolean + created_at: string | null + updated_at: string | null + } + Insert: { + id?: string + study_space_id: string + day_of_week: number + opens_at: string + closes_at: string + is_24_7: boolean + created_at?: string | null + updated_at?: string | null + } + Update: { + id?: string + study_space_id?: string + day_of_week?: number + opens_at?: string + closes_at?: string + is_24_7?: boolean + created_at?: string | null + updated_at?: string | null + } + Relationships: [ + { + foreignKeyName: "study_space_hours_study_space_id_fkey" + columns: ["study_space_id"] + isOneToOne: false + referencedRelation: "study_spaces" + referencedColumns: ["id"] + }, + ] + } } Views: { [_ in never]: never diff --git a/src/routes/space/[id]/edit/+page.server.ts b/src/routes/space/[id]/edit/+page.server.ts index 5ddf15d..78baabf 100644 --- a/src/routes/space/[id]/edit/+page.server.ts +++ b/src/routes/space/[id]/edit/+page.server.ts @@ -8,6 +8,12 @@ type StudySpaceData = Omit< > & { id?: string; building_location?: google.maps.places.PlaceResult; + opening_times?: { + day_of_week: number; + opens_at: string; + closes_at: string; + is_24_7: boolean; + }[]; }; export const load: PageServerLoad = async ({ params, locals: { supabase } }) => { @@ -34,6 +40,13 @@ export const load: PageServerLoad = async ({ params, locals: { supabase } }) => const studySpaceData = space as StudySpaceData & Partial; const images = studySpaceData.study_space_images || []; + const { data: hours, error: hoursErr } = await supabase + .from("study_space_hours") + .select("day_of_week, opens_at, closes_at, is_24_7") + .eq("study_space_id", params.id) + .order("day_of_week", { ascending: true }); + if (hoursErr) error(500, "Failed to load opening times"); + studySpaceData.opening_times = hours; delete studySpaceData.created_at; delete studySpaceData.updated_at; diff --git a/src/routes/space/[id]/edit/+page.svelte b/src/routes/space/[id]/edit/+page.svelte index e04eee2..bcf02ac 100644 --- a/src/routes/space/[id]/edit/+page.svelte +++ b/src/routes/space/[id]/edit/+page.svelte @@ -20,10 +20,35 @@ const { supabase } = $derived(data); const { space, images } = $derived(data); - const studySpaceData = $derived({ + // 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, + opens_at: "", + closes_at: "", + is_24_7: false + })), ...space }); + $effect(() => { + if (!space) return; + const { opening_times, ...rest } = space; + Object.assign(studySpaceData, rest); + if (opening_times) { + studySpaceData.opening_times = opening_times; + } + }); + let scrollPosition = $state(0); const existingImages = $derived( Promise.all( @@ -46,11 +71,13 @@ if (!spaceImgs || spaceImgs.length < 1) return alert("Please select an image file."); if (!studySpaceData.building_location) return alert("Please select a building location."); + const { opening_times, ...spacePayload } = studySpaceData; + const { data: studySpaceInsert, error: studySpaceError } = await supabase .from("study_spaces") .upsert( { - ...studySpaceData, + ...spacePayload, building_location: studySpaceData.building_location as Json }, { @@ -102,6 +129,23 @@ .select(); if (imageInsertError) return alert(`Error creating image: ${imageInsertError.message}`); + const { error: deleteErr } = await supabase + .from("study_space_hours") + .delete() + .eq("study_space_id", studySpaceInsert.id); + if (deleteErr) return alert(`Error clearing old hours: ${deleteErr.message}`); + + const { error: hoursErr } = await supabase.from("study_space_hours").insert( + opening_times.map((h) => ({ + study_space_id: studySpaceInsert.id, + day_of_week: h.day_of_week, + opens_at: h.opens_at, + closes_at: h.closes_at, + is_24_7: h.is_24_7 + })) + ); + if (hoursErr) return alert(`Error saving opening times: ${hoursErr.message}`); + alert("Thank you for your contribution!"); // Redirect to the new study space page await goto(`/space/${studySpaceInsert.id}`, { @@ -254,6 +298,36 @@ + +
+ {#each daysOfWeek as day, index (index)} +
+ + + to + + +
+ {/each} +
+
{#each studySpaceData.tags as tagName (tagName)} diff --git a/supabase/migrations/20250612032104_study_space_hours_table.sql b/supabase/migrations/20250612032104_study_space_hours_table.sql new file mode 100644 index 0000000..6020722 --- /dev/null +++ b/supabase/migrations/20250612032104_study_space_hours_table.sql @@ -0,0 +1,14 @@ +CREATE TABLE study_space_hours ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + study_space_id UUID REFERENCES study_spaces(id) ON DELETE CASCADE, + day_of_week INT CHECK (day_of_week BETWEEN 0 AND 6), -- 0 = Sunday, 6 = Saturday + opens_at TIME NOT NULL, + closes_at TIME NOT NULL, + is_24_7 BOOLEAN DEFAULT FALSE, + created_at timestamp with time zone DEFAULT now(), + updated_at timestamp with time zone DEFAULT now() +); + +CREATE TRIGGER study_space_hours_updated_at +AFTER UPDATE ON study_space_hours +FOR EACH ROW EXECUTE FUNCTION handle_updated_at(); \ No newline at end of file diff --git a/supabase/schemas/0001_study_spaces.sql b/supabase/schemas/0001_study_spaces.sql index 134ff96..6ccdccd 100644 --- a/supabase/schemas/0001_study_spaces.sql +++ b/supabase/schemas/0001_study_spaces.sql @@ -18,6 +18,7 @@ CREATE TABLE study_spaces ( volume text NOT NULL, wifi text NOT NULL, power text NOT NULL, + created_at timestamp with time zone DEFAULT now(), updated_at timestamp with time zone DEFAULT now() ); @@ -39,6 +40,17 @@ CREATE TABLE reports ( content text ); +CREATE TABLE study_space_hours ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + study_space_id UUID REFERENCES study_spaces(id) ON DELETE CASCADE, + day_of_week INT CHECK (day_of_week BETWEEN 0 AND 6), -- 0 = Sunday, 6 = Saturday + opens_at TIME NOT NULL, + closes_at TIME NOT NULL, + is_24_7 BOOLEAN DEFAULT FALSE, + created_at timestamp with time zone DEFAULT now(), + updated_at timestamp with time zone DEFAULT now() +); + -- Triggers CREATE TRIGGER study_spaces_updated_at AFTER UPDATE ON study_spaces @@ -51,3 +63,7 @@ FOR EACH ROW EXECUTE FUNCTION handle_updated_at(); CREATE TRIGGER reports_updated_at AFTER UPDATE ON reports FOR EACH ROW EXECUTE FUNCTION handle_updated_at(); + +CREATE TRIGGER study_space_hours_updated_at +AFTER UPDATE ON study_space_hours +FOR EACH ROW EXECUTE FUNCTION handle_updated_at();