Archived
Implement: Refactor: Consolidate Duplicate Backend and Frontend Implementations (#11)
Reviewed and merged by Reid (Hermes Reviewer) Co-authored-by: crisleo-hermes <hermes@codescripters.org> Co-committed-by: crisleo-hermes <hermes@codescripters.org>
This commit was merged in pull request #11.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import React, { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { booksApi } from "../api/books";
|
||||
|
||||
export function AddBookPage() {
|
||||
const navigate = useNavigate();
|
||||
const [title, setTitle] = useState("");
|
||||
const [author, setAuthor] = useState("");
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const selected = e.target.files?.[0] ?? null;
|
||||
if (selected) {
|
||||
const ext = selected.name.split(".").pop()?.toLowerCase();
|
||||
if (ext !== "epub" && ext !== "pdf") { setError("Only EPUB and PDF files are supported."); setFile(null); return; }
|
||||
setFile(selected); setError(null);
|
||||
if (!title) setTitle(selected.name.replace(/\.(epub|pdf)$/i, ""));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!file || !title.trim()) { setError("Title and file are required."); return; }
|
||||
setUploading(true); setError(null);
|
||||
try { await booksApi.uploadEBook(file, title.trim(), author.trim()); navigate("/"); }
|
||||
catch (err) { setError(err instanceof Error ? err.message : "Upload failed."); }
|
||||
finally { setUploading(false); }
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: 500, margin: "0 auto", padding: 16, minHeight: "100vh", background: "#f8f9fa" }}>
|
||||
<header style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 24, padding: "16px 0", borderBottom: "1px solid #eee" }}>
|
||||
<button onClick={() => navigate("/")} style={{ padding: "8px 16px", borderRadius: 6, border: "1px solid #ddd", background: "#fff", cursor: "pointer", fontSize: 14 }}>← Back</button>
|
||||
<h1 style={{ fontSize: 24, fontWeight: 700, color: "#1a1a2e", margin: 0 }}>Add Book</h1>
|
||||
</header>
|
||||
<form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column", gap: 20 }}>
|
||||
{error && <div style={{ background: "#fde8e8", padding: 12, borderRadius: 6, color: "#e74c3c", fontSize: 14 }}>{error}</div>}
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
||||
<label style={{ fontSize: 14, fontWeight: 600, color: "#555" }}>File (EPUB or PDF) *</label>
|
||||
<input type="file" accept=".epub,.pdf" onChange={handleFileChange} style={{ padding: "10px 0" }} />
|
||||
{file && <p style={{ fontSize: 13, color: "#666", marginTop: 4 }}>Selected: {file.name}</p>}
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
||||
<label style={{ fontSize: 14, fontWeight: 600, color: "#555" }}>Title *</label>
|
||||
<input type="text" value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Book title" style={{ padding: "10px 12px", borderRadius: 6, border: "1px solid #ddd", fontSize: 16, outline: "none" }} />
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
||||
<label style={{ fontSize: 14, fontWeight: 600, color: "#555" }}>Author</label>
|
||||
<input type="text" value={author} onChange={(e) => setAuthor(e.target.value)} placeholder="Author name" style={{ padding: "10px 12px", borderRadius: 6, border: "1px solid #ddd", fontSize: 16, outline: "none" }} />
|
||||
</div>
|
||||
<button type="submit" disabled={uploading} style={{ padding: "12px 24px", borderRadius: 8, border: "none", background: "#1a1a2e", color: "#fff", fontSize: 16, fontWeight: 600, cursor: "pointer", opacity: uploading ? 0.6 : 1, marginTop: 8 }}>{uploading ? "Uploading..." : "Upload Book"}</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user