Authentication Documentation
Filename src\app\contexts\AuthContext.tsx
This file handles all user authentification SignUp,SignIn,SignOut and PasswordReset
1. Global file imports
"use client"
import {useEffect,useState, useContext , createContext, ReactNode } from "react";
import {
onAuthStateChanged,
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
sendEmailVerification,
signOut,
sendPasswordResetEmail
} from "firebase/auth";
import { doc, setDoc, getDoc } from "firebase/firestore";
import { auth } from "../firebase";
import { toast} from "sonner";
import { useRouter } from "next/navigation";
import { db } from "../firebase";
useEffect,useState: are react hooks for state management
useContext,createContext: are react hooks to publish and create context API’s
ReactNode:a typescipt type that represends anything react can render
createUserWithEmailAndPassword:a firebase function that create a new user given and email and password
signInWithEmailAndPassword:a firebase function that authenticates a user given email and password exist
signOut:a firebase function that Logs the current user out of the application.
sendPasswordResetEmai:a firebase function that send an email link to reset password when email provided exists
sendEmailVerification:a firebase function that send verification email when user first signs up
onAuthStateChanged:a firebase function that listens for user state change
doc: a function that create a reference to the named document
setDoc: a function that add information to the named document and overwrites preexisting data
getDoc: a function that retrieves contents of the named document
auth: auth instance from firebase
Toast: function from the Sonner library, a React-based toast notification library.
useReducer:a react hook that enables programmatic navigation between paged
db: database instance from the firebase
2. Interface Declaration
interface AuthContextProps {
//updated
user:any
userInfo: UserInfo
signUp : (profile:any)=>Promise<void>,
signIn : (profile:any)=>Promise<void>,
signOutUser : ()=>Promise<void>,
passwordReset :(email:string)=>Promise<void>,
isloading:boolean
}AuthContextProps:Defines a blueprint of the shape the object should take
2b. Interface Declaration
interface AuthProviderProps{
children:ReactNode
}AuthProviderProps:Reprents every react element
2c. Interface Declaration
interface UserInfo {
fullname: string;
email: string;
}UserInfo:Defines blueprint of the user object
3. Context Creation
const AuthContext = createContext<AuthContextProps|undefined>(undefined)
AuthContet:It an instance of the context , that is export to other files
4. SignUp function
const signUp = async(profile:any)=>{
try{
setIsloading(true)
console.log(profile)
const userCredential = await createUserWithEmailAndPassword(auth , profile.email , profile.passWord)
const user = userCredential.user
await sendEmailVerification(user)
setIsloading(false)
toast.success("Sign up successful! Verification email sent..")
createUserDB(profile.firstName , profile.lastName , profile.email)
}catch(error:any){
setIsloading(false)
toast.error("Signup Error")
console.log(error.message)
}
}signUp
-
Takes in profile argument that has (
firstName,lastName,email,password) -
Creates a user in the firebase Auth by passing
emailandpasswordto thecreateUserWithEmailandPasswordfunction -
Sends verification to
emailvia thesendEmailVerification -
Adds user to that has (
firstName,lastName,email) in user database -
Then
toastsuccess message
5. SignIn function
const signIn = async (profile: any) => {
try {
console.log(profile);
setIsloading(true);
const userCredential = await signInWithEmailAndPassword(auth, profile.email, profile.passWord);
const user = userCredential.user;
if (user.emailVerified) {
// Handle successful sign-in without navigation
toast.success("Sign-in successful");
} else {
toast.warning("Verify your email please");
}
setIsloading(false);
} catch (error: any) {
setIsloading(false);
toast.error("Admin does not exist");
}
};-
Takes in profile argument that has (
email,password) -
Checks if email is verified via
user.emailVerified -
Checks if user exist and return userToken via
signInUserWithEmailAndPassword
6. SignOut function
const signOutUser = async()=>{
try{
await signOut(auth)
setUser(null); // Reset user state
toast.success("Signed out successfully!");
}catch(error:any){
toast.error(error.message)
}
}-
Takes in the available
authas argument -
Removes the auth via
signOut
7. Password Reset Function
const passwordReset = async(email:string)=>{
try{
setIsloading(true)
await sendPasswordResetEmail(auth , email)
setIsloading(false)
toast.success("Password reset email sent! Check your inbox.")
}catch(error:any){
setIsloading(false)
toast.error(error.message)
}
}-
Takes in
auth and email -
Sends reset email if if
emailexists inauth
8. UserDB Creation
const createUserDB =async(firstname:string , lastname:string , documentname:string)=>{
await setDoc(doc(db , "users" , documentname),{
fullname :`${firstname} ${lastname}`,
email :`${documentname}`
})
setUserInfo({
fullname :`${firstname} ${lastname}`,
email :`${documentname}`
})
}-
Takes in (
firstName,lastNameanddocumentName) as argurments -
Create a new user in the document with
documentName
9. fetchUser Function
const fetchUser = async(documentname:string)=>{
try{
const docsnap = await getDoc(doc(db,"users" , documentname))
if(docsnap.exists()){
setUserInfo(docsnap.data())
}else{
toast.error("user not fould!")
}
}catch(error){
toast.error("falied to fetch user from userDB")
}
}- Fetches
userfromdocumentname
10.React Hook
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
if (user) {
fetchUser(user.email || "");
} else {
setUserInfo(null);
}
});
return () => unsubscribe();
}, []);
- listens for
authchange
11. Context export
export const useAuth = ()=>{
const context = useContext(AuthContext)
if(!context){
throw new Error("Error with useAuth")
}
return context
}- Exports the
AuthContext
12. Main Function
export const AuthProvider = ({children}:AuthProviderProps)=>{
const router = useRouter()
const [user, setUser] = useState<any>(null);
const [userInfo , setUserInfo] =useState<any>(null)
const [isloading , setIsloading] = useState<boolean>(false)
const values ={
signUp,
signIn,
signOutUser,
passwordReset,
user,
userInfo,
isloading
}
return(
<AuthContext.Provider value={values} >
{children}
</AuthContext.Provider>
)
}values : Exports instances of the authContext
[user, setUser] :Stores user state in the authContext.tsx
[userInfo , setUserInfo] :Stores userInfo state in the authContext.tsx
[isloading , setIsloading] :Stores isloading state in the authContext.tsx