add 404.html and new upload page

This commit is contained in:
Christian Krakau-Louis
2025-03-25 21:16:02 +01:00
parent ff12e733ea
commit b95d13df1f
3 changed files with 107 additions and 29 deletions
+6 -2
View File
@@ -1,5 +1,5 @@
# app/frontend.py (new file or inline in main.py) # app/frontend.py (new file or inline in main.py)
from fastapi import APIRouter, Request from fastapi import APIRouter, Request, status
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from app.auth import require_login from app.auth import require_login
@@ -24,4 +24,8 @@ async def serve_upload(request: Request):
# 3) Serve favicon.ico from the frontend folder # 3) Serve favicon.ico from the frontend folder
@router.get("/favicon.ico", response_class=FileResponse) @router.get("/favicon.ico", response_class=FileResponse)
def favicon(): def favicon():
return os.path.join(frontend_folder, "favicon.ico") return os.path.join(frontend_folder, "favicon.ico")
@app.exception_handler(404)
async def custom_404_handler(request: Request, exc):
return FileResponse("frontend/404.html", status_code=status.HTTP_404_NOT_FOUND)
+21
View File
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>404 - Page not found</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="bg-gray-50 h-screen flex flex-col items-center justify-center">
<h1 class="text-4xl font-bold mb-4">404 - Page not found</h1>
<p class="text-gray-700 mb-8">
Sorry, we couldnt find the page youre looking for.
</p>
<a
href="/"
class="text-blue-600 underline text-lg hover:text-blue-800"
>
&larr; Back to home
</a>
</body>
</html>
+80 -27
View File
@@ -1,45 +1,78 @@
<!-- File: frontend/index.html -->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Document Processor - Upload</title> <title>Document Processor - Upload</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Tailwind via CDN or your own build -->
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script> <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script>
// Optional: Additional JS for drag-and-drop, or you can keep it inline.
</script>
</head> </head>
<body class="bg-gray-50 h-screen flex flex-col items-center justify-center"> <body class="bg-gray-50 h-screen flex flex-col">
<h1 class="text-3xl font-bold mb-8">Upload a File</h1>
<div <!-- Navigation Bar -->
id="dropZone" <nav class="bg-white shadow">
class="border-4 border-dashed border-gray-300 rounded-lg p-8 bg-white text-center w-1/2" <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex justify-between h-16 items-center">
ondrop="handleDrop(event)" <!-- Brand -->
ondragover="handleDragOver(event)" <div class="flex-shrink-0">
> <a href="/" class="text-xl font-bold text-blue-500 hover:text-blue-700">
<p class="text-gray-500"> Document Processor
Drag & drop a file here, or click to select a file. </a>
</p> </div>
<input <!-- Menu items on the right -->
id="fileInput" <div class="flex space-x-4 items-center">
type="file" <!-- Example link to /upload (current page), or other pages -->
class="hidden" <a href="/upload" class="text-gray-700 hover:text-gray-900">
onchange="handleFileSelect(event)" Upload
/> </a>
</div> <!-- Placeholder for future pages -->
<a href="/some-other" class="text-gray-700 hover:text-gray-900">
Some Page
</a>
<!-- Dynamic login/logout section -->
<div id="authSection" class="text-gray-700 hover:text-gray-900"></div>
</div>
</div>
</nav>
<div id="statusMessage" class="mt-4 text-gray-700"></div> <!-- Main content area -->
<main class="flex-grow flex flex-col items-center justify-center p-8">
<h1 class="text-3xl font-bold mb-8">Upload a File</h1>
<div
id="dropZone"
class="border-4 border-dashed border-gray-300 rounded-lg p-8 bg-white text-center w-full max-w-lg"
ondrop="handleDrop(event)"
ondragover="handleDragOver(event)"
>
<p class="text-gray-500 mb-4">
Drag & drop a file here, or click to select a file.
</p>
<input
id="fileInput"
type="file"
class="hidden"
onchange="handleFileSelect(event)"
/>
</div>
<div id="statusMessage" class="mt-4 text-gray-700"></div>
</main>
<!-- Footer (optional) -->
<footer class="bg-white shadow mt-auto">
<div class="max-w-7xl mx-auto px-4 py-4 text-center text-gray-600">
&copy; 2025 Document Processor - All rights reserved.
</div>
</footer>
<!-- JavaScript -->
<script> <script>
// 1) Drag-and-drop / file input logic
const dropZone = document.getElementById("dropZone"); const dropZone = document.getElementById("dropZone");
const fileInput = document.getElementById("fileInput"); const fileInput = document.getElementById("fileInput");
const statusMessage = document.getElementById("statusMessage"); const statusMessage = document.getElementById("statusMessage");
dropZone.addEventListener("click", () => { dropZone.addEventListener("click", () => fileInput.click());
fileInput.click();
});
function handleDragOver(e) { function handleDragOver(e) {
e.preventDefault(); e.preventDefault();
@@ -65,7 +98,6 @@
statusMessage.textContent = `Uploading ${file.name}...`; statusMessage.textContent = `Uploading ${file.name}...`;
try { try {
// We'll POST the file to /upload
let formData = new FormData(); let formData = new FormData();
formData.append("file", file); formData.append("file", file);
@@ -84,6 +116,27 @@
statusMessage.textContent = `Error: ${err}`; statusMessage.textContent = `Error: ${err}`;
} }
} }
// 2) Example dynamic auth check: if you have an endpoint like /api/whoami
// that returns JSON with { email: "..."} if logged in, or 401 if not.
(async function checkAuth() {
try {
const resp = await fetch("/api/whoami");
if (resp.ok) {
const data = await resp.json();
document.getElementById("authSection").innerHTML =
`Logged in as <strong>${data.email}</strong> <a href="/logout" class="ml-2 text-blue-600">Logout</a>`;
} else {
// If 401 or other non-OK status => show Login link
document.getElementById("authSection").innerHTML =
`<a href="/login" class="text-blue-600">Login</a>`;
}
} catch (error) {
// If fetch fails, also show login
document.getElementById("authSection").innerHTML =
`<a href="/login" class="text-blue-600">Login</a>`;
}
})();
</script> </script>
</body> </body>
</html> </html>