Skip to content

Commit

Permalink
Completed Authetication logic on frontend with email verification
Browse files Browse the repository at this point in the history
  • Loading branch information
aslezar committed Mar 11, 2024
1 parent 7b216ee commit e2c020f
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 124 deletions.
8 changes: 6 additions & 2 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import {
ScrollRestoration,
createBrowserRouter,
} from "react-router-dom"
import toast from "react-hot-toast"

//Components
import Navbar from "./components/Navbar"
import Footer from "./components/Footer"
// import Footer from "./components/Footer"

//Pages
import HomePage from "./Pages/HomePage"
import SignIn from "./Pages/SignInPage"
import SignUp from "./Pages/SignUpPage"
import VerifyOTP from "./Pages/VerifyOTP"
import ForgotPassword from "./Pages/ForgotPasswordPage"
import DashBoard from "./Pages/DashBoardPage"
import Profile from "./Pages/ProfilePage"
Expand Down Expand Up @@ -62,6 +62,10 @@ const router = createBrowserRouter([
path: "signup",
element: <SignUp />,
},
{
path: "verify",
element: <VerifyOTP />,
},
{
path: "forgotpassword",
element: <ForgotPassword />,
Expand Down
30 changes: 18 additions & 12 deletions client/src/Pages/BlogPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect } from "react"
import { useParams } from "react-router-dom"
import { handler, getBlog } from "../api/index.ts"
import { getBlog } from "../api/index.ts"
import Loader from "../components/Loader"
import toast from "react-hot-toast"

Expand All @@ -10,22 +10,28 @@ const BlogPage = () => {
const [isError, setError] = React.useState<boolean>(false)
const [isLoading, setLoading] = React.useState<boolean>(true)
const [blog, setBlog] = React.useState<BlogFullType | null>(null)
const { id } = useParams<{ id: string }>()
const { id } = useParams<{ id: BlogFullType["_id"] }>()

useEffect(() => {
handler(
getBlog,
id,
(data: BlogFullType) => {
setBlog(data)
const fetchBlog = async () => {
try {
if (!id) {
setError(true)
return toast.error("Blog not found")
}

setLoading(true)
const response = await getBlog(id)
// console.log(response.data)
setBlog(response.data)
setLoading(false)
},
(msg: string) => {
} catch (error) {
setError(true)
setLoading(false)
toast.error(msg)
},
)
}
}

fetchBlog()
}, [])

if (isLoading === true) return <Loader />
Expand Down
18 changes: 9 additions & 9 deletions client/src/Pages/SignInPage.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import * as React from "react"
import img from "../assets/img/Auth/signup.webp"
// import img from "../assets/img/Auth/auth.mp4";
// import img from "../assets/img/Auth/auth.gif";
import { useAppDispatch, useAppSelector } from "../hooks"
import { login } from "../features/userSlice"
import { Link, useNavigate } from "react-router-dom"
import { LoginType } from "../definitions"

export default function SignIn() {
const dispatch = useAppDispatch()
const navigate = useNavigate()
const { isAuthenticated, loading } = useAppSelector((state) => state.user)
const [values, setValues] = React.useState({
const [loginValues, setLoginValues] = React.useState<LoginType>({
email: "",
password: "",
})

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target
setValues((prevValues) => ({
setLoginValues((prevValues) => ({
...prevValues,
[name]: value,
}))
}

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
dispatch(login(values.email, values.password))
dispatch(login(loginValues))
}
React.useEffect(() => {
if (!loading && isAuthenticated) {
navigate("/")
}
}, [])
}, [loading, isAuthenticated])
return (
<div className="flex h-screen">
<div className="hidden lg:flex items-center justify-center flex-1 bg-white text-black">
Expand Down Expand Up @@ -62,7 +61,7 @@ export default function SignIn() {
type="text"
id="email"
name="email"
value={values.email}
value={loginValues.email}
onChange={handleChange}
placeholder="johndoe@example.com"
className="mt-1 p-2.5 px-4 w-full border rounded-3xl focus:border-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 transition-colors duration-300"
Expand All @@ -79,7 +78,7 @@ export default function SignIn() {
type="password"
id="password"
name="password"
value={values.password}
value={loginValues.password}
onChange={handleChange}
placeholder="*********"
className="mt-1 p-2.5 px-4 w-full border rounded-3xl focus:border-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 transition-colors duration-300"
Expand Down Expand Up @@ -124,9 +123,10 @@ export default function SignIn() {
<div className="mt-4 text-sm text-gray-600 text-center">
<Link to="/signup" className="hover:underline cursor-pointer">
Don't have an account?
<span className="text-black hover:underline">Login here</span>
<span className="text-black hover:underline"> Signup here</span>
</Link>
</div>
{/* {loading && <Loader />} */}
</div>
</div>
</div>
Expand Down
60 changes: 30 additions & 30 deletions client/src/Pages/SignUpPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import * as React from "react"
import { Link, useNavigate } from "react-router-dom"
import { useAppDispatch, useAppSelector } from "../hooks"
import { register } from "../features/userSlice"
import img from "../assets/img/Auth/signup.webp"
// import img from "../assets/img/Auth/auth.mp4";
// import img from "../assets/img/Auth/auth.gif";
import { SignUpType } from "../definitions"
import { signUp } from "../api/index.ts"
import toast from "react-hot-toast"
import { register } from "../features/userSlice"
import Loader from "../components/Loader"

export default function SignUp() {
const dispatch = useAppDispatch()
const navigate = useNavigate()
const { isAuthenticated, loading } = useAppSelector((state) => state.user)
console.log(isAuthenticated, loading)
const [values, setValues] = React.useState({
const { isAuthenticated, loading, verificationRequired } = useAppSelector(
(state) => state.user,
)
console.log(isAuthenticated, loading, verificationRequired)
const [signupValues, setSignupValues] = React.useState<SignUpType>({
firstName: "",
lastName: "",
email: "",
Expand All @@ -20,28 +24,33 @@ export default function SignUp() {

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target
setValues((prevValues) => ({
setSignupValues((prevValues) => ({
...prevValues,
[name]: value,
}))
}

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
dispatch(
register(
values.firstName + values.lastName,
values.email,
values.password,
),
if (
!signupValues.firstName ||
!signupValues.email ||
!signupValues.password
)
return alert("All fields are required")
dispatch(register(signupValues))
}

React.useEffect(() => {
if (!loading && isAuthenticated) {
navigate("/")
if (!loading) {
if (verificationRequired) {
navigate("/verify")
} else if (isAuthenticated) {
navigate("/")
}
}
}, [])
}, [loading, verificationRequired, isAuthenticated])

return (
<div className="flex h-screen">
<div className="hidden lg:flex items-center justify-center flex-1 bg-white text-black">
Expand All @@ -50,16 +59,6 @@ export default function SignUp() {
alt=""
className="hidden lg:block w-full h-full object-cover"
/>
{/* <video
autoPlay
loop
muted
playsInline
className="hidden lg:block w-3/5 aspect-square"
>
<source src={img} type="video/mp4" />
<source src={img} type="video/webm" />
</video> */}
</div>

<div className="w-full bg-gray-100 lg:w-1/2 flex items-center justify-center">
Expand All @@ -84,7 +83,7 @@ export default function SignUp() {
id="firstName"
name="firstName"
placeholder="John"
value={values.firstName}
value={signupValues.firstName}
onChange={handleChange}
className="mt-1 p-2.5 px-4 w-full border rounded-3xl focus:border-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 transition-colors duration-300"
/>
Expand All @@ -100,7 +99,7 @@ export default function SignUp() {
type="text"
id="lastName"
name="lastName"
value={values.lastName}
value={signupValues.lastName}
onChange={handleChange}
placeholder="Doe"
className="mt-1 p-2.5 px-4 w-full border rounded-3xl focus:border-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 transition-colors duration-300"
Expand All @@ -118,7 +117,7 @@ export default function SignUp() {
type="text"
id="email"
name="email"
value={values.email}
value={signupValues.email}
onChange={handleChange}
placeholder="johndoe@example.com"
className="mt-1 p-2.5 px-4 w-full border rounded-3xl focus:border-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 transition-colors duration-300"
Expand All @@ -135,7 +134,7 @@ export default function SignUp() {
type="password"
id="password"
name="password"
value={values.password}
value={signupValues.password}
onChange={handleChange}
placeholder="*********"
className="mt-1 p-2.5 px-4 w-full border rounded-3xl focus:border-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-300 transition-colors duration-300"
Expand Down Expand Up @@ -183,6 +182,7 @@ export default function SignUp() {
<span className="text-black hover:underline">Login here</span>
</Link>
</div>
{loading && <Loader />}
</div>
</div>
</div>
Expand Down
71 changes: 71 additions & 0 deletions client/src/Pages/VerifyOTP.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as React from "react"
import { Link, useNavigate } from "react-router-dom"
import { useAppDispatch, useAppSelector } from "../hooks"
import img from "../assets/img/Auth/signup.webp"
import { verification } from "../features/userSlice"

export default function SignUp() {
const dispatch = useAppDispatch()
const navigate = useNavigate()
const { verificationRequired, loading, isAuthenticated } = useAppSelector(
(state) => state.user,
)

const [otp, setOtp] = React.useState<number>(0)

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setOtp(+e.target.value)
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (!otp) return alert("All fields are required")
dispatch(verification(otp))
}

React.useEffect(() => {
if (!loading) {
if (verificationRequired === false || isAuthenticated) {
navigate("/")
}
}
}, [loading, verificationRequired, isAuthenticated])

return (
<div className="flex h-screen">
<div className="hidden lg:flex items-center justify-center flex-1 bg-white text-black">
<img
src={img}
alt=""
className="hidden lg:block w-full h-full object-cover"
/>
</div>

<div className="w-full bg-gray-100 lg:w-1/2 flex items-center justify-center">
<div className="max-w-md w-full p-6 scale-105">
<h1 className="text-3xl font-semibold mb-6 text-black text-center">
Enter OTP
</h1>
<form onSubmit={handleSubmit} className="space-y-4 ">
<div className=" gap-3 mt-4">
<label
htmlFor="otp"
className="ml-3 block text-sm font-medium text-gray-700"
>
OTP
</label>
<input
type="number"
name="otp"
id="otp"
required
value={otp}
onChange={handleChange}
className="w-full border-gray-300 rounded-md shadow-sm"
/>
</div>
</form>
</div>
</div>
</div>
)
}
Loading

1 comment on commit e2c020f

@aslezar
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completed #10

Please sign in to comment.