69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { useId, useState } from "react";
|
|
import type { ApiSettings, LoginResponse } from "../../types";
|
|
import { login } from "../../api/auth";
|
|
import Button from "../../components/Button";
|
|
import Dialog from "../../components/Dialog";
|
|
import FormField from "../../components/FormField";
|
|
import PasswordField from "../../components/PasswordField";
|
|
import DismissibleAlert from "../../components/DismissibleAlert";
|
|
|
|
export default function LoginModal({
|
|
settings,
|
|
onClose,
|
|
onLogin,
|
|
title = "Sign in",
|
|
message
|
|
}: {
|
|
settings: ApiSettings;
|
|
onClose: () => void;
|
|
onLogin: (response: LoginResponse) => void;
|
|
title?: string;
|
|
message?: string;
|
|
}) {
|
|
const [email, setEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [error, setError] = useState("");
|
|
const [busy, setBusy] = useState(false);
|
|
const formId = useId();
|
|
|
|
async function submit(event: React.FormEvent) {
|
|
event.preventDefault();
|
|
setError("");
|
|
setBusy(true);
|
|
try {
|
|
const response = await login(settings, { email, password });
|
|
onLogin(response);
|
|
onClose();
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : String(err));
|
|
} finally {
|
|
setBusy(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog
|
|
open
|
|
title={title}
|
|
onClose={onClose}
|
|
footer={(
|
|
<>
|
|
<Button type="button" onClick={onClose}>Cancel</Button>
|
|
<Button type="submit" form={formId} variant="primary" disabled={busy}>{busy ? "Signing in…" : "Sign in"}</Button>
|
|
</>
|
|
)}
|
|
>
|
|
<form id={formId} className="form-grid" onSubmit={submit}>
|
|
{message && <DismissibleAlert tone="info" dismissible={false}>{message}</DismissibleAlert>}
|
|
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
|
|
<FormField label="Email">
|
|
<input type="email" value={email} autoComplete="username" onChange={(e) => setEmail(e.target.value)} />
|
|
</FormField>
|
|
<FormField label="Password">
|
|
<PasswordField value={password} autoComplete="current-password" onValueChange={setPassword} />
|
|
</FormField>
|
|
</form>
|
|
</Dialog>
|
|
);
|
|
}
|