From 104341ddc4add57f83c58cb3fabb23b6fbfdd3e4 Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Sun, 2 Nov 2025 00:00:35 +0900
Subject: wip

---
 frontend/src/pages/Login.tsx | 133 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)
 create mode 100644 frontend/src/pages/Login.tsx

(limited to 'frontend/src/pages/Login.tsx')

diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx
new file mode 100644
index 0000000..5703047
--- /dev/null
+++ b/frontend/src/pages/Login.tsx
@@ -0,0 +1,133 @@
+import { useState } from "react";
+import { useLocation } from "wouter";
+import { useAuth } from "../contexts/AuthContext";
+
+export function Login() {
+	const [username, setUsername] = useState("");
+	const [password, setPassword] = useState("");
+	const [error, setError] = useState("");
+	const [isLoading, setIsLoading] = useState(false);
+	const { login } = useAuth();
+	const [, setLocation] = useLocation();
+
+	const handleSubmit = async (e: React.FormEvent) => {
+		e.preventDefault();
+		setError("");
+		setIsLoading(true);
+
+		try {
+			const success = await login(username, password);
+			if (success) {
+				setLocation("/");
+			} else {
+				setError("Invalid username or password");
+			}
+		} catch (_err) {
+			setError("An error occurred during login");
+		} finally {
+			setIsLoading(false);
+		}
+	};
+
+	return (
+		<div
+			style={{
+				display: "flex",
+				justifyContent: "center",
+				alignItems: "center",
+				minHeight: "100vh",
+				backgroundColor: "#f5f5f5",
+			}}
+		>
+			<div
+				style={{
+					backgroundColor: "white",
+					padding: "2rem",
+					borderRadius: "8px",
+					boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
+					width: "100%",
+					maxWidth: "400px",
+				}}
+			>
+				<h1 style={{ marginBottom: "1.5rem", textAlign: "center" }}>
+					Feedaka Login
+				</h1>
+				<form onSubmit={handleSubmit}>
+					<div style={{ marginBottom: "1rem" }}>
+						<label
+							htmlFor="username"
+							style={{ display: "block", marginBottom: "0.5rem" }}
+						>
+							Username
+						</label>
+						<input
+							id="username"
+							type="text"
+							value={username}
+							onChange={(e) => setUsername(e.target.value)}
+							required
+							style={{
+								width: "100%",
+								padding: "0.5rem",
+								border: "1px solid #ccc",
+								borderRadius: "4px",
+							}}
+							disabled={isLoading}
+						/>
+					</div>
+					<div style={{ marginBottom: "1rem" }}>
+						<label
+							htmlFor="password"
+							style={{ display: "block", marginBottom: "0.5rem" }}
+						>
+							Password
+						</label>
+						<input
+							id="password"
+							type="password"
+							value={password}
+							onChange={(e) => setPassword(e.target.value)}
+							required
+							style={{
+								width: "100%",
+								padding: "0.5rem",
+								border: "1px solid #ccc",
+								borderRadius: "4px",
+							}}
+							disabled={isLoading}
+						/>
+					</div>
+					{error && (
+						<div
+							style={{
+								color: "red",
+								marginBottom: "1rem",
+								padding: "0.5rem",
+								backgroundColor: "#fee",
+								borderRadius: "4px",
+							}}
+						>
+							{error}
+						</div>
+					)}
+					<button
+						type="submit"
+						disabled={isLoading}
+						style={{
+							width: "100%",
+							padding: "0.75rem",
+							backgroundColor: "#007bff",
+							color: "white",
+							border: "none",
+							borderRadius: "4px",
+							cursor: isLoading ? "not-allowed" : "pointer",
+							opacity: isLoading ? 0.7 : 1,
+						}}
+					>
+						{isLoading ? "Logging in..." : "Login"}
+					</button>
+				</form>
+			</div>
+		</div>
+	);
+}
-- 
cgit v1.2.3-70-g09d2

