diff --git a/src/app/auth/error/page.tsx b/src/app/auth/error/page.tsx
deleted file mode 100644
index 7552b02..0000000
--- a/src/app/auth/error/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function AuthError() {
- return
Authentication Error
;
-}
diff --git a/src/components/auth/action.ts b/src/components/auth/action.ts
new file mode 100644
index 0000000..e4718fa
--- /dev/null
+++ b/src/components/auth/action.ts
@@ -0,0 +1,50 @@
+"use server";
+
+import { revalidatePath } from "next/cache";
+import { createSupabaseClient } from "@/lib/supabase/serverComponentClient";
+import { redirect } from "next/navigation";
+
+export async function login(formData: FormData) {
+ const supabase = await createSupabaseClient();
+
+ const data = {
+ email: formData.get("email") as string,
+ password: formData.get("password") as string,
+ };
+
+ const { error } = await supabase.auth.signInWithPassword(data);
+
+ if (error) {
+ throw error;
+ }
+
+ revalidatePath("/", "layout");
+ redirect("/");
+}
+
+export async function signup(formData: FormData) {
+ const supabase = await createSupabaseClient();
+
+ const data = {
+ email: formData.get("email") as string,
+ password: formData.get("password") as string,
+ };
+
+ const { error } = await supabase.auth.signUp(data);
+
+ if (error) {
+ throw error;
+ }
+
+ revalidatePath("/", "layout");
+ redirect("/");
+}
+
+export async function logout() {
+ const supabase = await createSupabaseClient();
+ const { error } = await supabase.auth.signOut();
+
+ if (error) {
+ throw new Error("Logout failed: " + error.message);
+ }
+}
diff --git a/src/components/auth/loginForm.tsx b/src/components/auth/loginForm.tsx
index c0c7ac1..3cc7c2c 100644
--- a/src/components/auth/loginForm.tsx
+++ b/src/components/auth/loginForm.tsx
@@ -1,40 +1,70 @@
"use client";
-import React from "react";
-import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
-import { useState } from "react";
+import React, { useState } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
-import { useRouter } from "next/navigation";
+import { login } from "./action";
+import { LoginFormSchema } from "@/types/schemas/authentication.schema";
+import toast from "react-hot-toast";
export function LoginForm() {
- const router = useRouter();
- const supabase = createSupabaseClient();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
+ const [errors, setErrors] = useState<{ email?: string; password?: string; server?: string }>({});
- const handleLogin = async (event: React.MouseEvent) => {
+ const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
- await supabase.auth.signInWithPassword({
- email,
- password,
- });
- router.push("/");
+
+ const formData = { email, password };
+
+ const result = LoginFormSchema.safeParse(formData);
+
+ if (!result.success) {
+ const formErrors: { email?: string; password?: string } = {};
+ result.error.errors.forEach((error) => {
+ formErrors[error.path[0] as keyof typeof formErrors] = error.message;
+ });
+ setErrors(formErrors);
+ return;
+ }
+
+ setErrors({});
+
+ const form = new FormData();
+ form.append("email", email);
+ form.append("password", password);
+
+ try {
+ await login(form);
+ toast.success("Login succesfully!");
+ } catch (authError: any) {
+ setErrors((prevErrors) => ({
+ ...prevErrors,
+ server: authError.message || "An error occurred during login.",
+ }));
+ }
};
return (
-
+
);
}
diff --git a/src/components/auth/logoutButton.tsx b/src/components/auth/logoutButton.tsx
index d84b562..502d1b8 100644
--- a/src/components/auth/logoutButton.tsx
+++ b/src/components/auth/logoutButton.tsx
@@ -1,24 +1,30 @@
"use client";
-import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
-import { usePathname } from "next/navigation";
-import { useRouter } from "next/navigation";
+import { logout } from "./action"; // Adjust the import path accordingly
+import { usePathname, useRouter } from "next/navigation";
+import toast from "react-hot-toast";
export function LogoutButton() {
- const supabase = createSupabaseClient();
const pathname = usePathname();
const router = useRouter();
const handleLogout = async () => {
- await supabase.auth.signOut();
-
- if (pathname === "/") {
- window.location.reload();
- } else {
- await router.push("/");
- window.location.reload();
+ try {
+ await logout();
+ if (pathname === "/") {
+ window.location.reload();
+ } else {
+ await router.push("/");
+ window.location.reload();
+ }
+ } catch (error: any) {
+ toast.error(error.message || "An error occurred during logout.");
}
};
- return ;
+ return (
+
+
+
+ );
}
diff --git a/src/components/auth/signupForm.tsx b/src/components/auth/signupForm.tsx
index c4f2885..a589f15 100644
--- a/src/components/auth/signupForm.tsx
+++ b/src/components/auth/signupForm.tsx
@@ -1,50 +1,65 @@
"use client";
-import React from "react";
-import { createSupabaseClient } from "@/lib/supabase/clientComponentClient";
-import { useState } from "react";
+import React, { useState } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { useRouter } from "next/navigation";
import toast from "react-hot-toast";
+import { signup } from "./action";
+import { signupSchema } from "@/types/schemas/authentication.schema";
export function SignupForm() {
const router = useRouter();
- const supabase = createSupabaseClient();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
+ const [error, setError] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
- const handleSignup = async (event: React.MouseEvent) => {
+ const handleSignup = async (event: React.FormEvent) => {
event.preventDefault();
- if (password !== confirmPassword) {
- alert("Passwords do not match!");
+ const parsedData = signupSchema.safeParse({
+ email,
+ password,
+ confirmPassword,
+ });
+
+ if (!parsedData.success) {
+ setError(parsedData.error.errors[0].message);
return;
}
- const { error } = await supabase.auth.signUp({
- email,
- password,
- });
+ const formData = new FormData();
+ formData.append("email", email);
+ formData.append("password", password);
+ formData.append("confirmPassword", confirmPassword);
- if (error) {
- toast.error(error.message);
- } else {
+ try {
+ await signup(formData);
toast.success("Account created successfully!");
router.push("/");
+ } catch (error: any) {
+ setError(error.message);
}
};
return (
-
+
);
}
diff --git a/src/types/schemas/authentication.schema.ts b/src/types/schemas/authentication.schema.ts
new file mode 100644
index 0000000..5733333
--- /dev/null
+++ b/src/types/schemas/authentication.schema.ts
@@ -0,0 +1,17 @@
+import * as z from "zod";
+
+export const LoginFormSchema = z.object({
+ email: z.string().email("Invalid email address"),
+ password: z.string().min(6, "Password must be at least 6 characters"),
+});
+
+export const signupSchema = z
+ .object({
+ email: z.string().email("Invalid email format"),
+ password: z.string().min(6, "Password must be at least 6 characters long"),
+ confirmPassword: z.string().min(6, "Confirm password must be at least 6 characters long"),
+ })
+ .refine((data) => data.password === data.confirmPassword, {
+ message: "Passwords must match",
+ path: ["confirmPassword"],
+ });