2
unknown
plain_text
a month ago
13 kB
2
Indexable
Never
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 "../server/Endpoint"; 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;
Leave a Comment