feat: add firebase and react router to the project

-create login form to authenticate user using firebase
This commit is contained in:
sushant dhimal 2023-03-13 23:59:21 +05:45
parent 9600e17139
commit 085335589a
13 changed files with 1704 additions and 58 deletions

1461
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,10 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"firebase": "^9.17.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-spinners": "^0.13.7",
"web-vitals": "^2.1.4"

View File

@ -1,13 +1,33 @@
import "./normal.css";
import "./App.css";
import Home from "./pages/Home";
// import Login from "./pages/Login";
import Login from "./pages/Login";
import { Navigate, Route, Routes } from "react-router-dom";
import { useContext } from "react";
import { AuthContext } from "./context/AuthContext";
function App() {
const { currentUser } = useContext(AuthContext);
const RequireAuth = ({ children }) => {
return currentUser ? children : <Navigate to="login" />;
};
return (
<div className="App">
<Home />
{/* <Login /> */}
<Routes>
<Route
index
exact
path="/"
element={
<RequireAuth>
<Home />/
</RequireAuth>
}
/>
<Route exact path="login" element={<Login />} />
</Routes>
</div>
);
}

View File

@ -1,7 +1,11 @@
import React from "react";
const Button = ({ text }) => {
return <button id="loginButton">{text}</button>;
const Button = ({ text, handleClick }) => {
return (
<button id="loginButton" onClick={handleClick}>
{text}
</button>
);
};
export default Button;

View File

@ -1,21 +0,0 @@
import React from "react";
import Button from "./Button";
import SvgComponent from "./SvgComponent";
const Login = () => {
return (
<div className="loginContainer">
<div className="loginContainerContent">
<SvgComponent w={50} h={50} />
<h1>Welcome to Talkbot</h1>
<p>Your Ultimate AI Assistant</p>
<div className="loginButtonWrapper">
<Button text="Log in" />
<Button text="Sign up" />
</div>
</div>
</div>
);
};
export default Login;

View File

@ -1,6 +1,6 @@
import React from "react";
const SvgComponent = ({ w, h }) => {
const SvgComponent = ({ w, h, stroke }) => {
return (
<svg
width={w}
@ -8,6 +8,7 @@ const SvgComponent = ({ w, h }) => {
fill="none"
xmlns="http://www.w3.org/2000/svg"
strokeWidth={1.5}
stroke={stroke}
className="h-6 w-6"
>
<path

View File

@ -0,0 +1,72 @@
import React, { useContext, useState } from "react";
import "./loginform.css";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from "../../firebase.config";
import { AuthContext } from "../../context/AuthContext";
import { useNavigate } from "react-router-dom";
import SvgComponent from "../SvgComponent";
const LoginForm = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [errorMessage, setErrorMessage] = useState(false);
const { dispatch } = useContext(AuthContext);
console.log("context", dispatch);
const navigate = useNavigate();
const handleLogin = async (e) => {
e.preventDefault();
try {
let userCredential = await createUserWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
console.log("user", user);
dispatch({ type: "LOGIN", payload: user });
console.log("email", email);
// once user is signed in navigate them to the home page
navigate("/");
} catch (error) {
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorCode, errorMessage);
setErrorMessage(true);
}
};
return (
<div className="loginFormContainer">
<SvgComponent w={50} h={50} stroke="#202123" />
<h1>Create your account</h1>
<form onSubmit={handleLogin}>
<input
type="email"
name="email"
id="email"
placeholder="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
type="password"
name="password"
id="password"
placeholder="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
autoComplete="password"
/>
<button type="submit">Continue</button>
{errorMessage && <span>Wrong email or password!</span>}
</form>
</div>
);
};
export default LoginForm;

View File

@ -0,0 +1,47 @@
.loginFormContainer {
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
font-family: var(--text-font);
}
.loginFormContainer h1 {
color: #2d333a;
}
.loginFormContainer form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.loginFormContainer input {
width: 200px;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
}
.loginFormContainer input:focus {
outline: none;
border-color: #505ef6;
}
.loginFormContainer button {
width: 220px;
border: none;
border-radius: 5px;
padding: 12px;
margin-top: 5px;
background-color: #10a37f;
color: #fff;
cursor: pointer;
position: static;
}
.loginFormContainer span {
font-size: 15px;
color: red;
margin-top: 10px;
}

View File

@ -0,0 +1,24 @@
import { createContext, useEffect, useReducer } from "react";
import reducer from "./AuthReducer";
const initialState = {
// currentUser must be object so JSON string must be parsed into JS object
currentUser: JSON.parse(localStorage.getItem("user")) || null,
};
export const AuthContext = createContext(initialState);
export const AuthContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
// need to convert JS object to string to store in localStorage
localStorage.setItem("user", JSON.stringify(state.currentUser));
}, [state.currentUser]);
return (
<AuthContextProvider value={{ currentUser: state.currentUser, dispatch }}>
{children}
</AuthContextProvider>
);
};

View File

@ -0,0 +1,19 @@
function AuthReducer(state, action) {
switch (action.type) {
case "LOGIN": {
return {
currentUser: action.payload,
};
}
case "SignUp": {
return {
currentUser: action.payload,
};
}
default: {
return state;
}
}
}
export default AuthReducer;

View File

@ -0,0 +1,20 @@
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_KEY,
authDomain: process.env.REACT_APP_FIREBASE_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECTID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGEBUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_SENDERID,
appId: process.env.REACT_APP_FIREBASE_APPID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENTID,
};
// Initialize Firebase
const firebaseApp = initializeApp(firebaseConfig);
const auth = getAuth(firebaseApp);
const goggleAuthProvider = new GoogleAuthProvider();
export { auth, goggleAuthProvider };

View File

@ -1,13 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);

View File

@ -1,20 +1,40 @@
import React from "react";
import React, { useContext, useState } from "react";
import Button from "../components/Button";
import SvgComponent from "../components/SvgComponent";
import { useNavigate } from "react-router-dom";
import LoginForm from "../components/login/LoginForm";
import { AuthContext } from "../context/AuthContext";
const Login = () => {
const [isLoginFormVisible, setIsLoginFormVisible] = useState(false);
const handleClick = async (purpose) => {
if (purpose === "signup") {
setIsLoginFormVisible(true);
}
};
return (
<div className="loginContainer">
<div className="loginContainerContent">
<SvgComponent w={50} h={50} />
<h1>Welcome to Talkbot</h1>
<p>Your Ultimate AI Assistant</p>
<div className="loginButtonWrapper">
<Button text="Log in" />
<Button text="Sign up" />
<>
{!isLoginFormVisible ? (
<div className="loginContainer">
<div className="loginContainerContent">
<SvgComponent w={50} h={50} />
<h1>Welcome to Talkbot</h1>
<p>Your Ultimate AI Assistant</p>
<div className="loginButtonWrapper">
<Button text="Log in" handleClick={() => handleClick("login")} />
<Button
text="Sign up"
handleClick={() => handleClick("signup")}
/>
</div>
</div>
</div>
</div>
</div>
) : (
<LoginForm />
)}
</>
);
};