From 4fd6456e289d8a04d887ee6435ac31a85d0c453f Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Sat, 14 Mar 2026 00:03:35 -0700 Subject: [PATCH] Feat: Build frontend login page with captcha --- app/page.js | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 app/page.js diff --git a/app/page.js b/app/page.js new file mode 100644 index 0000000..04a50fc --- /dev/null +++ b/app/page.js @@ -0,0 +1,104 @@ +'use client'; +import { useState, useRef } from 'react'; + +export default function LoginPage() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [captcha, setCaptcha] = useState(''); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(''); + const captchaImgRef = useRef(null); + + const refreshCaptcha = () => { + if (captchaImgRef.current) { + captchaImgRef.current.src = `/api/captcha?${new Date().getTime()}`; + } + }; + + const handleLogin = async (e) => { + e.preventDefault(); + setError(''); + setSuccess(''); + + const res = await fetch('/api/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password, captcha }) + }); + + const data = await res.json(); + if (!res.ok) { + setError(data.error); + refreshCaptcha(); + setCaptcha(''); + } else { + setSuccess(data.message); + } + }; + + return ( +
+
+

Kalbot Access

+ + {error &&
{error}
} + {success &&
{success}
} + +
+
+ + setEmail(e.target.value)} + /> +
+
+ + setPassword(e.target.value)} + /> +
+ +
+ +
+ captcha + +
+ setCaptcha(e.target.value)} + /> +
+ + +
+
+
+ ); +}