feat(auth): add frontend login and route protection

This commit is contained in:
DS | Schubert 2026-07-02 17:00:50 +02:00
parent 6f7cae9e24
commit 4bc8b20a21
5 changed files with 116 additions and 19 deletions

View file

@ -32,7 +32,7 @@ def login(
key="access_token",
value=token,
httponly=True,
secure=True,
secure=False,
samesite="lax",
max_age=3600,
)

View file

@ -0,0 +1,15 @@
export default function DashboardPage() {
return (
<main className="min-h-screen bg-slate-100">
<div className="mx-auto max-w-7xl p-8">
<h1 className="text-4xl font-bold">
Olympus Dashboard
</h1>
<p className="mt-4 text-slate-600">
Willkommen bei Funktechnik Schubert.
</p>
</div>
</main>
);
}

View file

@ -0,0 +1,79 @@
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
export default function LoginPage() {
const router = useRouter();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
async function handleLogin(e: React.FormEvent) {
e.preventDefault();
setError("");
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/auth/login`,
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username,
password,
}),
}
);
if (response.ok) {
router.push("/dashboard");
return;
}
setError("Benutzername oder Passwort ist falsch.");
}
return (
<main className="flex min-h-screen items-center justify-center bg-slate-100">
<form
onSubmit={handleLogin}
className="w-full max-w-md rounded-xl bg-white p-8 shadow-xl"
>
<h1 className="mb-8 text-center text-3xl font-bold">
Olympus CRM
</h1>
<input
className="mb-4 w-full rounded border p-3"
placeholder="Benutzername"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<input
className="mb-4 w-full rounded border p-3"
type="password"
placeholder="Passwort"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
{error && (
<p className="mb-4 text-red-600">
{error}
</p>
)}
<button
className="w-full rounded bg-blue-600 p-3 text-white hover:bg-blue-700"
>
Anmelden
</button>
</form>
</main>
);
}

View file

@ -1,20 +1,5 @@
import StatCard from "@/components/StatCard";
import UserCounter from "@/components/UserCounter";
import { redirect } from "next/navigation";
export default function Home() {
return (
<>
<div className="grid grid-cols-4 gap-6">
<StatCard title="Benutzer" value={<UserCounter />} />
<StatCard title="Kunden" value="0" />
<StatCard title="Reparaturen" value="0" />
<StatCard title="Lager" value="0" />
</div>
</>
);
export default function HomePage() {
redirect("/login");
}

View file

@ -0,0 +1,18 @@
import { NextRequest, NextResponse } from "next/server";
export function middleware(request: NextRequest) {
const token = request.cookies.get("access_token");
if (!token) {
return NextResponse.redirect(new URL("/login", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
"/dashboard/:path*",
"/users/:path*",
],
};