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:
41
src/lib/database.d.ts
vendored
41
src/lib/database.d.ts
vendored
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user