This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Input,
|
||||
Link as ChakraLink,
|
||||
Text,
|
||||
ClientOnly,
|
||||
} from "@chakra-ui/react";
|
||||
import signUpImage from "../../../../../public/assets/img/sign-up-image.png";
|
||||
import { Button } from "@/components/ui/buttons/button";
|
||||
import { Field } from "@/components/ui/forms/field";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useForm } from "react-hook-form";
|
||||
import * as yup from "yup";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { InputGroup } from "@/components/ui/forms/input-group";
|
||||
import { BiLock, BiUser } from "react-icons/bi";
|
||||
import { Link } from "@/i18n/navigation";
|
||||
import { MdMail } from "react-icons/md";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { PasswordInput } from "@/components/ui/forms/password-input";
|
||||
import { Skeleton } from "@/components/ui/feedback/skeleton";
|
||||
import { authService } from "@/lib/api/auth/service";
|
||||
import { useState } from "react";
|
||||
import { signIn } from "next-auth/react";
|
||||
import { toaster } from "@/components/ui/feedback/toaster";
|
||||
|
||||
const schema = yup.object({
|
||||
name: yup.string().required(),
|
||||
email: yup.string().email().required(),
|
||||
password: yup.string().min(8).required(),
|
||||
});
|
||||
|
||||
type SignUpForm = yup.InferType<typeof schema>;
|
||||
|
||||
export default function SignUpForm() {
|
||||
const t = useTranslations();
|
||||
const router = useRouter();
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
register,
|
||||
formState: { errors },
|
||||
} = useForm<SignUpForm>({ resolver: yupResolver(schema), mode: "onChange" });
|
||||
|
||||
const onSubmit = async (formData: SignUpForm) => {
|
||||
setIsSubmitting(true);
|
||||
try {
|
||||
await authService.register({
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
firstName: formData.name,
|
||||
lastName: "",
|
||||
});
|
||||
|
||||
const res = await signIn("credentials", {
|
||||
redirect: false,
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
});
|
||||
|
||||
if (res?.error) {
|
||||
throw new Error(res.error);
|
||||
}
|
||||
|
||||
router.replace("/home");
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message) {
|
||||
toaster.error({
|
||||
title: error.message,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
// other errors are handled by api-service interceptor (toast + 422 display)
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
return formData;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box
|
||||
position="absolute"
|
||||
minH={{ base: "70vh", md: "50vh" }}
|
||||
w={{ md: "calc(100vw - 50px)" }}
|
||||
borderRadius={{ md: "15px" }}
|
||||
left="0"
|
||||
right="0"
|
||||
bgRepeat="no-repeat"
|
||||
overflow="hidden"
|
||||
zIndex="-1"
|
||||
top="0"
|
||||
bgImage={`url(${signUpImage.src})`}
|
||||
bgSize="cover"
|
||||
mx={{ md: "auto" }}
|
||||
mt={{ md: "14px" }}
|
||||
/>
|
||||
<Flex
|
||||
w="full"
|
||||
h="full"
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Text
|
||||
fontSize={{ base: "2xl", md: "3xl", lg: "4xl" }}
|
||||
color="white"
|
||||
fontWeight="bold"
|
||||
mt={{ base: "2rem", md: "4.5rem", "2xl": "6.5rem" }}
|
||||
mb={{ base: "2rem", md: "3rem", "2xl": "4rem" }}
|
||||
>
|
||||
{t("auth.create-an-account-now")}
|
||||
</Text>
|
||||
<Flex
|
||||
direction="column"
|
||||
w={{ base: "100%", md: "445px" }}
|
||||
background="transparent"
|
||||
borderRadius="15px"
|
||||
p="10"
|
||||
mx={{ base: "100px" }}
|
||||
bg="bg.panel"
|
||||
boxShadow="0 20px 27px 0 rgb(0 0 0 / 5%)"
|
||||
mb="8"
|
||||
>
|
||||
<Flex
|
||||
as="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
w="100%"
|
||||
>
|
||||
<Field
|
||||
mb="24px"
|
||||
label={t("name")}
|
||||
errorText={errors.name?.message}
|
||||
invalid={!!errors.name}
|
||||
>
|
||||
<InputGroup w="full" startElement={<BiUser size="1rem" />}>
|
||||
<Input
|
||||
borderRadius="15px"
|
||||
fontSize="sm"
|
||||
type="text"
|
||||
placeholder={t("name")}
|
||||
size="lg"
|
||||
{...register("name")}
|
||||
/>
|
||||
</InputGroup>
|
||||
</Field>
|
||||
<Field
|
||||
mb="24px"
|
||||
label={t("email")}
|
||||
errorText={errors.email?.message}
|
||||
invalid={!!errors.email}
|
||||
>
|
||||
<InputGroup w="full" startElement={<MdMail size="1rem" />}>
|
||||
<Input
|
||||
borderRadius="15px"
|
||||
fontSize="sm"
|
||||
type="text"
|
||||
placeholder={t("email")}
|
||||
size="lg"
|
||||
{...register("email")}
|
||||
/>
|
||||
</InputGroup>
|
||||
</Field>
|
||||
<Field
|
||||
mb="24px"
|
||||
label={t("password")}
|
||||
errorText={errors.password?.message}
|
||||
invalid={!!errors.password}
|
||||
>
|
||||
<InputGroup w="full" startElement={<BiLock size="1rem" />}>
|
||||
<PasswordInput
|
||||
borderRadius="15px"
|
||||
fontSize="sm"
|
||||
placeholder={t("password")}
|
||||
size="lg"
|
||||
{...register("password")}
|
||||
/>
|
||||
</InputGroup>
|
||||
</Field>
|
||||
<Field mb="24px">
|
||||
<ClientOnly fallback={<Skeleton height="45px" width="100%" />}>
|
||||
<Button
|
||||
type="submit"
|
||||
bg="primary.400"
|
||||
color="white"
|
||||
fontWeight="bold"
|
||||
w="100%"
|
||||
h="45px"
|
||||
_hover={{
|
||||
bg: "primary.500",
|
||||
}}
|
||||
_active={{
|
||||
bg: "primary.400",
|
||||
}}
|
||||
loading={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? t("auth.registering") : t("auth.sign-up")}
|
||||
</Button>
|
||||
</ClientOnly>
|
||||
</Field>
|
||||
</Flex>
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
maxW="100%"
|
||||
>
|
||||
<Text
|
||||
color={{ base: "gray.400", _dark: "white" }}
|
||||
fontWeight="medium"
|
||||
>
|
||||
{t("auth.already-have-an-account")}
|
||||
<ChakraLink
|
||||
as={Link}
|
||||
color={{ base: "primary.400", _dark: "primary.200" }}
|
||||
ml="2"
|
||||
href="/signin"
|
||||
fontWeight="bold"
|
||||
focusRing="none"
|
||||
>
|
||||
{t("auth.sign-in")}
|
||||
</ChakraLink>
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user