caca
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { useState } from "react";
|
||||
import type { FormEvent } from "react";
|
||||
|
||||
type LoginPageProps = {
|
||||
busy: boolean;
|
||||
error: string | null;
|
||||
onLogin: (email: string, password: string, totpCode?: string) => Promise<void>;
|
||||
};
|
||||
|
||||
export const LoginPage = ({ busy, error, onLogin }: LoginPageProps) => {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [totpCode, setTotpCode] = useState("");
|
||||
|
||||
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
await onLogin(email, password, totpCode || undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="auth-shell">
|
||||
<section className="auth-card">
|
||||
<div className="auth-card__eyebrow">Public internet hardened</div>
|
||||
<h1>Secure Webmail</h1>
|
||||
<p>
|
||||
Sessions stay on the server, cookies are <code>httpOnly</code>, and every state-changing request carries an in-memory CSRF token.
|
||||
</p>
|
||||
|
||||
<form className="auth-form" onSubmit={handleSubmit}>
|
||||
<label>
|
||||
Email
|
||||
<input
|
||||
autoComplete="username"
|
||||
inputMode="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(event) => setEmail(event.target.value)}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Password
|
||||
<input
|
||||
autoComplete="current-password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Two-factor code
|
||||
<input
|
||||
autoComplete="one-time-code"
|
||||
inputMode="numeric"
|
||||
pattern="\d{6}"
|
||||
type="text"
|
||||
value={totpCode}
|
||||
onChange={(event) => setTotpCode(event.target.value)}
|
||||
placeholder="123456"
|
||||
/>
|
||||
</label>
|
||||
|
||||
{error ? <div className="form-error">{error}</div> : null}
|
||||
|
||||
<button type="submit" className="primary-button" disabled={busy}>
|
||||
{busy ? "Signing in..." : "Sign in"}
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user