Skip to content

Commit

Permalink
Merge pull request #76 from razputshivanshu/feature-branch
Browse files Browse the repository at this point in the history
I have implemented the validation for the new users using firebase.
  • Loading branch information
VesperAkshay authored Oct 5, 2024
2 parents ad7b085 + b76d85e commit 7262297
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 167 deletions.
44 changes: 23 additions & 21 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Navbar from './components/Navbar';
Expand All @@ -11,36 +12,37 @@ import { AuthProvider } from './context/AuthContext';
import Support from './components/Support';
import Settings from './components/Setting';
import ImageQRCodeGenerator from './components/ImageQRCodeGenerator';
import SocialMedia from './components/SocialMedia';
import SocialMedia from './components/SocialMedia';
import BulkQRCode from './components/BulkQRCode';
import QRScanner from './components/QRScanner';
import PdfQRCodeGenerator from './components/PDFToQR';
import { ThemeProvider } from './context/ThemeContext';
import { Toaster } from 'react-hot-toast';
import ProtectedRoute from './components/ProtectedRoute';

export default function App() {
return (
<AuthProvider>
<ThemeProvider>
<Router>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/dashboard" element={<DashboardPage />} />
<Route path="/qr-code" element={<QRCodePage />} />
<Route path="/profile" element={<ProfilePage />} />
<Route path="/support" element={<Support />} />
<Route path="/settings" element={<Settings />} />
<Route path="/image-qr-code" element={<ImageQRCodeGenerator />} />
<Route path="/social-media-qr" element={<SocialMedia />} />
<Route path="/bulk-qr-code" element={<BulkQRCode />} />
<Route path="/qr-scanner" element={<QRScanner />} />
<Route path="/pdf-qr-code" element={<PdfQRCodeGenerator />} />
</Routes>
<Toaster />
</Router>
<Router>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/dashboard" element={<ProtectedRoute><DashboardPage /></ProtectedRoute>} />
<Route path="/qr-code" element={<QRCodePage />} />
<Route path="/profile" element={<ProfilePage />} />
<Route path="/support" element={<Support />} />
<Route path="/settings" element={<Settings />} />
<Route path="/image-qr-code" element={<ImageQRCodeGenerator />} />
<Route path="/social-media-qr" element={<SocialMedia />} />
<Route path="/bulk-qr-code" element={<BulkQRCode />} />
<Route path="/qr-scanner" element={<QRScanner />} />
<Route path="/pdf-qr-code" element={<PdfQRCodeGenerator />} />
{/* Remove the line for Verify */}
{/* <Route path="/verify" element={<Verify />} /> */}
</Routes>
</Router>
</ThemeProvider>
</AuthProvider>
);
Expand Down
70 changes: 59 additions & 11 deletions src/components/Login.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,63 @@
import React, { useState } from 'react';
import { signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from "firebase/auth";
import { signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider, sendEmailVerification } from "firebase/auth";
import { auth } from '../firebase';
import { useNavigate } from 'react-router-dom';
import { FcGoogle } from "react-icons/fc";
import { motion } from 'framer-motion';
import toast from 'react-hot-toast';
import { useAuth } from "../context/AuthContext";

export default function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showVerificationModal, setShowVerificationModal] = useState(false);
const [emailAuthVerified, setEmailAuthVerified] = useState(false);
const [googleAuthVerified, setGoogleAuthVerified] = useState(false);
const navigate = useNavigate();
const { setCurrentUser } = useAuth();

const handleSubmit = async (e) => {
e.preventDefault();
try {
await signInWithEmailAndPassword(auth, email, password);
navigate('/dashboard');
toast.success("Login Successful");
const userCredential = await signInWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
setCurrentUser(user);

if (user.emailVerified) {
setEmailAuthVerified(true);
navigate('/dashboard');
} else {
setShowVerificationModal(true);
}
} catch (error) {
toast.error('Something went wrong');
console.error(error.message);
alert(error.message);
}
};

const handleGoogleLogin = async () => {
const provider = new GoogleAuthProvider();
try {
await signInWithPopup(auth, provider);
navigate('/dashboard');
const userCredential = await signInWithPopup(auth, provider);
const user = userCredential.user;
setCurrentUser(user);

if (user.emailVerified) {
setGoogleAuthVerified(true);
navigate('/dashboard');
} else {
setShowVerificationModal(true);
}
} catch (error) {
toast.error('Something went wrong');
console.error(error.message);
alert(error.message);
}
};

const handleSendVerificationEmail = async () => {
try {
await sendEmailVerification(auth.currentUser);
alert('Verification email sent! Please check your inbox.');
setShowVerificationModal(false);
} catch (error) {
alert(error.message);
}
};

Expand Down Expand Up @@ -84,6 +111,27 @@ export default function Login() {
Sign in with <span className="font-bold ml-1"> Google</span>
</motion.button>
</motion.form>

{showVerificationModal && (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<div className="bg-white p-6 rounded-lg shadow-lg w-11/12 max-w-md">
<h2 className="text-2xl font-bold mb-4">Email Verification Required</h2>
<p className="mb-4">Your email address is not verified. Please verify your email to continue.</p>
<button
onClick={handleSendVerificationEmail}
className="w-full bg-indigo-600 text-white p-3 rounded-lg hover:bg-indigo-700 transition-colors duration-300 shadow-lg font-semibold"
>
Resend Verification Email
</button>
<button
onClick={() => setShowVerificationModal(false)}
className="w-full mt-3 bg-gray-200 text-black p-3 rounded-lg hover:bg-gray-300 transition-colors duration-150 shadow-lg font-semibold"
>
Close
</button>
</div>
</div>
)}
</div>
);
}
114 changes: 37 additions & 77 deletions src/components/Navbar.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import React, { useState, useEffect, useRef, useContext } from "react";
import { useAuth } from "../context/AuthContext";
import { Link, useNavigate } from "react-router-dom";
import { ThemeContext } from "../context/ThemeContext";
import toast from "react-hot-toast";

import {
FaUser,
Expand All @@ -22,69 +22,17 @@ export default function Navbar() {
const navigate = useNavigate();
const [dropdownOpen, setDropdownOpen] = useState(false);
const dropdownRef = useRef(null);

const { darkMode, setDarkMode } = useContext(ThemeContext);

const handleLogout = async () => {
// Show a confirmation toast
const confirmation = toast(
(t) => (
<div>
<p>Are you sure you want to log out?</p>
<div className="flex justify-between">
<button
onClick={() => {
toast.dismiss(t.id); // Dismiss the confirmation toast
}}
className="text-blue-600 hover:bg-blue-200 px-4 py-2 bg-blue-100 m-2 mt-4 rounded-md "
>
Cancel
</button>
<button
onClick={async () => {
toast.dismiss(t.id); // Dismiss the confirmation toast
try {
await logout(); // Proceed with logout
navigate("/"); // Redirect to the home page after logout
toast.success("Logged out");
} catch (error) {
console.error("Failed to log out", error);
toast.error("Logout failed. Please try again."); // Show an error message
}
}}
className="text-red-600 hover:bg-red-200 px-4 py-2 bg-red-100 m-2 mt-4 rounded-md "
>
Log out
</button>
</div>
</div>
),
{
duration: 0, // Keep the toast open until dismissed
position: 'top-center', // Adjust position if needed
}
)
};

const handleToggleTheme = () => {
setDarkMode((prevMode) => {
const newMode = !prevMode;

// Show toast notification when theme changes
toast(`Theme changed to ${newMode ? 'Dark' : 'Light'} mode!`, {
icon: `${newMode ? '🌙' :'☀️'}`,
style: {
borderRadius: '10px',
background: `${newMode ? '#333' : '#fff'} `,
color: `${newMode ? '#fff' : '#333'}`,
},
});

return newMode;
});
try {
await logout();
navigate("/"); // Redirect to the home page after logout
} catch (error) {
console.error("Failed to log out", error);
}
};


const toggleDropdown = () => {
setDropdownOpen(!dropdownOpen);
};
Expand All @@ -105,10 +53,11 @@ export default function Navbar() {

return (
<nav
className={`p-4 shadow-lg ${darkMode
className={`p-4 shadow-lg ${
darkMode
? "bg-[#00050e] border-b-[1px] border-[#333333]"
: "bg-gradient-to-r from-indigo-600 to-purple-600"
}`}
}`}
>
<div className="container mx-auto flex justify-between items-center">
<div className="flex items-center space-x-3">
Expand Down Expand Up @@ -150,13 +99,15 @@ export default function Navbar() {
<div className="relative" ref={dropdownRef}>
{dropdownOpen && (
<div className="absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-2 z-20">
<Link
to="/dashboard"
className="flex items-center px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300"
>
<FaUser className="mr-2" />
Dashboard
</Link>
{currentUser.emailVerified && ( // Check if the user is verified
<Link
to="/dashboard"
className="flex items-center px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300"
>
<FaUser className="mr-2" />
Dashboard
</Link>
)}
<Link
to="/profile"
className="flex items-center px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300"
Expand All @@ -183,7 +134,9 @@ export default function Navbar() {
</div>
</div>
<button
onClick={handleToggleTheme}
onClick={() => {
setDarkMode(!darkMode);
}}
className="text-white hover:text-indigo-200 transition duration-300 text-xl"
>
{darkMode ? <MdLightMode /> : <FaMoon />}
Expand Down Expand Up @@ -220,13 +173,15 @@ export default function Navbar() {
<div className="md:hidden mt-2 w-full bg-white dark:bg-gray-800 rounded-md shadow-lg py-2 z-20">
{currentUser ? (
<>
<Link
to="/dashboard"
className="flex items-center px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300"
>
<FaUser className="mr-2" />
Dashboard
</Link>
{currentUser.emailVerified && ( // Check if the user is verified
<Link
to="/dashboard"
className="flex items-center px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300"
>
<FaUser className="mr-2" />
Dashboard
</Link>
)}
<Link
to="/profile"
className="flex items-center px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300"
Expand All @@ -249,7 +204,9 @@ export default function Navbar() {
Logout
</button>
<button
onClick={() => { setDarkMode(!darkMode); }}
onClick={() => {
setDarkMode(!darkMode);
}}
className="flex items-center gap-2 px-4 py-2 text-gray-700 dark:text-white hover:bg-indigo-500 hover:text-white transition duration-300 w-full"
>
{darkMode ? <MdLightMode size={16} /> : <FaMoon size={10} />} Toggle Dark Mode
Expand Down Expand Up @@ -278,3 +235,6 @@ export default function Navbar() {
</nav>
);
}



36 changes: 36 additions & 0 deletions src/components/ProtectedRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@


import React, { useEffect, useState } from 'react';
import { Navigate } from 'react-router-dom';
import { auth, onAuthStateChanged } from '../firebase'; // Ensure the correct import

const ProtectedRoute = ({ children }) => {
const [loading, setLoading] = useState(true);
const [isAuthorized, setIsAuthorized] = useState(false);

useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
if (user) {
// Check if the user has verified their email
setIsAuthorized(user.emailVerified);
} else {
setIsAuthorized(false);
}
setLoading(false);
});

return () => unsubscribe();
}, []);

if (loading) {
return <div>Loading...</div>; // Show loading indicator while checking auth
}

if (!isAuthorized) {
return <Navigate to="/login" />;
}

return children;
};

export default ProtectedRoute;
Loading

0 comments on commit 7262297

Please sign in to comment.