Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { BrowserRouter, Routes, Route } from "react-router-dom"
import { Error, Landing, Register, ProtectedRoute } from "./pages"
import {
Error,
Landing,
Register,
ProtectedRoute,
EmailVerification,
} from "./pages"
import {
AddJob,
AllJobs,
Expand Down Expand Up @@ -29,6 +35,10 @@ function App() {
</Route>
<Route path="landing" element={<Landing />} />
<Route path="register" element={<Register />} />
<Route
path="/user/email-verification"
element={<EmailVerification />}
/>
<Route path="*" element={<Error />} />
</Routes>
<Toaster position="top-center" />
Expand Down
2 changes: 1 addition & 1 deletion src/components/ProfileForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ProfileForm = () => {
e.preventDefault()
const { image } = user
const { name, lastName, email, location, bio } = userData
if (!name || !lastName || !email || !location || !bio) {
if (!name || !lastName || !email || !location) {
toast.error("Please fill out all fields")
return
}
Expand Down
3 changes: 1 addition & 2 deletions src/components/UserImage.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react'
import { useSelector } from "react-redux"
import defaultUserImage from "../assets/default_user_avatar.jpg"
const UserImage = ({ className }) => {
const { user } = useSelector((store) => store.user)
return (
<img
src={user?.image || defaultUserImage}
src={user.image}
className={`${className} rounded-full object-cover object-top `}
alt={"profile picture"}
/>
Expand Down
36 changes: 31 additions & 5 deletions src/features/user/userSlice.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"
import { toast } from "react-hot-toast"
import customFetch from "../../utils/axios"

import {
addUserToLocalStorage,
Expand All @@ -13,12 +12,14 @@ import {
registerUserThunk,
updateUserThunk,
uploadUserImageThunk,
userAccountVerificationThunk,
} from "./userThunk"
getUserFromLocalStorage

const initialState = {
isLoading: false,
uploadLoading: false,
userRegisterSuccess: false,
user: getUserFromLocalStorage(),
}

Expand All @@ -30,6 +31,12 @@ export const registerUser = createAsyncThunk(
}
)

//** ==================== Email Verification ==================== */
export const userAccountVerification = createAsyncThunk(
"user/userAccountVerification",
userAccountVerificationThunk
)

//** ==================== Login User ==================== */
export const loginUser = createAsyncThunk("user/loginUser", loginUserThunk)

Expand Down Expand Up @@ -64,18 +71,37 @@ const userSlice = createSlice({
state.isLoading = true
})
.addCase(registerUser.fulfilled, (state, action) => {
const { user } = action.payload
state.isLoading = false
state.user = user
addUserToLocalStorage(user)
toast.success(`Hello ${user.name}`)
state.userRegisterSuccess = true
// const { user } = action.payload
// state.user = user
// addUserToLocalStorage(user)
// toast.success(`Hello ${user.name}`)
})
.addCase(registerUser.rejected, (state, action) => {
state.isLoading = false
toast.error(
action.payload || "Something went wrong, Please try again later."
)
})
//** ==================== Email Verification ==================== */
.addCase(userAccountVerification.pending, (state) => {
state.isLoading = true
})
.addCase(userAccountVerification.fulfilled, (state, action) => {
state.isLoading = false
// const { user } = action.payload
// state.user = user
// addUserToLocalStorage(user)
// toast.success(`Hello ${user.name}`)
toast.success(
action.payload || "Your account has been confirmed successfully!"
)
})
.addCase(userAccountVerification.rejected, (state, action) => {
state.isLoading = false
toast.error(action.payload || "Your account has been confirmed")
})
//** ==================== LOGIN USER ==================== */
.addCase(loginUser.pending, (state) => {
state.isLoading = true
Expand Down
15 changes: 15 additions & 0 deletions src/features/user/userThunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ export const registerUserThunk = async (url, user, thunkAPI) => {
}
}

//** ==================== Email Verification ==================== */
export const userAccountVerificationThunk = async (
{ verificationToken, email },
thunkAPI
) => {
try {
const { data } = await customFetch.post("/auth/email-verification", {
verificationToken,
email,
})
} catch (error) {
return thunkAPI.rejectWithValue(error.response.data.msg)
}
}

//** ==================== Login User ==================== */
export const loginUserThunk = async (user, thunkAPI) => {
try {
Expand Down
42 changes: 42 additions & 0 deletions src/pages/EmailVerification.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useEffect } from "react"
import { useDispatch, useSelector } from "react-redux"
import { Link, useLocation } from "react-router-dom"
import { userAccountVerification } from "../features/user/userSlice"

const useQuery = () => {
return new URLSearchParams(useLocation().search)
}

const EmailVerification = () => {
const { isLoading } = useSelector((store) => store.user)
const query = useQuery()
const dispatch = useDispatch()

useEffect(() => {
if (!isLoading) {
dispatch(
userAccountVerification({
verificationToken: query.get("token"),
email: query.get("email"),
})
)
}
}, [])

return (
<>
<section className=" my-10 mb-28 grid place-items-center space-y-10 px-5 md:px-8 ">
<h2> Account Confirmed </h2>
<Link
to="/register"
className=" rounded-md bg-primary px-4 py-2 text-white "
>
{" "}
Please Login{" "}
</Link>
</section>
</>
)
}

export default EmailVerification
16 changes: 13 additions & 3 deletions src/pages/Register.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import UserImage from "../assets/user.jpg"
import Logo from "../assets/Logo.png"
import { RegisterForm } from "../components"
import { useSelector } from "react-redux"

const Register = () => {
const { userRegisterSuccess } = useSelector((store) => store.user)
return (
<>
<section className=" container mx-auto ">
<section className=" container mx-auto ">
<div className="flex ">
{/* Right */}
<aside className=" relative my-16 hidden flex-col justify-between space-y-10 overflow-hidden rounded-2xl bg-primary p-10 shadow-2xl md:w-1/2 lg:flex xl:w-1/3 ">
Expand Down Expand Up @@ -42,7 +44,8 @@ const Register = () => {
<div className="absolute -top-12 -right-10 h-28 w-28 rounded-full bg-secondary-900 opacity-40 "></div>
</aside>
{/* Left */}
<article className=" my-10 flex w-full flex-col items-center justify-between space-y-12 md:my-16 ">
<article className=" justifybetween my-10 flex w-full flex-col items-center space-y-12 md:my-16 ">
{/* <article className=" my-10 flex w-full flex-col items-center justify-between space-y-12 md:my-16 "> */}
<div className=" flex flex-col items-center space-y-4 ">
<img
src={Logo}
Expand All @@ -52,7 +55,14 @@ const Register = () => {
<h4 className="text-4xl font-medium">Hello Again!</h4>
</div>

<RegisterForm />
{!userRegisterSuccess ? (
<RegisterForm />
) : (
<p className=" bg-green-100 py-4 px-6 capitalize text-green-600/70 ">
{" "}
Success! Please Check your email to verify account.{" "}
</p>
)}
</article>
</div>
</section>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import Error from "./Error"
import Landing from "./Landing"
import ProtectedRoute from "./ProtectedRoute"
import Register from "./Register"

export { Error, Landing, ProtectedRoute, Register }
import EmailVerification from "./EmailVerification"
export { Error, Landing, ProtectedRoute, Register, EmailVerification }