Skip to content

Commit

Permalink
Merge pull request #102 from Anshul-251204/feature/auto-login
Browse files Browse the repository at this point in the history
add auto login
  • Loading branch information
Sowmya-Raghuram authored Nov 19, 2024
2 parents 2c17dfe + 6b1fe26 commit c6e172e
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 52 deletions.
14 changes: 14 additions & 0 deletions src/main/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

229 changes: 185 additions & 44 deletions src/main/frontend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,101 +1,242 @@
// import React, { useEffect, useState } from "react";
// import LoginPage from "./containers/LoginPage/LoginPage";
// import MainPage from "./containers/MainPage/MainPage";
// import ExplorePage from "./containers/ExplorePage/ExplorePage";
// import { auth } from "./firebase";
// import { useSelector, useDispatch } from 'react-redux';
// import { fetchUserByEmail } from './state/userSlice';
// import { fetchNeeds } from './state/needSlice';
// import { fetchNeedtypes } from './state/needtypeSlice';
// import { fetchNeedsByUid } from "./state/needByUidSlice";
// import { fetchEntities } from "./state/entitySlice";
// import { fetchUserList } from "./state/userListSlice";

// function App() {
// const dispatch = useDispatch();

// // AUTHENTICATION using firebase
// const [presentUser, setPresentUser] = useState(null);
// useEffect(() => {
// const unsubscribe = auth.onAuthStateChanged((user) => {
// if (user) {
// setPresentUser({
// uid: user.uid, // this is firebase userId
// email: user.email,
// });
// } else {
// setPresentUser(null);
// }
// });

// // Cleanup subscription on unmount
// return () => unsubscribe();
// }, []);

// // UPDATE USER STATE based on authenticated email
// const userDetails = useSelector((state) => state.user.data);
// console.log(userDetails);

// // Dispatch the user to store
// useEffect(() => {
// if (presentUser) {
// const userEmail = presentUser.email.replace(/@/g, "%40") || '';
// console.log(userEmail);
// dispatch(fetchUserByEmail(userEmail));
// }
// }, [dispatch, presentUser]);

// // UPDATE USERLIST
// useEffect(() => {
// dispatch(fetchUserList());
// }, [dispatch]);

// // UPDATE NEEDSBYID
// useEffect(() => {
// if (userDetails.osid) {
// dispatch(fetchNeedsByUid(userDetails.osid));
// }
// }, [dispatch, userDetails]);

// // UPDATE NEEDS
// useEffect(() => {
// dispatch(fetchNeeds());
// }, [dispatch]);

// // UPDATE NEEDTYPES
// useEffect(() => {
// dispatch(fetchNeedtypes());
// }, [dispatch]);

// // UPDATE ENTITIES
// useEffect(() => {
// dispatch(fetchEntities());
// }, [dispatch]);

// const [volunteer, setVolunteer] = useState(false);

// const handleVolunteer = (value) => {
// setVolunteer(value);
// };

// // Handle explore button click
// if (volunteer) {
// return <ExplorePage />;
// }

// // If user is logged in and userDetails are available
// if (presentUser !== null && userDetails !== undefined) {
// if (userDetails.role && userDetails.role.includes('Volunteer')) {
// // User is a volunteer
// return <ExplorePage />;
// } else {
// // Default: render MainPage for other roles
// return <MainPage />;
// }
// }

// // Default: render LoginPage if user is not logged in or userDetails are being fetched
// return <LoginPage getVolunteerStatus={handleVolunteer} />;
// }

// export default App;



import React, { useEffect, useState } from "react";
import LoginPage from "./containers/LoginPage/LoginPage";
import MainPage from "./containers/MainPage/MainPage";
import ExplorePage from "./containers/ExplorePage/ExplorePage";
import { auth } from "./firebase";
import { useSelector, useDispatch } from 'react-redux';
import { fetchUserByEmail } from './state/userSlice';
import { fetchNeeds } from './state/needSlice';
import { fetchNeedtypes } from './state/needtypeSlice';
import { signInWithCustomToken } from "firebase/auth";
import { useSelector, useDispatch } from "react-redux";
import { fetchUserByEmail } from "./state/userSlice";
import { fetchNeeds } from "./state/needSlice";
import { fetchNeedtypes } from "./state/needtypeSlice";
import { fetchNeedsByUid } from "./state/needByUidSlice";
import { fetchEntities } from "./state/entitySlice";
import { fetchUserList } from "./state/userListSlice";

import "./index.css"
function App() {
const dispatch = useDispatch();
const [presentUser, setPresentUser] = useState(null); // Holds Firebase-authenticated user
const [loading, setLoading] = useState(true); // Global loading state

// Redux state for user details
const userDetails = useSelector((state) => state.user.data);
const userStatus = useSelector((state) => state.user.status); // loading, succeeded, failed
const [volunteer, setVolunteer] = useState(false); // State for volunteer redirection

// Token-Based Authentication Logic
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const token = params.get("token");

if (token) {
signInWithCustomToken(auth, token)
.then((userCredential) => {
console.log("User authenticated with custom token:", userCredential.user);

const email = userCredential.user?.uid; // Access email from the user object
if (email) {
setPresentUser({
uid: userCredential.user.uid,
email: email,
});

// Fetch user details
const userEmail = email?.replace(/@/g, "%40");
dispatch(fetchUserByEmail(userEmail));
} else {
console.error("Email is missing from the user object.");
}
})
.catch((error) => {
console.error("Authentication with custom token failed:", error);
setPresentUser(null);
})
.finally(() => setLoading(false));
} else {
// Handle case where no token is present
setLoading(false);
}
}, [dispatch]);

// AUTHENTICATION using firebase
const [presentUser, setPresentUser] = useState(null);
// Firebase Listener-Based Authentication Logic
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
if (user) {
setPresentUser({
uid: user.uid, // this is firebase userId
uid: user.uid,
email: user.email,
});

// Fetch user details for listener-based login
const userEmail = user.email?.replace(/@/g, "%40");
dispatch(fetchUserByEmail(userEmail));
} else {
setPresentUser(null);
}
});

// Cleanup subscription on unmount
return () => unsubscribe();
}, []);

// UPDATE USER STATE based on authenticated email
const userDetails = useSelector((state) => state.user.data);
console.log(userDetails);
}, [dispatch]);

// Dispatch the user to store
// Fetch user list after user details are loaded
useEffect(() => {
if (presentUser) {
const userEmail = presentUser.email.replace(/@/g, "%40") || '';
console.log(userEmail);
dispatch(fetchUserByEmail(userEmail));
if (userStatus === "succeeded") {
dispatch(fetchUserList());
}
}, [dispatch, presentUser]);

// UPDATE USERLIST
useEffect(() => {
dispatch(fetchUserList());
}, [dispatch]);
}, [dispatch, userStatus]);

// UPDATE NEEDSBYID
// Fetch needs by UID when userDetails are populated
useEffect(() => {
if (userDetails.osid) {
dispatch(fetchNeedsByUid(userDetails.osid));
}
}, [dispatch, userDetails]);

// UPDATE NEEDS
// Fetch global needs
useEffect(() => {
dispatch(fetchNeeds());
}, [dispatch]);

// UPDATE NEEDTYPES
// Fetch need types
useEffect(() => {
dispatch(fetchNeedtypes());
}, [dispatch]);

// UPDATE ENTITIES
// Fetch entities
useEffect(() => {
dispatch(fetchEntities());
}, [dispatch]);

const [volunteer, setVolunteer] = useState(false);

// Handle volunteer status change
const handleVolunteer = (value) => {
setVolunteer(value);
};

// Handle explore button click
if (volunteer) {
return <ExplorePage />;
// Conditional rendering logic
if (loading) {
return <div>Loading...</div>;
}

// If user is logged in and userDetails are available
if (presentUser !== null && userDetails !== undefined) {
if (userDetails.role && userDetails.role.includes('Volunteer')) {
// User is a volunteer
return <ExplorePage />;
} else {
// Default: render MainPage for other roles
return <MainPage />;
}
if (presentUser === null) {
return <LoginPage getVolunteerStatus={handleVolunteer} />;
}

if (userStatus === "loading") {
return (<div className="loading-div">
<div className="spiner"></div>
</div>);
}

// Default: render LoginPage if user is not logged in or userDetails are being fetched
return <LoginPage getVolunteerStatus={handleVolunteer} />;
if (userDetails.role && userDetails.role.includes("Volunteer")) {
return <ExplorePage />;
}

return <MainPage />;
}

export default App;

42 changes: 34 additions & 8 deletions src/main/frontend/src/index.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,39 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Inter','Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI",
"Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
"Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

.loading-div {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}

.spiner {
height: 55px;
width: 55px;
border-top: 3px solid purple;
border-left: 3px solid purple;
border-radius: 50%;
animation: spin 1s linear infinite;
}

@keyframes spin {
0% {
transform: rotate(0deg); /* Initial rotation */
}
100% {
transform: rotate(360deg); /* Full rotation */
}
}

0 comments on commit c6e172e

Please sign in to comment.