Merge branch 'feat/initial-study-space-view' into 'master'
feat: initial uploads and single study space view See merge request gk1623/drp-48!1
This commit is contained in:
@@ -2,8 +2,13 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: Inter;
|
||||
src: url("%sveltekit.assets%/Inter.ttf") format("truetype");
|
||||
}
|
||||
</style>
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
|
||||
11
src/lib/assets/camera.svg
Normal file
11
src/lib/assets/camera.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_117_282)">
|
||||
<path d="M36.4168 30.0833C36.4168 30.9232 36.0832 31.7286 35.4893 32.3225C34.8955 32.9164 34.09 33.25 33.2502 33.25H4.75016C3.91031 33.25 3.10486 32.9164 2.51099 32.3225C1.91713 31.7286 1.5835 30.9232 1.5835 30.0833V12.6667C1.5835 11.8268 1.91713 11.0214 2.51099 10.4275C3.10486 9.83363 3.91031 9.5 4.75016 9.5H11.0835L14.2502 4.75H23.7502L26.9168 9.5H33.2502C34.09 9.5 34.8955 9.83363 35.4893 10.4275C36.0832 11.0214 36.4168 11.8268 36.4168 12.6667V30.0833Z" stroke="#49BD85" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M19.0002 26.9167C22.498 26.9167 25.3335 24.0811 25.3335 20.5833C25.3335 17.0855 22.498 14.25 19.0002 14.25C15.5024 14.25 12.6668 17.0855 12.6668 20.5833C12.6668 24.0811 15.5024 26.9167 19.0002 26.9167Z" stroke="#49BD85" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_117_282">
|
||||
<rect width="38" height="38" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
src/lib/assets/cross.svg
Normal file
3
src/lib/assets/cross.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="68" height="68" viewBox="0 0 68 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M43.8404 24.0416L24.0414 43.8406M24.0414 24.0416L43.8404 43.8406" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 259 B |
4
src/lib/assets/logo.svg
Normal file
4
src/lib/assets/logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 7.9 KiB |
30
src/lib/components/Button.svelte
Normal file
30
src/lib/components/Button.svelte
Normal file
@@ -0,0 +1,30 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
onclick?: (event: MouseEvent) => void;
|
||||
disabled?: boolean;
|
||||
type?: "button" | "submit" | "reset";
|
||||
children?: Snippet;
|
||||
}
|
||||
const { children, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<button {...rest}>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
|
||||
<style>
|
||||
button {
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background: linear-gradient(-83deg, #3fb095, #49bd85);
|
||||
box-shadow: 0rem 0rem 0.5rem #182125;
|
||||
color: #eaffeb;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:focus {
|
||||
outline: 2px solid #007bff;
|
||||
}
|
||||
</style>
|
||||
45
src/lib/components/Navbar.svelte
Normal file
45
src/lib/components/Navbar.svelte
Normal file
@@ -0,0 +1,45 @@
|
||||
<script lang="ts">
|
||||
import logoUrl from "$lib/assets/logo.svg";
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
const { children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src={logoUrl} alt="logo" />
|
||||
</a>
|
||||
<div class="rightButton">{@render children?.()}</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
display: flex;
|
||||
position: sticky;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(-77deg, #2e4653, #3a5b56);
|
||||
box-shadow: 0rem 0rem 0.5rem #182125;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
.logo img {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rightButton {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -5,17 +5,18 @@
|
||||
alt: string;
|
||||
imgSrc: string;
|
||||
description?: Snippet;
|
||||
href?: string;
|
||||
}
|
||||
|
||||
const { alt, imgSrc, description }: Props = $props();
|
||||
const { alt, imgSrc, description, href }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<a class="card" {href}>
|
||||
<img src={imgSrc} {alt} />
|
||||
<div class="description">
|
||||
{@render description?.()}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
.card {
|
||||
|
||||
64
src/lib/components/inputs/Image.svelte
Normal file
64
src/lib/components/inputs/Image.svelte
Normal file
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
import cameraUrl from "$lib/assets/camera.svg";
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
height?: string;
|
||||
minHeight?: string;
|
||||
files?: FileList;
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
let { name, height, minHeight, files = $bindable(), ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<label
|
||||
for={name}
|
||||
style="height: {height || 'auto'}; min-height: {minHeight || 'auto'};"
|
||||
class:no-bg={files && files.length > 0}
|
||||
>
|
||||
{#if files && files.length > 0}
|
||||
<img src={URL.createObjectURL(files[0])} alt="uploaded study space" class="preview" />
|
||||
{:else}
|
||||
<div class="message">
|
||||
<img src={cameraUrl} class="icon" alt="camera icon" />
|
||||
<span>Click to upload a photo</span>
|
||||
</div>
|
||||
{/if}
|
||||
<input type="file" id={name} {name} accept=".png, .jpg, .jpeg, .svg" {...rest} bind:files />
|
||||
</label>
|
||||
|
||||
<style>
|
||||
label {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: #eaffeb;
|
||||
cursor: pointer;
|
||||
}
|
||||
label.no-bg {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
label input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #49bd85;
|
||||
}
|
||||
.preview {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.message .icon {
|
||||
width: 2rem;
|
||||
}
|
||||
</style>
|
||||
29
src/lib/components/inputs/Text.svelte
Normal file
29
src/lib/components/inputs/Text.svelte
Normal file
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
name: string;
|
||||
value?: string | null;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
let { value = $bindable(), name, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<input type="text" id={name} {name} bind:value {...rest} />
|
||||
|
||||
<style>
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 2px solid #eaffeb;
|
||||
background: none;
|
||||
color: #eaffeb;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-color: #007bff;
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
32
src/lib/components/inputs/Textarea.svelte
Normal file
32
src/lib/components/inputs/Textarea.svelte
Normal file
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
name: string;
|
||||
value?: string | null;
|
||||
placeholder?: string;
|
||||
required?: boolean;
|
||||
rows?: number;
|
||||
cols?: number;
|
||||
}
|
||||
|
||||
let { value = $bindable(), name, ...rest }: Props = $props();
|
||||
</script>
|
||||
|
||||
<textarea id={name} {name} {...rest}></textarea>
|
||||
|
||||
<style>
|
||||
textarea {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
resize: vertical;
|
||||
border: 2px solid #eaffeb;
|
||||
background: none;
|
||||
color: #eaffeb;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
textarea:focus {
|
||||
border-color: #007bff;
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,35 @@
|
||||
<script lang="ts">
|
||||
import logoUrl from "$lib/assets/logo.svg";
|
||||
|
||||
const { children } = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Study Spaces</title>
|
||||
<link rel="icon" href={logoUrl} />
|
||||
</svelte:head>
|
||||
|
||||
{@render children?.()}
|
||||
|
||||
<style>
|
||||
:global(body) {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
:global(html) {
|
||||
background-color: #182125;
|
||||
color: #eaffeb;
|
||||
}
|
||||
|
||||
:global(*) {
|
||||
box-sizing: border-box;
|
||||
font-family: Inter;
|
||||
}
|
||||
|
||||
:global(h1, h2, h3, h4, h5, h6, p) {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,59 +1,19 @@
|
||||
<script lang="ts">
|
||||
import SpaceCard from "$lib/components/SpaceCard.svelte";
|
||||
import defaultImg from "$lib/assets/study_space.png";
|
||||
import { invalidate } from "$app/navigation";
|
||||
import type { Table } from "$lib";
|
||||
import crossUrl from "$lib/assets/cross.svg";
|
||||
import Navbar from "$lib/components/Navbar.svelte";
|
||||
|
||||
const { data } = $props();
|
||||
const { studySpaces, supabase } = $derived(data);
|
||||
|
||||
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) 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>
|
||||
|
||||
<Navbar>
|
||||
<a href="/space">
|
||||
<img src={crossUrl} alt="new" class="new-space" />
|
||||
</a>
|
||||
</Navbar>
|
||||
|
||||
<main>
|
||||
{#each studySpaces as studySpace (studySpace.id)}
|
||||
{@const imgUrl =
|
||||
@@ -62,7 +22,11 @@
|
||||
.from("files_bucket")
|
||||
.getPublicUrl(studySpace.study_space_images[0].image_path).data.publicUrl
|
||||
: defaultImg}
|
||||
<SpaceCard alt="Photo of {studySpace.description}" imgSrc={imgUrl}>
|
||||
<SpaceCard
|
||||
alt="Photo of {studySpace.description}"
|
||||
href="/space/{studySpace.id}"
|
||||
imgSrc={imgUrl}
|
||||
>
|
||||
{#snippet description()}
|
||||
<p>{studySpace.description}</p>
|
||||
{/snippet}
|
||||
@@ -70,37 +34,6 @@
|
||||
{/each}
|
||||
</main>
|
||||
|
||||
<form
|
||||
onsubmit={(e) => {
|
||||
e.preventDefault();
|
||||
uploadStudySpace();
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
|
||||
<style>
|
||||
main {
|
||||
display: grid;
|
||||
@@ -109,10 +42,8 @@
|
||||
padding: 1rem;
|
||||
width: min(600px, 100vw);
|
||||
}
|
||||
form {
|
||||
max-width: 600px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
|
||||
.new-space {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
</style>
|
||||
|
||||
118
src/routes/space/+page.svelte
Normal file
118
src/routes/space/+page.svelte
Normal file
@@ -0,0 +1,118 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import Text from "$lib/components/inputs/Text.svelte";
|
||||
import Textarea from "$lib/components/inputs/Textarea.svelte";
|
||||
import Navbar from "$lib/components/Navbar.svelte";
|
||||
import crossUrl from "$lib/assets/cross.svg";
|
||||
import Button from "$lib/components/Button.svelte";
|
||||
import Image from "$lib/components/inputs/Image.svelte";
|
||||
import type { Table } from "$lib";
|
||||
|
||||
const { data } = $props();
|
||||
const { supabase } = $derived(data);
|
||||
|
||||
let spaceImg = $state<FileList>();
|
||||
let studySpaceData = $state<Omit<Table<"study_spaces">, "id" | "created_at" | "updated_at">>({
|
||||
description: "",
|
||||
building_address: "",
|
||||
location: ""
|
||||
});
|
||||
|
||||
async function uploadStudySpace() {
|
||||
const imageFile = spaceImg?.[0];
|
||||
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}`);
|
||||
|
||||
alert("Thank you for your contribution!");
|
||||
// Redirect to the new study space page
|
||||
await goto(`/space/${studySpaceInsert.id}`, {
|
||||
invalidate: ["db:study_spaces"]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<Navbar>
|
||||
<a href="/">
|
||||
<img src={crossUrl} alt="close" />
|
||||
</a>
|
||||
</Navbar>
|
||||
|
||||
<form
|
||||
onsubmit={async (event) => {
|
||||
event.preventDefault();
|
||||
await uploadStudySpace();
|
||||
}}
|
||||
>
|
||||
<Image name="study-space-image" minHeight="16rem" bind:files={spaceImg} />
|
||||
|
||||
<label for="location">Enter the name:</label>
|
||||
<Text name="location" bind:value={studySpaceData.location} placeholder="Room 123, Floor 1" />
|
||||
|
||||
<label for="description">Add a description:</label>
|
||||
<Textarea
|
||||
name="description"
|
||||
bind:value={studySpaceData.description}
|
||||
placeholder="A quiet, but small study space..."
|
||||
rows={5}
|
||||
/>
|
||||
|
||||
<label for="address">Add an address:</label>
|
||||
<Text
|
||||
name="address"
|
||||
bind:value={studySpaceData.building_address}
|
||||
placeholder="180 Queen's Gate, London, SW7 5HF"
|
||||
/>
|
||||
|
||||
<div class="submit">
|
||||
<Button type="submit">Share this study space!</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1.5rem;
|
||||
gap: 0.5rem;
|
||||
max-width: 32rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
label {
|
||||
color: #ffffff;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.submit {
|
||||
position: sticky;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 0.5rem;
|
||||
bottom: 0;
|
||||
margin-left: -0.5rem;
|
||||
width: calc(100% + 1rem);
|
||||
}
|
||||
</style>
|
||||
13
src/routes/space/[id]/+page.server.ts
Normal file
13
src/routes/space/[id]/+page.server.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { error } from "@sveltejs/kit";
|
||||
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(*)")
|
||||
.eq("id", params.id)
|
||||
.single();
|
||||
if (err) error(500, "Failed to load study space");
|
||||
|
||||
return { space };
|
||||
};
|
||||
97
src/routes/space/[id]/+page.svelte
Normal file
97
src/routes/space/[id]/+page.svelte
Normal file
@@ -0,0 +1,97 @@
|
||||
<script lang="ts">
|
||||
import Navbar from "$lib/components/Navbar.svelte";
|
||||
import crossUrl from "$lib/assets/cross.svg";
|
||||
import placeholder from "$lib/assets/study_space.png";
|
||||
|
||||
const { data } = $props();
|
||||
const { space, supabase } = $derived(data);
|
||||
|
||||
const imgUrl = $derived(
|
||||
space.study_space_images.length > 0
|
||||
? supabase.storage
|
||||
.from("files_bucket")
|
||||
.getPublicUrl(space.study_space_images[0].image_path).data.publicUrl
|
||||
: placeholder
|
||||
);
|
||||
</script>
|
||||
|
||||
<Navbar>
|
||||
<a href="/">
|
||||
<img src={crossUrl} alt="close" />
|
||||
</a>
|
||||
</Navbar>
|
||||
|
||||
<main>
|
||||
<img src={imgUrl} alt="the study space" />
|
||||
<div class="nameContainer">
|
||||
{space.location}
|
||||
</div>
|
||||
<p class="descContainer">
|
||||
{space.description}
|
||||
</p>
|
||||
<hr />
|
||||
<div class="whereSubtitle">Where it is:</div>
|
||||
<p class="addrContainer">
|
||||
{space.building_address}
|
||||
</p>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 0 1rem 0;
|
||||
max-width: 32rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 1/0.8;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 2px;
|
||||
background-color: #2e3c42;
|
||||
width: 70%;
|
||||
border: none;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.nameContainer {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.6rem;
|
||||
margin-top: -0.5rem;
|
||||
object-position: center;
|
||||
background-color: #49bd85;
|
||||
border-radius: 8px;
|
||||
font-size: 2.8rem;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.descContainer {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 1.4rem;
|
||||
margin-top: -0.5rem;
|
||||
object-position: center;
|
||||
border-radius: 8px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.whereSubtitle {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
padding: 1.4rem;
|
||||
}
|
||||
|
||||
.addrContainer {
|
||||
font-size: 1.2rem;
|
||||
padding: 0rem 1.4rem;
|
||||
}
|
||||
</style>
|
||||
BIN
static/Inter.ttf
Normal file
BIN
static/Inter.ttf
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -3,6 +3,9 @@ import { sveltekit } from "@sveltejs/kit/vite";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
allowedHosts: ["localhost", "bf05-2a00-23c6-9fa6-7b40-f028-650e-65f0-1c99.ngrok-free.app"]
|
||||
},
|
||||
plugins: [sveltekit()],
|
||||
test: {
|
||||
workspace: [
|
||||
|
||||
Reference in New Issue
Block a user