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 <tt2022@ic.ac.uk>
This commit is contained in:
Caspar Jojo Asaam
2025-06-12 10:10:41 +01:00
parent 7c0f9b3f52
commit 7117f85ef7
5 changed files with 160 additions and 2 deletions

41
src/lib/database.d.ts vendored
View File

@@ -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

View File

@@ -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<typeof space>;
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;

View File

@@ -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 @@
</div>
</div>
<label for="opening-times-label">Opening Times:</label>
<div class="opening-times">
{#each daysOfWeek as day, index (index)}
<div class="opening-time-item">
<label for={"opens-" + index}>{day}</label>
<input
id={"opens-" + index}
type="time"
bind:value={studySpaceData.opening_times[index].opens_at}
required
/>
<span>to</span>
<input
id={"closes-" + index}
type="time"
bind:value={studySpaceData.opening_times[index].closes_at}
required
/>
<label for={"is247-" + index}>
<input
id={"is247-" + index}
type="checkbox"
bind:checked={studySpaceData.opening_times[index].is_24_7}
/>
24/7
</label>
</div>
{/each}
</div>
<label for="tags">Additional tags:</label>
<div class="tagDisplay">
{#each studySpaceData.tags as tagName (tagName)}