Files
koc-loop/app/login/page.tsx

70 lines
2.1 KiB
TypeScript
Raw Normal View History

"use client";
import { FormEvent, useState } from "react";
export default function LoginPage() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [working, setWorking] = useState(false);
const submit = async (event: FormEvent) => {
event.preventDefault();
setError("");
setWorking(true);
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
});
const result = (await response.json()) as { error?: string };
if (!response.ok) throw new Error(result.error || "登录失败");
window.location.assign("/");
} catch (reason) {
setError(reason instanceof Error ? reason.message : "登录失败");
} finally {
setWorking(false);
}
};
return (
<main className="login-page">
<section className="login-brand">
<div className="login-logo">K</div>
<p>KOC LOOP</p>
<h1></h1>
<span>KOC </span>
</section>
<form className="login-card" onSubmit={submit}>
<p className="eyebrow"></p>
<h2></h2>
<span className="login-tip">使</span>
<label>
<span></span>
<input
value={username}
onChange={(event) => setUsername(event.target.value)}
autoComplete="username"
required
/>
</label>
<label>
<span></span>
<input
type="password"
value={password}
onChange={(event) => setPassword(event.target.value)}
autoComplete="current-password"
required
/>
</label>
{error && <p className="login-error">{error}</p>}
<button className="primary-button" disabled={working}>
{working ? "登录中…" : "登录"}
</button>
</form>
</main>
);
}