import { useState } from "react"; import { useNavigate } from "react-router"; import { t } from "@lingui/core/macro"; import { Trans } from "@lingui/react/macro"; import { API_URL } from "../config/api.ts"; import { deserializeAuthResponse, type LoginRequest, type RawAuthResponse, } from "../model.ts"; import { useAuth } from "../hooks/useAuth.ts"; import { useDocumentTitle } from "../hooks/useDocumentTitle.ts"; import { useHeightTransition } from "../hooks/useHeightTransition.ts"; import { PageShell } from "../components/layout/PageShell.tsx"; import { expectOk, FormError, FormProvider, SubmitButton, TextField, useApiForm, } from "../components/form/index.ts"; interface LoginValues { username: string; password: string; } interface ResetValues { email: string; } export function UserLogin() { useDocumentTitle(t`Log in`); const navigate = useNavigate(); const { login } = useAuth(); const [showReset, setShowReset] = useState(false); const cardRef = useHeightTransition(showReset); const form = useApiForm({ defaultValues: { username: "", password: "" }, }); const onSubmit = form.submit(async ({ username, password }) => { const data = await expectOk( await fetch(`${API_URL}/api/users/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username, password } satisfies LoginRequest), }), ); login(deserializeAuthResponse(data)); navigate("/"); }); return (

Log in

name="username" placeholder={t`Username`} autoFocus rules={{ required: true }} /> name="password" type="password" placeholder={t`Password`} rules={{ required: true }} /> Logging in…}> Log in

{showReset && }

This is a mirage.

); } function ResetRequestPanel() { const [sent, setSent] = useState(false); const form = useApiForm({ defaultValues: { email: "" } }); const onSubmit = form.submit(async ({ email }) => { // The answer is the same whether or not the address is known; only a // server that failed to take the request is worth reporting. await expectOk( await fetch(`${API_URL}/api/users/request-password-reset`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: email.trim() }), }), ); setSent(true); }); if (sent) { return (

If that address is registered you'll receive a reset link shortly.

); } return (
name="email" type="email" placeholder={t`Your email address`} autoFocus rules={{ required: true }} /> Sending…}> Send reset link
); }