diff --git a/actions/auth/auth.ts b/actions/auth/auth.ts
index 28504d2c0c..394bdf4f3e 100644
--- a/actions/auth/auth.ts
+++ b/actions/auth/auth.ts
@@ -7,7 +7,7 @@ import { signIn, signOut } from "@/auth.config";
import { authFormSchema } from "@/types";
const formSchemaSignIn = authFormSchema("sign-in");
-// const formSchemaSignUp = authFormSchema("sign-up");
+const formSchemaSignUp = authFormSchema("sign-up");
const defaultValues: z.infer = {
email: "",
@@ -50,6 +50,46 @@ export async function authenticate(
}
}
+export const createNewUser = async (
+ formData: z.infer,
+) => {
+ const keyServer = process.env.API_BASE_URL;
+ const url = new URL(`${keyServer}/users`);
+
+ const bodyData = {
+ data: {
+ type: "User",
+ attributes: {
+ name: formData.name,
+ company_name: formData.company,
+ email: formData.email,
+ password: formData.password,
+ },
+ },
+ };
+
+ try {
+ const response = await fetch(url.toString(), {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/vnd.api+json",
+ Accept: "application/vnd.api+json",
+ },
+ body: JSON.stringify(bodyData),
+ });
+
+ const parsedResponse = await response.json();
+
+ if (!response.ok) {
+ return parsedResponse;
+ }
+
+ return parsedResponse;
+ } catch (error) {
+ return { errors: [{ detail: "Network error or server is unreachable" }] };
+ }
+};
+
export const getToken = async (formData: z.infer) => {
const keyServer = process.env.API_BASE_URL;
const url = new URL(`${keyServer}/tokens`);
diff --git a/auth.config.ts b/auth.config.ts
index ffcfaad06d..556c7d40c0 100644
--- a/auth.config.ts
+++ b/auth.config.ts
@@ -74,7 +74,7 @@ export const authConfig = {
const parsedCredentials = z
.object({
email: z.string().email(),
- password: z.string().min(6),
+ password: z.string().min(12),
})
.safeParse(credentials);
diff --git a/components/auth/auth-form.tsx b/components/auth/auth-form.tsx
index de53e66f8b..1a9dbd9777 100644
--- a/components/auth/auth-form.tsx
+++ b/components/auth/auth-form.tsx
@@ -9,18 +9,19 @@ import { useFormState } from "react-dom";
import { useForm } from "react-hook-form";
import { z } from "zod";
-import { authenticate } from "@/actions/auth";
+import { authenticate, createNewUser } from "@/actions/auth";
import {
Form,
FormControl,
FormField,
FormMessage,
} from "@/components/ui/form";
-import { authFormSchema } from "@/types";
+import { ApiError, authFormSchema } from "@/types";
import { NotificationIcon, ProwlerExtended } from "../icons";
import { ThemeSwitch } from "../ThemeSwitch";
import { CustomButton, CustomInput } from "../ui/custom";
+import { useToast } from "../ui/toast";
export const AuthForm = ({ type }: { type: string }) => {
const formSchema = authFormSchema(type);
@@ -31,17 +32,20 @@ export const AuthForm = ({ type }: { type: string }) => {
email: "",
password: "",
...(type === "sign-up" && {
- firstName: "",
- companyName: "",
+ name: "",
+ company: "",
+ termsAndConditions: false,
confirmPassword: "",
}),
},
});
- const isLoading = form.formState.isSubmitting;
-
const [state, dispatch] = useFormState(authenticate, undefined);
+ const { toast } = useToast();
+
+ const isLoading = form.formState.isSubmitting;
+
useEffect(() => {
if (state?.message === "Success") {
router.push("/");
@@ -49,20 +53,53 @@ export const AuthForm = ({ type }: { type: string }) => {
}, [state]);
const onSubmit = async (data: z.infer) => {
- try {
- // Sign-up logic will be here.
- if (type === "sign-in") {
- dispatch({
- email: data.email.toLowerCase(),
- password: data.password,
+ if (type === "sign-in") {
+ dispatch({
+ email: data.email.toLowerCase(),
+ password: data.password,
+ });
+ }
+ if (type === "sign-up") {
+ const newUser = await createNewUser(data);
+
+ if (newUser?.errors && newUser.errors.length > 0) {
+ newUser.errors.forEach((error: ApiError) => {
+ const errorMessage = error.detail;
+
+ switch (error.source.pointer) {
+ case "/data/attributes/name":
+ form.setError("name", { type: "server", message: errorMessage });
+ break;
+ case "/data/attributes/email":
+ form.setError("email", { type: "server", message: errorMessage });
+ break;
+ case "/data/attributes/password":
+ form.setError("password", {
+ type: "server",
+ message: errorMessage,
+ });
+ break;
+ default:
+ toast({
+ variant: "destructive",
+ title: "Oops! Something went wrong",
+ description: errorMessage,
+ });
+ }
+ });
+ } else {
+ toast({
+ title: "Success!",
+ description: "The user was registered successfully.",
+ });
+ form.reset({
+ name: "",
+ company: "",
+ email: "",
+ password: "",
+ termsAndConditions: false,
});
}
- if (type === "sign-up") {
- // const newUser = await signUp(data);
- }
- } catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
}
};
@@ -107,18 +144,20 @@ export const AuthForm = ({ type }: { type: string }) => {
<>
>
)}
@@ -128,9 +167,15 @@ export const AuthForm = ({ type }: { type: string }) => {
type="email"
label="Email"
placeholder="Enter your email"
+ isInvalid={!!form.formState.errors.email}
/>
-
+
{type === "sign-in" && (
@@ -143,40 +188,40 @@ export const AuthForm = ({ type }: { type: string }) => {
)}
{type === "sign-up" && (
- (
- <>
-
-
-
- field.onChange(e.target.checked ? "true" : "false")
- }
- >
- I agree with the
-
- Terms
-
- and
-
- Privacy Policy
-
-
-
-
- >
- )}
- />
+ <>
+
+ (
+ <>
+
+ field.onChange(e.target.checked)}
+ >
+ I agree with the
+
+ Terms
+
+ and
+
+ Privacy Policy
+
+
+
+
+ >
+ )}
+ />
+ >
)}
{state?.message === "Credentials error" && (
@@ -186,8 +231,6 @@ export const AuthForm = ({ type }: { type: string }) => {
)}
- {isLoading && Loading...
}
-
{
@@ -74,8 +74,8 @@ export const SidebarWrap = () => {
Loading...
}>
diff --git a/types/authFormSchema.ts b/types/authFormSchema.ts
index 7705b2e19f..6f3ab5a087 100644
--- a/types/authFormSchema.ts
+++ b/types/authFormSchema.ts
@@ -4,11 +4,9 @@ export const authFormSchema = (type: string) =>
z
.object({
// Sign Up
- companyName:
- type === "sign-in"
- ? z.string().optional()
- : z.string().min(3).optional(),
- firstName:
+ company:
+ type === "sign-in" ? z.string().optional() : z.string().optional(),
+ name:
type === "sign-in"
? z.string().optional()
: z
@@ -20,20 +18,19 @@ export const authFormSchema = (type: string) =>
confirmPassword:
type === "sign-in"
? z.string().optional()
- : z.string().min(3, {
+ : z.string().min(12, {
message: "It must contain at least 12 characters.",
}),
termsAndConditions:
type === "sign-in"
- ? z.enum(["true"]).optional()
- : z.enum(["true"], {
- errorMap: () => ({
- message: "You must accept the terms and conditions.",
- }),
+ ? z.boolean().optional()
+ : z.boolean().refine((value) => value === true, {
+ message: "You must accept the terms and conditions.",
}),
+
// Fields for Sign In and Sign Up
email: z.string().email(),
- password: z.string().min(3, {
+ password: z.string().min(12, {
message: "It must contain at least 12 characters.",
}),
})
diff --git a/types/components.ts b/types/components.ts
index 6bac7ce1d2..02018469dc 100644
--- a/types/components.ts
+++ b/types/components.ts
@@ -30,6 +30,15 @@ export interface SearchParamsProps {
[key: string]: string | string[] | undefined;
}
+export interface ApiError {
+ detail: string;
+ status: string;
+ source: {
+ pointer: string;
+ };
+ code: string;
+}
+
export interface ProviderProps {
id: string;
type: "providers";