diff --git a/components/auth/sign-in-form.tsx b/components/auth/sign-in-form.tsx index f95a76e..9552e7e 100644 --- a/components/auth/sign-in-form.tsx +++ b/components/auth/sign-in-form.tsx @@ -8,8 +8,10 @@ import { PasswordInput } from "../ui/passwor-input"; import { Button } from "../ui/button"; import { Separator } from "../ui/separator"; import { signInSchema } from "@/utils/authValidationSchema"; +import { useAuth } from "@/hooks/auth/useAuth"; export default function SignInForm() { + const { login } = useAuth(); const formik = useFormik({ initialValues: { email: "", @@ -18,8 +20,13 @@ export default function SignInForm() { }, validationSchema: signInSchema, onSubmit: async (values) => { + const formData = { + identifier: values.email, + password: values.password, + }; try { // Here you would typically call an API endpoint + await login(formData) console.log("Form submitted:", values); // Simulate successful signin // router.push("/dashboard"); diff --git a/components/auth/sign-up-form.tsx b/components/auth/sign-up-form.tsx index 39f4f47..360618c 100644 --- a/components/auth/sign-up-form.tsx +++ b/components/auth/sign-up-form.tsx @@ -7,8 +7,14 @@ import { FormInput } from "../ui/form-input"; import { PasswordInput } from "../ui/passwor-input"; import { Button } from "../ui/button"; import { signUpSchema } from "@/utils/authValidationSchema"; +// import { useState } from "react"; +// import { useAuth } from "@/hooks/auth/useAuth"; export default function SignUpForm() { + // const { signup } = useAuth(); + + // const [error, setError] = useState(null); + // const [isLoading, setIsLoading] = useState(false); const formik = useFormik({ initialValues: { fullName: "", @@ -19,10 +25,22 @@ export default function SignUpForm() { }, validationSchema: signUpSchema, onSubmit: async (values) => { + console.log(values); + // const formData = { + // email: values.email, + // password: values.password, + // } + // setError(null); + // setIsLoading(true); + try { - console.log("Form submitted:", values); - } catch (error) { - console.error("Signup error:", error); + // await signup(formData); + alert("User created successfully!"); + } catch (err) { + console.log("Signup error:", err); + // setError(err.message || "An error occurred during signup."); + } finally { + // setIsLoading(false); } }, }); diff --git a/hooks/auth/useAuth.ts b/hooks/auth/useAuth.ts new file mode 100644 index 0000000..46ce627 --- /dev/null +++ b/hooks/auth/useAuth.ts @@ -0,0 +1,158 @@ +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { userService } from "@/services/api"; +import { useState, useEffect } from "react"; + +// Define types for auth state +export interface AuthTokens { + accessToken: string; + refreshToken: string; +} + +export interface AuthUser { + id: string; + username: string; + address: string; + email: string | null; + picture: string | null; + isVerified: boolean; + roles: string; + createdAt: string; + updatedAt: string; +} + +export interface AuthState { + isAuthenticated: boolean; + user: AuthUser | null; + tokens: AuthTokens | null; +} + +// API response types +interface LoginResponse { + message: string; + user?: AuthUser; + tokens: AuthTokens; +} + +// Local storage keys +const AUTH_TOKENS_KEY = "auth_tokens"; +const AUTH_USER_KEY = "auth_user"; + +// Helper functions for localStorage +const getStoredTokens = (): AuthTokens | null => { + if (typeof window === "undefined") return null; + const tokensStr = localStorage.getItem(AUTH_TOKENS_KEY); + return tokensStr ? JSON.parse(tokensStr) : null; +}; + +const getStoredUser = (): AuthUser | null => { + if (typeof window === "undefined") return null; + const userStr = localStorage.getItem(AUTH_USER_KEY); + return userStr ? JSON.parse(userStr) : null; +}; + +// Set stored values +const setStoredAuth = (tokens: AuthTokens | null, user: AuthUser | null) => { + if (typeof window === "undefined") return; + + if (tokens) { + localStorage.setItem(AUTH_TOKENS_KEY, JSON.stringify(tokens)); + } else { + localStorage.removeItem(AUTH_TOKENS_KEY); + } + + if (user) { + localStorage.setItem(AUTH_USER_KEY, JSON.stringify(user)); + } else { + localStorage.removeItem(AUTH_USER_KEY); + } +}; + +export function useAuth() { + const queryClient = useQueryClient(); + const [isInitialized, setIsInitialized] = useState(false); + + // Initialize auth state from localStorage + useEffect(() => { + const tokens = getStoredTokens(); + const user = getStoredUser(); + + if (tokens) { + queryClient.setQueryData(["auth"], { + isAuthenticated: true, + tokens, + user, + }); + } + + setIsInitialized(true); + }, [queryClient]); + + const authState = queryClient.getQueryData(["auth"]) || { + isAuthenticated: false, + tokens: null, + user: null, + }; + + // Create User mutation + const createUserMutation = useMutation({ + mutationFn: userService.createUser, + onSuccess: (data) => { + console.log("User created successfully:", data); + const newAuthState = { + isAuthenticated: true, + tokens: data.tokens, + user: data.user || getStoredUser(), + }; + + // Update query cache + queryClient.setQueryData(["auth"], newAuthState); + + // Store in localStorage + setStoredAuth(data.tokens, data.user || getStoredUser()); + }, + }); + + // Login mutation + const loginMutation = useMutation({ + mutationFn: userService.createUser, + onSuccess: (data) => { + console.log("Login successful:", data); + const newAuthState = { + isAuthenticated: true, + tokens: data.tokens, + user: data.user || getStoredUser(), + }; + + // Update query cache + queryClient.setQueryData(["auth"], newAuthState); + + // Store in localStorage + setStoredAuth(data.tokens, data.user || getStoredUser()); + }, + }); + + // Logout function + const logout = () => { + queryClient.setQueryData(["auth"], { + isAuthenticated: false, + tokens: null, + user: null, + }); + + setStoredAuth(null, null); + + // Invalidate queries that depend on auth + queryClient.invalidateQueries({ queryKey: ["auth"] }); + }; + + return { + isAuthenticated: authState.isAuthenticated, + user: authState.user, + tokens: authState.tokens, + login: loginMutation.mutateAsync, + signup: createUserMutation.mutateAsync, + logout, + isLoading: loginMutation.isPending, + error: loginMutation.error, + }; +} diff --git a/services/api/config.ts b/services/api/config.ts index 9d1e07d..6f49895 100644 --- a/services/api/config.ts +++ b/services/api/config.ts @@ -18,7 +18,11 @@ export const API_CONFIG = { export const API_ENDPOINTS = { // Auth endpoints AUTH: { - CREATE: "/auth/login", + CREATE: "/auth/initiate-signup", + VERIFY: "/auth/verify-signup", + LOGIN: "/auth/login", + LOGOUT: "/auth/logout", + REFRESH: "/auth/refresh", }, diff --git a/services/api/userService.ts b/services/api/userService.ts index 56d5a65..6287e36 100644 --- a/services/api/userService.ts +++ b/services/api/userService.ts @@ -3,9 +3,19 @@ import axiosClient from "./axiosClient"; // import { apiClient } from "./client"; interface CreateUserParams { - address: string; - username: string; - picture?: string; + email: string; + phone: string; + password: string; +} + +interface VerifySignupParams { + email: string; + otp: string; +} + +interface LoginParams { + identifier: string; + password: string; } interface User { @@ -34,6 +44,34 @@ const createUser = async (params: CreateUserParams): Promise => { return response.data; }; +const verifySignup = async ( + params: VerifySignupParams +): Promise => { + const response = await axiosClient.post(API_ENDPOINTS.AUTH.VERIFY, params); + return response.data; +}; + +const login = async (params: LoginParams): Promise => { + const response = await axiosClient.post(API_ENDPOINTS.AUTH.LOGIN, params); + return response.data; +}; + +const logout = async (): Promise<{ message: string }> => { + const response = await axiosClient.post(API_ENDPOINTS.AUTH.LOGOUT); + return response.data; +}; + +const refreshToken = async (token: string): Promise => { + const response = await axiosClient.post(API_ENDPOINTS.AUTH.REFRESH, { + token, + }); + return response.data; +}; + export const userService = { createUser, -}; + verifySignup, + login, + logout, + refreshToken, +}; \ No newline at end of file