Skip to content

Commit

Permalink
Merge pull request chetannada#52 from chetannada/Chapter-09
Browse files Browse the repository at this point in the history
Added: Custom Hook useAuth and useLocalStorage
  • Loading branch information
chetannada authored Sep 10, 2023
2 parents ec9e5c1 + 4f93790 commit 5a7fcb3
Show file tree
Hide file tree
Showing 12 changed files with 525 additions and 191 deletions.
18 changes: 9 additions & 9 deletions Chapter 09 - Optimizing our App/Coding/Components/About.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import food from "../Images/burger-image.png";
const About = () => {
const [show, setShow] = useState(false);
return (
<div>
<div className="about-container-main">
<div className="about-profile-container">
{/* used ternary condition to Show my profile and Hide my Profile and using nested routing */}
{show ? (
<>
<Link to={"/about"}>
<button
className="about-profile-button"
onClick={() => setShow(false)}
>
Hide My Profile
</button>
<Link to={"/about"}>
<button
className="about-profile-button"
onClick={() => setShow(false)}
>
Hide My Profile
</button>
</Link>
<Outlet />
</>
Expand All @@ -34,7 +34,7 @@ const About = () => {
<div className="about-container">
<div className="about-left">
<h1>
Welcome to <br /> The world of <br />{" "}
Welcome to <br /> The world of <br />
<span>Tasty & Fresh Food</span>
</h1>
<h4>
Expand Down
7 changes: 4 additions & 3 deletions Chapter 09 - Optimizing our App/Coding/Components/Body.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const Body = () => {
const [allRestaurants, FilterRes] = useResData(swiggy_api_URL);
const [filteredRestaurants, setFilteredRestaurants] = useState(null);
const isOnline = useOnline();

// if user is not Online then return UserOffline component
if (!isOnline) {
return <UserOffline />
Expand All @@ -42,7 +43,7 @@ const Body = () => {
if (!allRestaurants) return null;

return (
<>
<div className="body-container">
<div className="search-container">
<input
type="text"
Expand All @@ -55,7 +56,7 @@ const Body = () => {
// when user will enter the data, it automatically called searchData function so it work same as when you click on Search button
searchData(e.target.value, allRestaurants);
}}
></input>
/>
<button
className="search-btn"
onClick={() => {
Expand Down Expand Up @@ -89,7 +90,7 @@ const Body = () => {
)}
</div>
)}
</>
</div>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Contact = () => {
return (
<div className="contact-container">
<div className="contact-left">
<img src={contact} alt="" />
<img src={contact} alt="Contact us" />
</div>
<div className="contact-right">
<h1>Contact us</h1>
Expand Down
44 changes: 31 additions & 13 deletions Chapter 09 - Optimizing our App/Coding/Components/Header.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,50 @@
import { useState } from "react";
import FoodFireLogo from "../Images/Food Fire Logo.png";
import { Link } from "react-router-dom"; // imported Link for client side routing
import { useNavigate } from "react-router-dom";
import useOnline from "../Hooks/useOnline";
import useAuth from "../Hooks/useAuth";
import useLocalStorage from "../Hooks/useLocalStorage";
import { useEffect } from "react";

// Title component for display logo
const Title = () => (
<a href="/">
<Link to="/">
<img
className="logo"
src={FoodFireLogo}
alt="Food Fire"
title="Food Fire"
/>
</a>
</Link>
);

// Header component for header section: Logo, Nav Items
const Header = () => {
const token = localStorage.getItem("token");
// use useState for user logged in or logged out
const [isLoggedin, setIsLoggedin] = useState(
token?.length === 100 ? true : false
);
const navigate = useNavigate();

// call custom hook useLocalStorage for getting localStorage value of user
const [getLocalStorage, , clearLocalStorage] = useLocalStorage("user");

// call custom hook useAuth for user is loggedin or not
const [isLoggedin, setIsLoggedin] = useAuth();

useEffect(() => {
// if value of getLocalStorage is equal to null setIsLoggedin to false
if (getLocalStorage === null) {
setIsLoggedin(false);
}
}, [getLocalStorage])

// call custom hook useOnline if user is online or not
const isOnline = useOnline();

return (
<div className="header">
<Title />

{/* if user is logged in then display userName */}
{isLoggedin && <div className="user-name">Hi {getLocalStorage?.userName}!</div>}

<div className="nav-items">
<ul>
<li>
Expand All @@ -48,21 +66,21 @@ const Header = () => {
<button
className="logout-btn"
onClick={() => {
localStorage.clear();
setIsLoggedin(!isLoggedin);
clearLocalStorage()
setIsLoggedin(false);
}}
>
Logout
Logout<span className={isOnline ? "login-btn-green" : "login-btn-red"}></span>
</button>
) : (
<button className="login-btn" onClick={() => navigate("/login")}>
Login
Login<span className={isOnline ? "login-btn-green" : "login-btn-red"}></span>
</button>
)}
</li>
</ul>
</div>
</div>
</div >
);
};

Expand Down
54 changes: 32 additions & 22 deletions Chapter 09 - Optimizing our App/Coding/Components/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,53 @@ import React, { useEffect } from "react";
import { Formik } from "formik"; // import Formik from formik
import * as Yup from "yup"; // import Yup from yup
import { useNavigate } from "react-router-dom";
import useLocalStorage from "../Hooks/useLocalStorage";

// create a schema for validation
// create a schema for Email and Password validation
const schema = Yup.object().shape({
email: Yup.string()
.required("Email is a required field")
.email("Invalid email format"),
.required("Email is a required")
.email("Enter Valid Email"),
password: Yup.string()
.required("Password is a required field")
.min(8, "Password must be at least 8 characters"),
.required("Password is a required")
.min(8, "Password must be 8 characters long"),
});

const Login = () => {
const navigate = useNavigate();
const token = localStorage.getItem("token");
// call custom hook useLocalStorage for getting localStorage value of user
const [getLocalStorage, setLocalStorage] = useLocalStorage("user");

useEffect(() => {
if (token?.length === 100) {
// if length of token is equal to 100 then navigate to previous page
if (getLocalStorage?.token?.length === 100) {
navigate(-1);
}
}, []);

function handleNavigate(values) {
// setTimeout for navigate from login page to home page
setTimeout(() => {
// generate random String of 100 character
const genRandomStringNthChar = () => {
return [...Array(100)]
.map(() => Math.random().toString(36)[2])
.join("");
};
// store token in local storage
localStorage.setItem("token", genRandomStringNthChar());
navigate(-1);
}, 0);
let index = values?.email.indexOf('@');
let name = values?.email.slice(0, index);

// generate 100 character random string
const genRandomStringNthChar = () => {
return [...Array(100)]
.map(() => Math.random().toString(36)[2])
.join("");
};

// store userName and token in localStorage
setLocalStorage({
...getLocalStorage,
"userName": name,
"token": genRandomStringNthChar()
})
// navigate to previous page
navigate(-1);
}

if(token?.length === 100) return null;
// if length of token is equal to 100 then return null
if (getLocalStorage?.token?.length === 100) return null;

return (
<>
Expand All @@ -47,8 +57,8 @@ const Login = () => {
validationSchema={schema}
initialValues={{ email: "", password: "" }}
onSubmit={(values) => {
// call handleNavigate and pass input filed data
handleNavigate(JSON.stringify(values));
// invoke handleNavigate function and pass input filed data
handleNavigate(values);
}}
>
{({
Expand Down
36 changes: 19 additions & 17 deletions Chapter 09 - Optimizing our App/Coding/Components/ProfileClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ class Profile extends Component {
this.state = {
userInfo: {
name: "",
bio: "",
},
bio: ""
}
};
// console.log("Profile-Parent constructor");
}

async componentDidMount() {
const response = await fetch(Github_API_User + Github_UserName, options); // Fetch the data from github User API
const json = await response.json();
this.setState({
userInfo: json,
});
})
// console.log("Profile-Parent componentDidMount");
}

Expand All @@ -33,21 +33,23 @@ class Profile extends Component {
// console.log("Profile-Parent componentWillUnmount");
}
render() {
const {userInfo} = this.state; // object destructuring for json data
const { userInfo } = this.state; // object destructuring for json data
// console.log("Profile-Parent - render");
return (
<div className="profile-class-container">
<div className="profile-container">
<h1 className="profile-title">About Me</h1>
<ProfileUserClass data={userInfo} />
{/* Passing props data (full json data) from parent to child */}
</div>
<div className="repo-container">
<h1 className="repo-title">Food<span>Fire</span> App Repository</h1>
<ProfileRepoClass followers={userInfo.followers} />
{/* Passing props followers from parent to child */}
</div>
</div>
<>
{userInfo.name === "" ? null : (<div className="profile-class-container">
<div className="profile-container">
<h1 className="profile-title">About Me</h1>
<ProfileUserClass data={userInfo} />
{/* Passing props data (full json data) from parent to child */}
</div>
<div className="repo-container">
<h1 className="repo-title">Food<span>Fire</span> App Github Repository</h1>
{/* Passing props followers from parent to child */}
<ProfileRepoClass followers={userInfo} />
</div>
</div>)}
</>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ProfileRepoClass extends Component {
// console.log("ProfileRepoClass child componentWillUnmount");
}
render() {
const { followers } = this.props; // accessing followers as props from parent class `ProfileClass`
const { followers, html_url } = this.props.followers; // accessing followers as props from parent class `ProfileClass`
const [...repoList] = this.state.repoInfo;
// console.log("ProfileRepoClass child render");
return (
Expand All @@ -44,27 +44,31 @@ class ProfileRepoClass extends Component {
.filter((repo) => repo.name === Github_Repository_Name)
.map((repo) => {
return (
<div key={repo.id}>
<div key={repo.id} className="profile-repo">
<h1>
<a href={repo.html_url} target="_blank">{repo.name}</a>
<a href={repo.html_url} target="_blank" rel='noopener noreferrer'>{repo.name}</a>
</h1>
<h3 className="repo-des">{repo.description}</h3>
<a href={repo.html_url} target="_blank">
<div className="profile-repo-items">
<h3>
<div className="profile-repo-items">
<h3>
<a href={html_url} target="_blank" rel='noopener noreferrer'>
<FiUsers />
<span>{followers} Followers</span>
</h3>
<h3>
</a>
</h3>
<h3>
<a href={repo.html_url} target="_blank" rel='noopener noreferrer'>
<BiGitRepoForked />
<span>{repo.forks_count} Forks</span>
</h3>
<h3>
</a>
</h3>
<h3>
<a href={repo.html_url} target="_blank" rel='noopener noreferrer'>
<BiStar />
<span>{repo.stargazers_count} Stars</span>
</h3>
</div>
</a>
</a>
</h3>
</div>
</div>
);
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ProfileUserClass extends Component {
super(props);
// console.log("ProfileUserClass child constructor");
}

componentDidMount() {
// console.log("ProfileUserClass child componentDidMount");
}
Expand All @@ -17,18 +17,20 @@ class ProfileUserClass extends Component {
// console.log("ProfileUserClass child componentWillUnmount");
}
render() {
const { name, avatar_url, bio } = this.props.data; // accessing full json data as props from parent class `ProfileClass`
const { name, html_url, avatar_url, bio } = this.props.data; // accessing full json data as props from parent class `ProfileClass`
// console.log("ProfileUserClass child render");
return (
<div className="profile-user-card">
<a href={html_url} target="_blank" rel='noopener noreferrer'>
<img
className="profile-user-img"
src={avatar_url}
alt={name}
title={name}
/>
<p className="profile-user-bio">{bio}</p>
<SocialProfileClass />
</a>
<p className="profile-user-bio">{bio}</p>
<SocialProfileClass />
</div>
);
}
Expand Down
Loading

0 comments on commit 5a7fcb3

Please sign in to comment.