95 lines
2.3 KiB
Svelte
95 lines
2.3 KiB
Svelte
|
<script lang="ts">
|
||
|
import { enhance } from '$app/forms';
|
||
|
import type { ActionData } from './$types';
|
||
|
|
||
|
export let form: ActionData;
|
||
|
|
||
|
let files: FileList;
|
||
|
let sending = false;
|
||
|
|
||
|
const siPrefixes = new Map([
|
||
|
[1_000_000, 'M'],
|
||
|
[1_000, 'k']
|
||
|
]);
|
||
|
const fileSize = (files: FileList) => {
|
||
|
const size = Array.from(files)
|
||
|
.map((f) => f.size)
|
||
|
.reduce((a, b) => a + b, 0);
|
||
|
return (
|
||
|
Array.from(siPrefixes)
|
||
|
.filter(([k]) => size >= k)
|
||
|
.map(([k, v]) => `${(size / k).toFixed(1)} ${v}B`)[0] ?? `${size} bytes`
|
||
|
);
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<form
|
||
|
enctype="multipart/form-data"
|
||
|
class="box"
|
||
|
method="POST"
|
||
|
use:enhance={() => {
|
||
|
sending = true;
|
||
|
return ({ update }) => {
|
||
|
update({ invalidateAll: true }).finally(async () => {
|
||
|
sending = false;
|
||
|
});
|
||
|
};
|
||
|
}}
|
||
|
>
|
||
|
{#if sending}
|
||
|
<div class="notification is-info">Wird hochgeladen...</div>
|
||
|
{:else if form?.success}
|
||
|
<div class="notification is-success">Erfolgreich hochgeladen</div>
|
||
|
{/if}
|
||
|
<div class="field">
|
||
|
<label for="name" class="label">Name</label>
|
||
|
<div class="control">
|
||
|
<input
|
||
|
id="name"
|
||
|
class="input"
|
||
|
type="text"
|
||
|
name="name"
|
||
|
placeholder="Name"
|
||
|
value={form?.name ?? ''}
|
||
|
required
|
||
|
/>
|
||
|
</div>
|
||
|
{#if form?.field === 'name'}
|
||
|
{#if form?.missing}
|
||
|
<p class="help is-danger">Bitte einen Namen angeben</p>
|
||
|
{:else if form?.incorrect}
|
||
|
<p class="help is-danger">Ungültiger Name</p>
|
||
|
{/if}
|
||
|
{/if}
|
||
|
</div>
|
||
|
|
||
|
<div class="file is-centered has-name is-boxed">
|
||
|
<label class="file-label">
|
||
|
<input class="file-input" type="file" name="files" bind:files multiple required />
|
||
|
<span class="file-cta">
|
||
|
<span class="file-label">Fotos auswählen...</span>
|
||
|
</span>
|
||
|
{#if files}
|
||
|
<span class="file-name"
|
||
|
>{files.length} Bild{#if files.length > 1}er{/if} ausgewählt ({fileSize(files)})</span
|
||
|
>
|
||
|
{:else}
|
||
|
<span class="file-name">Keine Bilder ausgewählt</span>
|
||
|
{/if}
|
||
|
{#if form?.field === 'files'}
|
||
|
{#if form?.missing || form?.empty}
|
||
|
<p class="help is-danger">Bitte mindestens eine Datei auswählen</p>
|
||
|
{:else if form?.incorrect}
|
||
|
<p class="help is-danger">Ungültige Dateien</p>
|
||
|
{/if}
|
||
|
{/if}
|
||
|
</label>
|
||
|
</div>
|
||
|
|
||
|
<div class="field is-grouped is-grouped-centered">
|
||
|
<div class="control">
|
||
|
<button class="button is-link">Hochladen</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</form>
|