Initial commit

This commit is contained in:
hiperman
2025-12-04 00:33:37 -05:00
commit 7ca0a21283
798 changed files with 190424 additions and 0 deletions
@@ -0,0 +1,98 @@
<script lang="ts">
import { uploadBookFiles } from '$lib/api';
import {
displaySize,
FileDropZone,
type FileDropZoneProps
} from '$lib/components/ui/file-drop-zone';
import { Button } from '$lib/components/ui/button';
import * as Field from '$lib/components/ui/field/index.js';
import { Switch } from '$lib/components/ui/switch/index';
import { X } from '@lucide/svelte';
import type { Book } from '$lib/schema';
import { tick } from 'svelte';
import { toast } from 'svelte-sonner';
let { book }: { book: Book } = $props();
let files = $derived(uploadBookFiles.fields.files.value() ?? []);
let autoUploadOnDrop = $state(true);
let formEl = $state<HTMLFormElement>();
const onUpload: FileDropZoneProps['onUpload'] = async (uploadedFiles) => {
uploadBookFiles.fields.files.set([...Array.from(files), ...uploadedFiles]);
if (autoUploadOnDrop && files.length > 0) {
await tick();
formEl?.requestSubmit();
}
};
const onFileRejected: FileDropZoneProps['onFileRejected'] = async ({ reason, file }) => {
toast.error(`${file.name} failed to upload!`, { description: reason });
};
</script>
<form
{...uploadBookFiles.enhance(async ({ submit, form }) => {
try {
await submit();
// Check if there are any validation issues
const issues = uploadBookFiles.fields.allIssues();
if (issues && issues.length > 0) {
return;
}
// Reset the files field
uploadBookFiles.fields.files.set([]);
toast.success('Files successfully added!');
} catch (error) {
console.error('Failed to upload files: ', error);
toast.error('Failed to upload files');
}
})}
bind:this={formEl}
enctype="multipart/form-data"
class="flex w-full flex-col gap-2 p-4"
>
<input {...uploadBookFiles.fields.book_id.as('hidden', book.id)} />
<FileDropZone
{onUpload}
{onFileRejected}
accept=".pdf,.epub,.mobi,application/pdf,application/epub+zip,application/x-mobipocket-ebook"
sublabel="Only PDF, EPUB, and MOBI files supported"
/>
<input class="hidden" {...uploadBookFiles.fields.files.as('file multiple')} />
<div class="flex flex-col gap-2">
{#each files as file, idx}
<div class="flex place-items-center justify-between gap-2">
<div class="flex flex-col">
<span>{file.name}</span>
<span class="text-xs text-muted-foreground">{displaySize(file.size)}</span>
</div>
<Button
variant="outline"
size="icon"
onclick={() => {
uploadBookFiles.fields.files.set([
...Array.from(files).slice(0, idx),
...Array.from(files).slice(idx + 1)
]);
}}
>
<X />
</Button>
</div>
{/each}
</div>
<div class="flex flex-row items-center space-x-2">
<Switch bind:checked={autoUploadOnDrop} />
<Field.Label for="auto-upload-on-drop">Auto upload on file drop</Field.Label>
<Button type="submit" class="ml-auto w-fit">Upload</Button>
</div>
</form>