home
unknown
plain_text
a year ago
13 kB
7
Indexable
import React, { useEffect, useState } from "react";
import "./Home.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
import { faBook } from "@fortawesome/free-solid-svg-icons"; // Import the specific icon
import Footer from "../components/Footer";
import { Link } from "react-router-dom";
import Navbar from "../components/Navbar";
import Sidebar from "../components/Sidebar";
import Loader from "../components/Loader";
import { BASE_URL } from'./apiConfig';
const Home = () => {
const [loading, setLoading] = useState(true);
const [popularBooks, setPopularBooks] = useState([]);
const [newBooks, setNewBooks] = useState([]);
const [vipBooks, setVipBooks] = useState([]);
const [authors, setAuthors] = useState([]);
const [topBooks, setTopBooks] = useState([]);
useEffect(() => {
fetchBooks();
fetchAuthors();
fetchTopBooks();
}, []);
const fetchBooks = async () => {
try {
const popularResponse = await fetch(
`${BASE_URL}/api/public/books/pagedAndSorted?page=0&size=4&sortBy=views&sortDir=DESC`,
{
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
},
}
);
if (!popularResponse.ok) {
throw new Error("Error fetching popular books");
}
const popularData = await popularResponse.json();
const popularBooksWithRatings = await Promise.all(
popularData.content.map(async (book) => ({
...book,
averageRating: await fetchRating(book.id),
}))
);
setPopularBooks(popularBooksWithRatings);
// Fetch new books
const newResponse = await fetch(
`${BASE_URL}/api/public/books/pagedAndSorted?page=0&size=4&sortBy=createdAt&sortDir=DESC`,
{
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
},
}
);
if (!newResponse.ok) {
throw new Error("Error fetching new books");
}
const newData = await newResponse.json();
const newBooksWithRatings = await Promise.all(
newData.content.map(async (book) => ({
...book,
averageRating: await fetchRating(book.id),
}))
);
setNewBooks(newBooksWithRatings);
// Fetch VIP books
const vipResponse = await fetch(
`${BASE_URL}/api/public/books/pagedAndSorted?page=2&size=4&sortBy=title&sortDir=ASC`,
{
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
},
}
);
if (!vipResponse.ok) {
throw new Error("Error fetching VIP books");
}
const vipData = await vipResponse.json();
const vipBooksWithRatings = await Promise.all(
vipData.content.map(async (book) => ({
...book,
averageRating: await fetchRating(book.id),
}))
);
setVipBooks(vipBooksWithRatings);
setLoading(false);
} catch (error) {
console.error("Error fetching books:", error);
setLoading(false);
}
};
const fetchAuthors = async () => {
try {
const response = await fetch(`${BASE_URL}/api/public/author/getAll`, {
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
},
});
if (!response.ok) {
throw new Error("Error fetching authors");
}
const data = await response.json();
setAuthors(data);
} catch (error) {
console.error("Error fetching authors:", error);
}
};
const fetchTopBooks = async () => {
try {
const response = await fetch(
`${BASE_URL}/api/public/books/pagedAndSorted?sortBy=views&sortDir=DESC&page=0&size=5`,
{
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
},
}
);
if (!response.ok) {
throw new Error("Error fetching top books");
}
const data = await response.json();
const topBooksWithRatings = await Promise.all(
data.content.map(async (book) => ({
...book,
averageRating: await fetchRating(book.id),
}))
);
setTopBooks(topBooksWithRatings);
} catch (error) {
console.error("Error fetching top books:", error);
}
};
const fetchRating = async (bookId) => {
try {
const response = await fetch(
`${BASE_URL}/api/public/review/ave-rat/${bookId}/average-rating`,
{
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
},
}
);
if (!response.ok) {
throw new Error("Error fetching rating");
}
const data = await response.json();
return data.averageRating;
} catch (error) {
console.error(`Error fetching rating for book ${bookId}:`, error);
return null;
}
};
const renderRating = (rating) => {
if (rating === null || rating === undefined) {
return "No rating available";
} else {
const fullStars = Math.floor(rating);
const emptyStars = 5 - fullStars;
return (
<>
{"★".repeat(fullStars)}
{"☆".repeat(emptyStars)}
</>
);
}
};
if (loading) {
return <Loader />;
}
const chunkArray = (arr, size) => {
const chunkedArray = [];
for (let i = 0; i < arr.length; i += size) {
chunkedArray.push(arr.slice(i, i + size));
}
return chunkedArray;
};
return (
<div className="container-home">
<Navbar />
<div className="content-home">
<div className="main">
<Sidebar></Sidebar>
<section className="section-popular">
<div className="section-title">
<h2>Popular Books</h2>
<Link to="/books?sortBy=views&sortDir=DESC" className="see-more">
<span>View All</span>
<FontAwesomeIcon icon={faArrowRight} />
</Link>
</div>
<div className="bookshome-list">
{popularBooks.map((book) => (
<div className="bookshome-item" key={book.id}>
<Link to={`/book/${book.id}`}>
<div className="package-tag-popular">
<p>Popular</p>
</div>
<img src={book.cover} alt={book.title} />
<div className="bookshome-inf">
<h3>{book.title}</h3>
<p className="rating">
{renderRating(book.averageRating)}
</p>
</div>
</Link>
</div>
))}
</div>
</section>
<section className="section-subject">
<div className="section-title">
<h2>Subject Section</h2>
</div>
<div className="grid-container">
<Link to="/books?genre=Novel" className="subject">
Novel
</Link>
<Link to="/books?genre=Self-Development" className="subject">
Self-Development
</Link>
<Link to="/books?genre=Love language" className="subject">
Love language
</Link>
<Link to="/books?genre=Detective" className="subject">
Detective
</Link>
<Link to="/books?genre=Children's Stories" className="subject">
Children's Stories
</Link>
<Link to="/books" className="subject">
Others
</Link>
</div>
</section>
<section className="section-new">
<div className="section-title">
<h2>New Books</h2>
<Link
to="/books?sortBy=createdAt&sortDir=DESC"
className="see-more"
>
<span>View All</span>
<FontAwesomeIcon icon={faArrowRight} />
</Link>
</div>
<div className="bookshome-list">
{newBooks.map((book) => (
<div className="bookshome-item" key={book.id}>
<Link to={`/book/${book.id}`}>
<div className="package-tag-new">
<p>NEW</p>
</div>
<img src={book.cover} alt={book.title} />
<div className="bookshome-inf">
<h3>{book.title}</h3>
<p className="rating">
{renderRating(book.averageRating)}
</p>
</div>
</Link>
</div>
))}
</div>
</section>
<section className="section-vip">
<div className="section-title">
<h2>VIP Books</h2>
<Link to="/authors" className="see-more">
<span>View All</span>
<FontAwesomeIcon icon={faArrowRight} />
</Link>
</div>
<div className="bookshome-list">
{vipBooks.map((book) => (
<div className="bookshome-item" key={book.id}>
<Link to={`/book/${book.id}`}>
<div className="package-tag-vip">
<p>VIP</p>
</div>
<img src={book.cover} alt={book.title} />
<div className="bookshome-inf">
<h3>{book.title}</h3>
<p className="rating">
{renderRating(book.averageRating)}
</p>
</div>
</Link>
</div>
))}
</div>
</section>
</div>
<div className="main-second">
<section className="section-top-books">
<div className="section-title">
<h2>Top 5 Books</h2>
<Link to="/books" className="see-more">
<span>View All</span>
<FontAwesomeIcon icon={faArrowRight} />
</Link>
</div>
<div className="bookshome-list-top">
{topBooks.map((book, index) => (
<div className="bookshome-item-top" key={book.id}>
<div className="book-rank">{index + 1}</div>
<div className="book-cover">
<img src={book.cover} alt={book.title} />
</div>
<div className="book-info">
<h3>{book.title}</h3>
<p className="rating-top">Views: {book.views}</p>
</div>
</div>
))}
</div>
</section>
<section className="section-authors">
<div className="section-title">
<h2>Authors</h2>
<Link to="/authors" className="see-more">
<span>View All</span>
<FontAwesomeIcon icon={faArrowRight} />
</Link>
</div>
<div className="authors-list">
{chunkArray(authors.slice(0, 6), 2).map(
(authorGroup, rowIndex) => (
<div className="author-row" key={rowIndex}>
{authorGroup.map((author) => (
<div key={author.id} className="authorhome-card">
<div className="author-header">
<img
src={author.avatar}
alt={author.fullName}
className="authorhome-image"
/>
<span className="book-count">
<FontAwesomeIcon icon={faBook} /> :{" "}
{author.books.length}
</span>
</div>
<div className="authorhome-info">
<Link className="author-link">{author.fullName}</Link>
</div>
</div>
))}
</div>
)
)}
</div>
</section>
</div>
</div>
<Footer />
</div>
);
};
export default Home;Editor is loading...
Leave a Comment