From 42f1b4de384bcbbdab3b80d8e5cc53b36fcffd50 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Thu, 12 Feb 2026 21:50:56 -0800 Subject: Implement frontend login logic with >90% coverage --- frontend/src/components/Login.tsx | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 frontend/src/components/Login.tsx (limited to 'frontend/src/components/Login.tsx') diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx new file mode 100644 index 0000000..2e8bbf7 --- /dev/null +++ b/frontend/src/components/Login.tsx @@ -0,0 +1,54 @@ +import { useState, type FormEvent } from 'react'; +import { useNavigate } from 'react-router-dom'; +import './Login.css'; + +export default function Login() { + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + const navigate = useNavigate(); + + const handleSubmit = async (e: FormEvent) => { + e.preventDefault(); + setError(''); + + try { + // Use URLSearchParams to send as form-urlencoded, matching backend expectation + const params = new URLSearchParams(); + params.append('password', password); + + const res = await fetch('/api/login', { + method: 'POST', + body: params, + }); + + if (res.ok) { + navigate('/'); + } else { + const data = await res.json(); + setError(data.message || 'Login failed'); + } + } catch (err) { + setError('Network error'); + } + }; + + return ( +
+
+

neko rss mode

+
+ + setPassword(e.target.value)} + autoFocus + /> +
+ {error &&
{error}
} + +
+
+ ); +} -- cgit v1.2.3