Files
full-stack-fastapi/frontend/src/routes/recover-password.tsx
2025-09-09 14:45:10 +02:00

95 lines
2.5 KiB
TypeScript

import { Container, Heading, Input, Text } from "@chakra-ui/react"
import { useMutation } from "@tanstack/react-query"
import { createFileRoute, redirect } from "@tanstack/react-router"
import { type SubmitHandler, useForm } from "react-hook-form"
import { FiMail } from "react-icons/fi"
import { type ApiError, LoginService } from "@/client"
import { Button } from "@/components/ui/button"
import { Field } from "@/components/ui/field"
import { InputGroup } from "@/components/ui/input-group"
import { isLoggedIn } from "@/hooks/useAuth"
import useCustomToast from "@/hooks/useCustomToast"
import { emailPattern, handleError } from "@/utils"
interface FormData {
email: string
}
export const Route = createFileRoute("/recover-password")({
component: RecoverPassword,
beforeLoad: async () => {
if (isLoggedIn()) {
throw redirect({
to: "/",
})
}
},
})
function RecoverPassword() {
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm<FormData>()
const { showSuccessToast } = useCustomToast()
const recoverPassword = async (data: FormData) => {
await LoginService.recoverPassword({
email: data.email,
})
}
const mutation = useMutation({
mutationFn: recoverPassword,
onSuccess: () => {
showSuccessToast("Password recovery email sent successfully.")
reset()
},
onError: (err: ApiError) => {
handleError(err)
},
})
const onSubmit: SubmitHandler<FormData> = async (data) => {
mutation.mutate(data)
}
return (
<Container
as="form"
onSubmit={handleSubmit(onSubmit)}
h="100vh"
maxW="sm"
alignItems="stretch"
justifyContent="center"
gap={4}
centerContent
>
<Heading size="xl" color="ui.main" textAlign="center" mb={2}>
Password Recovery
</Heading>
<Text textAlign="center">
A password recovery email will be sent to the registered account.
</Text>
<Field invalid={!!errors.email} errorText={errors.email?.message}>
<InputGroup w="100%" startElement={<FiMail />}>
<Input
{...register("email", {
required: "Email is required",
pattern: emailPattern,
})}
placeholder="Email"
type="email"
/>
</InputGroup>
</Field>
<Button variant="solid" type="submit" loading={isSubmitting}>
Continue
</Button>
</Container>
)
}