Skip to content

Commit 385446e

Browse files
#TRAPWLS-19 loader added and code optimized
1 parent ca52297 commit 385446e

File tree

8 files changed

+144
-48
lines changed

8 files changed

+144
-48
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"react-redux": "^8.1.3",
1919
"react-router-dom": "^6.4.1",
2020
"react-scripts": "5.0.1",
21+
"react-spinners": "^0.14.1",
2122
"react-toastify": "^10.0.6",
2223
"react-uuid": "^1.0.3",
2324
"redux": "^4.2.0",

src/App.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ nav ul li a:not(.active):hover{
161161
}
162162

163163
.home-card{
164+
height: 100%;
164165
width: 30%;
165166
padding: 10px;
166167
padding-bottom: 80px;
@@ -339,4 +340,17 @@ nav ul li a:not(.active):hover{
339340
.contactus{
340341
margin-top: 20px;
341342
text-align: center;
343+
}
344+
345+
/* Styling for loader*/
346+
.loader {
347+
top: 0;
348+
left: 0;
349+
position: fixed;
350+
width: 100%;
351+
height: 100%;
352+
display: flex;
353+
justify-content: center;
354+
align-items: center;
355+
z-index: 1;
342356
}

src/fetchApiData/FetchApi.jsx

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,66 @@
11
import React ,{useEffect, useState} from 'react'
22
import axios from 'axios'
3+
import { toast } from 'react-toastify'
4+
import ClipLoader from 'react-spinners/ClipLoader';
35

46
function FetchApi() {
5-
const [data, setData] = useState([])
7+
const [data, setData] = useState([]);
8+
const [isLoading, setIsLoading] = useState(false);
69

7-
const fetchData = () => {
8-
console.log("Button clicked")
10+
const fetchData = async () => {
911
//sample get api
10-
axios.get("https://newsapi.org/v2/top-headlines?country=us&apiKey=6004b8fcb1604003b4ead57854e8d2c2")
11-
.then((response) => {
12-
console.log(response);
13-
setData(response.data.articles)
14-
15-
})
12+
try {
13+
setIsLoading(true);
14+
await axios.get("https://newsapi.org/v2/top-headlines?country=us&apiKey=6004b8fcb1604003b4ead57854e8d2c2")
15+
.then((response) => {
16+
setData(response?.data?.articles);
17+
})
18+
} catch (e) {
19+
console.error(e);
20+
} finally {
21+
setIsLoading(false);
22+
}
1623
}
1724

18-
useEffect(() => {
19-
document.body.style.backgroundColor = 'silver';
25+
useEffect(() => {
26+
if (!isLoading) document.body.style.backgroundColor = 'silver';
2027
return () => {
2128
document.body.style.backgroundColor = '';
2229
}
23-
}, []);
30+
}, [isLoading]);
31+
32+
const showToast = () => {
33+
toast.info("Data Already Fetched!!")
34+
}
2435

2536
return (
2637
<>
2738
<div className="btn-fetchContainer">
28-
<button className='btn-fetch' onClick={fetchData}>Click here to Fetch Api Data!!</button>
39+
<button className='btn-fetch' onClick={data.length > 0 ? showToast : fetchData}>Click here to Fetch Api Data!!</button>
2940
</div>
3041

3142
<div className="ui-fetched">
3243
{
3344
data.map((value, index) => {
34-
const imageUrl = value?.urlToImage
35-
console.log("imageUrl--",imageUrl)
45+
const imageUrl = value?.urlToImage;
3646
return(
37-
<div className='card' style={{width: "20rem"}} key={index}>
38-
<img src={value?.urlToImage} className="card-img-top" width={300} alt={value?.title}/>
39-
<div className="card-body">
40-
<h5 className="card-title">{value?.title}</h5>
41-
<p className="card-desc">{value?.description}</p><br></br>
42-
Want to Read more, <a href={value?.url || "/notfound"} className="btn-primary"> <span style={{fontWeight: "bold"}}>Click here</span></a>
47+
<div className='card' style={{width: "20rem"}} key={index}>
48+
<img src={(imageUrl && imageUrl !== null) ? imageUrl : "favicon1.ico"} className="card-img-top" width={300} alt={value?.title}/>
49+
<div className="card-body">
50+
<h5 className="card-title">{value?.title}</h5>
51+
<p className="card-desc">{value?.description}</p><br></br>
52+
Want to Read more, <a href={value?.url || "/notfound"} target='_blank' rel='noopener noreferrer' className="btn-primary"> <span style={{fontWeight: "bold"}}>Click here</span></a>
53+
</div>
4354
</div>
44-
</div>
4555
);
4656
})
4757
}
4858
</div>
59+
60+
{/* Loader */}
61+
{isLoading && <div className="loader" style={{backgroundColor: "none"}}>
62+
<ClipLoader color="#09f" loading={isLoading} size={50} /></div>
63+
}
4964
</>
5065
)
5166
}

src/homePage/Card.jsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
1-
import React from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import { Link } from 'react-router-dom'
3+
let counter = 0;
4+
5+
const Card = ({post, itemArrLength, isAllCardLoaded}) => {
6+
const [imageSrc, setImageSrc] = useState("favicon1.ico");
7+
const handleImageLoad = () => {
8+
setImageSrc(post?.img || "logo512.png");
9+
}
10+
11+
useEffect(() => {
12+
counter = counter + 1;
13+
if (itemArrLength === counter) {
14+
return () => {
15+
setTimeout(() => { isAllCardLoaded(true) }, 1000);
16+
};
17+
}
18+
}, [itemArrLength, isAllCardLoaded]);
319

4-
const Card = ({post}) => {
520
return (
6-
<div className='home-card'>
21+
<div className='home-card'>
722
<Link className='link' to={`/post/${post?.id}`}>
8-
<span className='title'>{post?.title}</span>
23+
<span className='title'>{post?.title}</span>
924
</Link>
1025
<Link className='imgLink' to={'/dashboard'}>
11-
<img src={post?.img} alt="" className="img" />
12-
<p className='desc'>{post?.desc}</p>
13-
<button className='cardButton'>Read more</button>
26+
<img src={imageSrc} alt="" className="img" onLoad={handleImageLoad}/>
27+
<p className='desc'>{post?.desc}</p>
28+
<button className='cardButton'>Read more</button>
1429
</Link>
15-
16-
</div>
30+
</div>
1731
)
1832
}
1933

20-
export default Card
34+
export default Card;

src/homePage/HeaderNavbarLogin.jsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,29 @@ import React, { useEffect, useState } from 'react'
22
import { Link, NavLink, useNavigate } from 'react-router-dom'
33
import "../App.css"
44
import { auth } from '../loginAuthentication/firebase/FirebaseConfig';
5-
import { signOut } from "firebase/auth";
6-
// import { useAuth } from "./../loginAuthentication/firebase/FirebaseAuth"
5+
import { signOut, deleteUser } from "firebase/auth";
6+
import ClipLoader from 'react-spinners/ClipLoader';
77

88
// SampleProfileUrl - https://images.pexels.com/photos/1742370/pexels-photo-1742370.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500
99
const HeaderNavbarLogin = (props) => {
1010
const [menuOpen, setMenuOpen] = useState(false);
1111
const navigateToNextPage = useNavigate();
1212
const {isLoggedinUser, setLoggedInUser} = props;
13-
// const useAuthData = useAuth();
13+
const [isLoading, setIsLoading] = useState(false);
14+
const loggedInData = JSON.parse(localStorage.getItem("loggedInData") || "{}");
1415

15-
16-
function logoutOnclick(isClick = false) {
17-
isClick = true
18-
if(isClick) {
19-
auth.signOut();
16+
async function logoutOnclick() {
17+
setIsLoading(true);
18+
const user = auth?.currentUser;
19+
if(loggedInData?.loggedInType === "usernamePwd") {
20+
await auth.signOut();
2021
} else {
2122
signOut(auth).then(() => {
22-
console.log("GLogin Successfully loggedOut")
23+
if (user) {
24+
deleteUser(user);
25+
console.log("User successfully deleted from Firebase.");
26+
}
27+
setIsLoading(false);
2328
}).catch((e) => {
2429
console.error("Sign out error-->",e)
2530
})
@@ -32,7 +37,6 @@ const HeaderNavbarLogin = (props) => {
3237
}
3338

3439
useEffect(() => {
35-
// console.log("header screen--useAuthData--",useAuthData)
3640
const checkScreenSize = () => {
3741
if (window.innerWidth > 480) {
3842
setMenuOpen(false)
@@ -65,13 +69,18 @@ const HeaderNavbarLogin = (props) => {
6569
<li><NavLink to={"/fetch-api"}>FetchApi</NavLink></li>
6670
<li><NavLink to={"/demo-tasks"}>Other tasks</NavLink></li>
6771
<li className='header-listItem'>
68-
<img alt='' className='header-avatar' src={isLoggedinUser?.loggedInPhotoUrl || "favicon1.ico"}/>
72+
<img src={isLoggedinUser?.loggedInPhotoUrl || "favicon1.ico"} className='header-avatar' alt='' />
6973
</li>
7074
<li className='listItemUserTitle'>Welcome! <b>{isLoggedinUser?.loggedInUsername}</b></li>
7175
<button className='listItemLogout' onClick={logoutOnclick}>Logout</button>
7276
</ul>
7377
</nav>
7478
) : (<Link className='header-loginhere' to="/">Login Here</Link>)}
79+
80+
{/* Loader */}
81+
{isLoading && <div className="loader">
82+
<ClipLoader color="#09f" loading={isLoading} size={50} /></div>
83+
}
7584
</div>
7685
)
7786
}

src/homePage/Home.jsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
1-
import React from 'react'
1+
import React, { useState } from 'react'
22
import {posts} from "./data"
33
import Card from './Card'
4+
import ClipLoader from 'react-spinners/ClipLoader';
45

56
const Home = () => {
7+
const [isLoading, setIsLoading] = useState(true);
8+
9+
const isAllCardLoaded = async (isAllLoaded = false) => {
10+
if(isAllLoaded) { setIsLoading(false); }
11+
}
12+
613
return (
714
<div className='home'>
8-
{posts.map(post=>(
9-
<Card key={post.id} post={post}/>
15+
{posts.map((post, index) => (
16+
<Card
17+
key={post?.id}
18+
post={post}
19+
itemArrLength={posts.length}
20+
isAllCardLoaded={isAllCardLoaded}
21+
/>
1022
))}
11-
</div>
23+
24+
{/* Loader */}
25+
{isLoading && <div className="loader">
26+
<ClipLoader color="#09f" loading={isLoading} size={50} /></div>
27+
}
28+
</div>
1229
)
1330
}
1431

15-
export default Home
32+
export default Home;

src/loginAuthentication/LoginPage.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,16 @@ input:focus{
131131
cursor: pointer;
132132
font-weight: bold;
133133
font-size: 20px;
134+
}
135+
136+
/* Styling for loader*/
137+
.loader {
138+
position: fixed;
139+
width: 100%;
140+
height: 100%;
141+
display: flex;
142+
justify-content: center;
143+
align-items: center;
144+
background-color: rgba(255, 255, 255, 0.8);
145+
z-index: 1;
134146
}

src/loginAuthentication/LoginPage.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { toast } from 'react-toastify';
88
import {auth, provider} from "./firebase/FirebaseConfig";
99
import {signInWithPopup } from "firebase/auth";
1010
import {handleCreateUserWithEmailAndPassword, handleSignInWithEmailAndPassword} from './firebase/LoginAuthCreation';
11+
import ClipLoader from 'react-spinners/ClipLoader';
1112

1213
// for each time show the google accounts in the dialog
1314
provider.setCustomParameters({
@@ -22,6 +23,7 @@ function LoginPage(props) {
2223
//for navigate
2324
const navigateToNextPage = useNavigate();
2425
const {setLoggedInUser} = props;
26+
const [isLoading, setIsLoading] = useState(false);
2527
const [isRegisterClicked, setRegisterClicked] = useState(false);
2628

2729
//password requirement
@@ -101,9 +103,11 @@ function LoginPage(props) {
101103
if (!isValidated) return;
102104

103105
try {
106+
setIsLoading(true);
104107
const signInwithUsername = await handleSignInWithEmailAndPassword(input.username, input.password);
105108
if(signInwithUsername?.success) {
106109
const userObj = {
110+
loginUsernamePwdSuccess: signInwithUsername?.success,
107111
displayName: input.username.slice(0,7) + "...",
108112
email: input.username
109113
}
@@ -118,6 +122,7 @@ function LoginPage(props) {
118122
} catch(e) {
119123
console.log("catch error login--",e)
120124
} finally {
125+
setIsLoading(false);
121126
}
122127
}
123128

@@ -134,6 +139,7 @@ function LoginPage(props) {
134139
}
135140

136141
try {
142+
setIsLoading(true);
137143
const registerWithUsername = await handleCreateUserWithEmailAndPassword(input.username, input.password);
138144
if (registerWithUsername?.success) {
139145
notifyToast({
@@ -146,6 +152,8 @@ function LoginPage(props) {
146152
navigateToRegister_Login();
147153
} catch(e) {
148154
console.log("catch error register--",e)
155+
} finally {
156+
setIsLoading(false);
149157
}
150158
}
151159

@@ -188,6 +196,7 @@ function LoginPage(props) {
188196
const storeLoginSuccessAndNavigate = (user) => {
189197
const loginObj = {
190198
loginSuccess: true,
199+
loggedInType: user?.loginUsernamePwdSuccess ? "usernamePwd" : "socialLogin",
191200
loggedInUsername: user?.displayName || "",
192201
loggedInEmail: user?.email || input?.username || "",
193202
loggedInPhotoUrl: user?.photoURL || ""
@@ -266,6 +275,11 @@ function LoginPage(props) {
266275

267276
{/* Password hint feedback dialog */}
268277
{isPwdFeedbackHint}
278+
279+
{/* Loader */}
280+
{isLoading && <div className="loader">
281+
<ClipLoader color="#09f" loading={isLoading} size={50} /></div>
282+
}
269283
</div>
270284

271285
)

0 commit comments

Comments
 (0)