feat: initial uploads and single study space view

Co-Authored-By: Alex Ling <al443@ic.ac.uk>
This commit is contained in:
2025-06-04 18:10:45 +01:00
parent b02f2b2303
commit 40435df5e2
16 changed files with 486 additions and 86 deletions

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

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

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