assignment-4/src/pages/Home.jsx
2025-01-02 16:21:24 +05:30

148 lines
4.2 KiB
JavaScript

import React, { useEffect, useState } from "react";
import axios from "axios";
import { useInView } from "react-intersection-observer";
import Skeleton from "react-loading-skeleton";
import "react-loading-skeleton/dist/skeleton.css";
import CharacterCard from "../components/CharacterCard";
const Home = () => {
const [page, setPage] = useState(1);
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [searchQuery, setSearchQuery] = useState("");
const [loading, setLoading] = useState(true);
const [showSkeleton, setShowSkeleton] = useState(false);
const [suggestions, setSuggestions] = useState([]);
const [hasMore, setHasMore] = useState(true);
const { ref, inView } = useInView({
threshold: 0.1,
});
useEffect(() => {
if (!hasMore) return;
setShowSkeleton(true);
setTimeout(() => {
axios
.get(`https://swapi.py4e.com/api/people/?page=${page}`)
.then((res) => {
const results = res.data.results;
if (results.length > 0) {
setData((prevData) => [...prevData, ...results]);
setFilteredData((prevData) => [...prevData, ...results]);
} else {
setHasMore(false);
}
setLoading(false);
setShowSkeleton(false);
})
.catch(() => {
setShowSkeleton(false);
setHasMore(false);
});
}, 1000);
}, [page]);
useEffect(() => {
if (inView && hasMore && !loading) {
setPage((prevPage) => prevPage + 1);
}
}, [inView, hasMore, loading]);
const handleSearch = (e) => {
const query = e.target.value.toLowerCase();
setSearchQuery(query);
if (query === "") {
setFilteredData(data);
setSuggestions([]);
return;
}
const filtered = data.filter((character) =>
character.name.toLowerCase().includes(query)
);
setFilteredData(filtered);
const autoSuggestions = data
.map((character) => character.name)
.filter((name) => name.toLowerCase().includes(query))
.slice(0, 5);
setSuggestions(autoSuggestions);
};
const handleSuggestionClick = (suggestion) => {
setSearchQuery(suggestion);
setFilteredData(
data.filter(
(character) => character.name.toLowerCase() === suggestion.toLowerCase()
)
);
setSuggestions([]);
};
return (
<div className="main">
<div className="header-container">
<div className="header">
{loading ? (
<Skeleton width={120} height={60} />
) : (
<img src="/images/logo.png" alt="Logo" />
)}
</div>
<div className="search-container">
{loading ? (
<Skeleton width={280} height={52} />
) : (
<input
type="text"
placeholder="Search by name..."
value={searchQuery}
onChange={handleSearch}
className="search-input"
/>
)}
{suggestions.length > 0 && (
<ul className="suggestions">
{suggestions.map((suggestion, index) => (
<li
key={index}
className="suggestion-item"
onClick={() => handleSuggestionClick(suggestion)}
>
{suggestion}
</li>
))}
</ul>
)}
</div>
</div>
<CharacterCard data={filteredData} />
{showSkeleton && hasMore && (
<ul className="skeleton-character-container">
{[...Array.from({ length: 5 })].map((_, index) => (
<li className="skeleton-character-card skeleton" key={index}>
<div className="skeleton-character-details">
<div className="skeleton-line skeleton-title"></div>
<div className="skeleton-line"></div>
<div className="skeleton-line"></div>
<div className="skeleton-line"></div>
<div className="skeleton-line"></div>
</div>
</li>
))}
</ul>
)}
{hasMore && <div ref={ref}></div>}
</div>
);
};
export default Home;