First Commit. AI Generated App.

This commit is contained in:
2026-01-21 21:17:22 -05:00
parent ea70d85f9d
commit 4345b7bcdd
22 changed files with 449 additions and 208 deletions
+9 -9
View File
@@ -36,15 +36,15 @@
<p class="text-tokyo-fg-dark">{error}</p>
</div>
</div>
{:else if ebooks.length === 0}
<div class="card max-w-lg mx-auto text-center">
<div class="card-body">
<div class="text-6xl mb-4">📖</div>
<h3 class="text-2xl font-semibold text-tokyo-fg mb-2">Welcome to your library!</h3>
<p class="text-tokyo-fg-dark mb-6">You haven't added any ebooks yet. Start building your collection by uploading your favorite books.</p>
<button class="btn-primary">Add Your First Ebook</button>
</div>
</div>
{:else if ebooks.length === 0}
<div class="card max-w-lg mx-auto text-center">
<div class="card-body">
<div class="text-6xl mb-4">📖</div>
<h3 class="text-2xl font-semibold text-tokyo-fg mb-2">Welcome to your library!</h3>
<p class="text-tokyo-fg-dark mb-6">You haven't added any ebooks yet. Start building your collection by uploading your favorite books.</p>
<a href="/upload" class="btn-primary inline-block">Add Your First Ebook</a>
</div>
</div>
{:else}
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8">
{#each ebooks as ebook (ebook.id)}
@@ -0,0 +1,34 @@
import type { Actions } from './$types';
import { createEbook } from '$lib/api';
import { redirect } from '@sveltejs/kit';
export const actions: Actions = {
default: async ({ request, fetch }) => {
const data = await request.formData();
const title = data.get('title') as string;
const author = data.get('author') as string;
const description = data.get('description') as string;
const file = data.get('file') as File;
if (!title || !file) {
return { success: false, error: 'Title and file are required' };
}
try {
// For now, simulate upload - in reality, the backend would handle file upload
// and return the ebook data
const ebookData = {
title,
author: author || null,
description: description || null,
file_path: `/uploads/${file.name}`, // Placeholder
};
await createEbook(ebookData);
throw redirect(303, '/');
} catch (err) {
if (err instanceof Response) throw err; // Redirect
return { success: false, error: err instanceof Error ? err.message : 'Upload failed' };
}
},
};
+105
View File
@@ -0,0 +1,105 @@
<script lang="ts">
import { enhance } from '$app/forms';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { showError } from '$lib/toast';
let loading = false;
</script>
<svelte:head>
<title>Upload Ebook - Bookmann</title>
</svelte:head>
<div class="min-h-screen flex items-center justify-center bg-gradient-to-br from-tokyo-bg to-tokyo-bg-dark py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full animate-slide-in">
<div class="card">
<div class="card-header text-center">
<div class="text-4xl mb-4">📤</div>
<h2 class="text-2xl font-bold text-tokyo-fg">
Upload Ebook
</h2>
<p class="text-tokyo-fg-dark mt-2">Add a new book to your library</p>
</div>
<div class="card-body">
<form method="POST" enctype="multipart/form-data" use:enhance={() => {
loading = true;
return async ({ update }) => {
try {
await update();
goto('/');
} catch (err) {
showError('Upload failed');
} finally {
loading = false;
}
};
}}>
<div class="space-y-6">
<div>
<label for="title" class="block text-sm font-medium text-tokyo-fg mb-2">
Title *
</label>
<input
id="title"
name="title"
type="text"
required
class="input-field w-full"
placeholder="Enter book title"
/>
</div>
<div>
<label for="author" class="block text-sm font-medium text-tokyo-fg mb-2">
Author
</label>
<input
id="author"
name="author"
type="text"
class="input-field w-full"
placeholder="Enter author name"
/>
</div>
<div>
<label for="description" class="block text-sm font-medium text-tokyo-fg mb-2">
Description
</label>
<textarea
id="description"
name="description"
rows="3"
class="input-field w-full resize-none"
placeholder="Brief description of the book"
></textarea>
</div>
<div>
<label for="file" class="block text-sm font-medium text-tokyo-fg mb-2">
Ebook File *
</label>
<input
id="file"
name="file"
type="file"
accept=".pdf,.epub,.mobi,.txt"
required
class="input-field w-full file:mr-4 file:py-2 file:px-4 file:rounded-l file:border-0 file:text-sm file:font-semibold file:bg-tokyo-bg-highlight file:text-tokyo-fg hover:file:bg-tokyo-bg-selection"
/>
</div>
</div>
<button
type="submit"
disabled={loading}
class="btn-primary w-full flex justify-center items-center mt-6 disabled:opacity-50 disabled:cursor-not-allowed"
>
{#if loading}
<div class="animate-spin rounded-full h-4 w-4 border-2 border-white border-t-transparent mr-2"></div>
{/if}
{loading ? 'Uploading...' : 'Upload Ebook'}
</button>
</form>
</div>
</div>
</div>
</div>