| 3 | 3 | | import type { Route } from "./+types/forgot"; |
| 4 | 4 | | import { page } from "../lib/meta"; |
| 5 | 5 | | import { AuthCard } from "../components/auth-card"; |
| 6 | | − | import { Field, Input, SubmitButton } from "../components/ui"; |
| 6 | + | import { ErrorText, Field, Input, SubmitButton } from "../components/ui"; |
| 7 | 7 | | import { identity } from "../lib/services.server"; |
| 8 | 8 | | import { assertSameOrigin, clientOf } from "../lib/session.server"; |
| 9 | 9 | | |
| ⋯ |
| 14 | 14 | | export async function action({ request }: Route.ActionArgs) { |
| 15 | 15 | | assertSameOrigin(request); |
| 16 | 16 | | const form = await request.formData(); |
| 17 | | − | await identity.requestPasswordReset(String(form.get("email") ?? ""), clientOf(request)); |
| 18 | | − | return { sent: true }; |
| 17 | + | try { |
| 18 | + | await identity.requestPasswordReset(String(form.get("email") ?? ""), clientOf(request)); |
| 19 | + | } catch (error) { |
| 20 | + | // Logged, never shown: what went wrong could say whether the address |
| 21 | + | // has an account. The person hears only that it did not go. |
| 22 | + | console.warn("forgot:", error); |
| 23 | + | return { sent: false, error: "We could not send a reset link just now. Try again in a few minutes." }; |
| 24 | + | } |
| 25 | + | return { sent: true, error: null }; |
| 19 | 26 | | } |
| 20 | 27 | | |
| 21 | 28 | | export default function Forgot({ actionData }: Route.ComponentProps) { |
| ⋯ |
| 39 | 46 | | <Field label="Email"> |
| 40 | 47 | | <Input name="email" type="email" autoComplete="email" required autoFocus /> |
| 41 | 48 | | </Field> |
| 49 | + | <ErrorText>{actionData?.error}</ErrorText> |
| 42 | 50 | | <div className="pt-2 *:w-full"> |
| 43 | 51 | | <SubmitButton pending="Sending…">Send reset link</SubmitButton> |
| 44 | 52 | | </div> |