refactor: cleanup skeleton, setup supabase properly
This commit is contained in:
9
src/routes/+layout.server.ts
Normal file
9
src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { LayoutServerLoad } from "./$types";
|
||||
|
||||
export const load: LayoutServerLoad = async ({ locals: { safeGetSession }, cookies }) => {
|
||||
const { session } = await safeGetSession();
|
||||
return {
|
||||
session,
|
||||
cookies: cookies.getAll()
|
||||
};
|
||||
};
|
||||
44
src/routes/+layout.ts
Normal file
44
src/routes/+layout.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { createBrowserClient, createServerClient, isBrowser } from "@supabase/ssr";
|
||||
import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from "$env/static/public";
|
||||
import type { Database } from "$lib/database";
|
||||
import type { LayoutLoad } from "./$types";
|
||||
|
||||
export const load: LayoutLoad = async ({ data, depends, fetch }) => {
|
||||
/**
|
||||
* Declare a dependency so the layout can be invalidated, for example, on
|
||||
* session refresh.
|
||||
*/
|
||||
depends("supabase:auth");
|
||||
|
||||
const supabase = isBrowser()
|
||||
? createBrowserClient<Database>(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
|
||||
global: {
|
||||
fetch
|
||||
}
|
||||
})
|
||||
: createServerClient<Database>(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, {
|
||||
global: {
|
||||
fetch
|
||||
},
|
||||
cookies: {
|
||||
getAll() {
|
||||
return data.cookies;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* It's fine to use `getSession` here, because on the client, `getSession` is
|
||||
* safe, and on the server, it reads `session` from the `LayoutData`, which
|
||||
* safely checked the session using `safeGetSession`.
|
||||
*/
|
||||
const {
|
||||
data: { session }
|
||||
} = await supabase.auth.getSession();
|
||||
|
||||
const {
|
||||
data: { user }
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
return { session, supabase, user };
|
||||
};
|
||||
@@ -1,12 +1,8 @@
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from "$env/static/public";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
import type { Database } from "$lib/database";
|
||||
import { error } from "@sveltejs/kit";
|
||||
|
||||
export const load: PageServerLoad = async ({ depends }) => {
|
||||
export const load: PageServerLoad = async ({ depends, locals: { supabase } }) => {
|
||||
depends("db:study_spaces");
|
||||
const supabase = createClient<Database>(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY);
|
||||
const { data: studySpaces, error: err } = await supabase
|
||||
.from("study_spaces")
|
||||
.select("*, study_space_images(*)");
|
||||
|
||||
@@ -1,35 +1,56 @@
|
||||
<script lang="ts">
|
||||
import SpaceCard from "$lib/components/SpaceCard.svelte";
|
||||
import defaultImg from "$lib/assets/study_space.png";
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "$lib/database";
|
||||
import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from "$env/static/public";
|
||||
import { invalidate } from "$app/navigation";
|
||||
import type { Table } from "$lib";
|
||||
|
||||
const supabase = createClient<Database>(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY);
|
||||
const { data } = $props();
|
||||
const { studySpaces } = $derived(data);
|
||||
const { studySpaces, supabase } = $derived(data);
|
||||
|
||||
let title = $state("");
|
||||
let fileInput = $state<HTMLInputElement | null>(null);
|
||||
const blankStudySpace = {
|
||||
description: "",
|
||||
building_address: "",
|
||||
location: ""
|
||||
};
|
||||
|
||||
let studySpaceData = $state<Omit<Table<"study_spaces">, "id" | "created_at" | "updated_at">>({
|
||||
...blankStudySpace
|
||||
});
|
||||
let fileInput = $state<HTMLInputElement>();
|
||||
|
||||
async function uploadStudySpace() {
|
||||
const imageFile = fileInput?.files?.[0];
|
||||
if (!imageFile) {
|
||||
alert("Please select an image file.");
|
||||
return;
|
||||
}
|
||||
const params = new URLSearchParams({ title, imgTitle: imageFile.name });
|
||||
const res = await fetch(`/api/study_spaces?${params.toString()}`, {
|
||||
method: "POST",
|
||||
body: imageFile
|
||||
});
|
||||
if (res.ok) {
|
||||
alert("Study space uploaded successfully!");
|
||||
await invalidate("db:study_spaces");
|
||||
} else {
|
||||
alert("Failed to upload study space.");
|
||||
}
|
||||
if (!imageFile) return alert("Please select an image file.");
|
||||
|
||||
const { data: studySpaceInsert, error: studySpaceError } = await supabase
|
||||
.from("study_spaces")
|
||||
.insert(studySpaceData)
|
||||
.select()
|
||||
.single();
|
||||
if (studySpaceError)
|
||||
return alert(`Error uploading study space: ${studySpaceError.message}`);
|
||||
|
||||
const { data: imgUpload, error: imageError } = await supabase.storage
|
||||
.from("files_bucket")
|
||||
.upload(`public/${studySpaceInsert.id}-${imageFile.name}`, imageFile, {
|
||||
contentType: imageFile.type
|
||||
});
|
||||
if (imageError) return alert(`Error uploading image: ${imageError.message}`);
|
||||
|
||||
const { error: imageInsertError } = await supabase
|
||||
.from("study_space_images")
|
||||
.insert({
|
||||
study_space_id: studySpaceInsert.id,
|
||||
image_path: imgUpload.path
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
if (imageInsertError) return alert(`Error creating image: ${imageInsertError.message}`);
|
||||
|
||||
if (fileInput) fileInput.value = ""; // Clear the file input
|
||||
studySpaceData = { ...blankStudySpace }; // Reset the form data
|
||||
alert("Thank you for your contribution!");
|
||||
invalidate("db:study_spaces"); // Invalidate page data so that it refreshes
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -41,9 +62,9 @@
|
||||
.from("files_bucket")
|
||||
.getPublicUrl(studySpace.study_space_images[0].image_path).data.publicUrl
|
||||
: defaultImg}
|
||||
<SpaceCard alt="Photo of {studySpace.title}" imgSrc={imgUrl}>
|
||||
<SpaceCard alt="Photo of {studySpace.description}" imgSrc={imgUrl}>
|
||||
{#snippet description()}
|
||||
<p>{studySpace.title}</p>
|
||||
<p>{studySpace.description}</p>
|
||||
{/snippet}
|
||||
</SpaceCard>
|
||||
{/each}
|
||||
@@ -55,7 +76,27 @@
|
||||
uploadStudySpace();
|
||||
}}
|
||||
>
|
||||
<input type="text" name="title" bind:value={title} placeholder="Study Space Title" required />
|
||||
<input
|
||||
type="text"
|
||||
name="description"
|
||||
bind:value={studySpaceData.description}
|
||||
placeholder="Study Space Description"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="location"
|
||||
bind:value={studySpaceData.location}
|
||||
placeholder="Study Space Location within building"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="building_address"
|
||||
bind:value={studySpaceData.building_address}
|
||||
placeholder="Building Address"
|
||||
required
|
||||
/>
|
||||
<input type="file" name="image" accept=".png, image/png" required bind:this={fileInput} />
|
||||
<button type="submit">Upload some Study Space!</button>
|
||||
</form>
|
||||
@@ -70,5 +111,8 @@
|
||||
}
|
||||
form {
|
||||
max-width: 600px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from "$env/static/public";
|
||||
import type { Database } from "$lib/database";
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
import { error, type RequestHandler } from "@sveltejs/kit";
|
||||
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
const supabase = createClient<Database>(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY);
|
||||
const body = await request.bytes();
|
||||
const url = new URL(request.url);
|
||||
const title = url.searchParams.get("title");
|
||||
const imgTitle = url.searchParams.get("imgTitle");
|
||||
if (!title || !imgTitle) error(400, "Missing required fields: title, imgTitle");
|
||||
|
||||
const { data: imageData, error: imageError } = await supabase.storage
|
||||
.from("files_bucket")
|
||||
.upload(`public/${imgTitle}`, body, {
|
||||
contentType: request.headers.get("content-type") || "image/png",
|
||||
upsert: false
|
||||
});
|
||||
if (imageError) error(500, `Failed to upload image: ${imageError.message}`);
|
||||
|
||||
const { data: studySpaceData, error: studySpaceError } = await supabase
|
||||
.from("study_spaces")
|
||||
.insert({ title })
|
||||
.select()
|
||||
.single();
|
||||
if (studySpaceError) error(500, "Failed to create study space");
|
||||
|
||||
const { error: imageLinkError } = await supabase
|
||||
.from("study_space_images")
|
||||
.insert({ study_space_id: studySpaceData.id, image_path: imageData.path });
|
||||
|
||||
if (imageLinkError) error(500, "Failed to link image to study space");
|
||||
return new Response(JSON.stringify({ id: studySpaceData.id }), { status: 200 });
|
||||
};
|
||||
Reference in New Issue
Block a user