From 5b8f1c8e6ced54a8d4becfd84a952e7c6abd0fd7 Mon Sep 17 00:00:00 2001 From: SoSmoothy <58429050+sonicname@users.noreply.github.com> Date: Tue, 23 Aug 2022 04:56:44 +0700 Subject: [PATCH] fix loading, refactor code, add icon title --- assets/otaku.ico | Bin 0 -> 19029 bytes index.html | 3 +- .../anime-details/DetailListItem.jsx | 4 +- src/components/anime-details/DetailStatus.jsx | 4 +- src/components/anime/AnimeItem.jsx | 3 +- src/components/anime/AnimeItemSkeleton.jsx | 3 +- src/components/anime/AnimeList.jsx | 3 +- src/components/buttons/Button.jsx | 4 +- src/components/character/CharacterItem.jsx | 4 +- .../character/CharacterItemSkeleton.jsx | 3 +- src/components/character/CharacterList.jsx | 33 ------ src/components/header/HeaderHamburger.jsx | 4 +- src/components/header/HeaderLink.jsx | 5 +- src/components/icons/IconEmail.jsx | 4 +- src/components/icons/IconFavorite.jsx | 4 +- src/components/icons/IconPhone.jsx | 4 +- src/components/icons/IconRank.jsx | 4 +- src/components/icons/IconStar.jsx | 4 +- src/components/icons/IconUserGroup.jsx | 4 +- src/components/index.jsx | 48 ++++++++ src/components/layout/Footer.jsx | 3 +- src/components/layout/Header.jsx | 4 +- src/components/layout/ShareLayout.jsx | 3 +- src/components/loading/LoadingComponent.jsx | 4 +- src/components/loading/LoadingSkeleton.jsx | 4 +- src/components/search/SearchContainer.jsx | 107 ----------------- src/main.jsx | 11 +- src/page/AnimeDetailPage.jsx | 17 +-- src/page/AnimePage.jsx | 2 +- src/page/CharacterDetailPage.jsx | 6 +- src/page/CharacterPage.jsx | 7 -- src/page/Error404Page.jsx | 3 +- src/page/SearchPage.jsx | 112 +++++++++++++++++- src/utils/fetcher.jsx | 1 - src/utils/request.jsx | 0 35 files changed, 233 insertions(+), 196 deletions(-) create mode 100644 assets/otaku.ico delete mode 100644 src/components/character/CharacterList.jsx create mode 100644 src/components/index.jsx delete mode 100644 src/components/search/SearchContainer.jsx delete mode 100644 src/page/CharacterPage.jsx delete mode 100644 src/utils/fetcher.jsx delete mode 100644 src/utils/request.jsx diff --git a/assets/otaku.ico b/assets/otaku.ico new file mode 100644 index 0000000000000000000000000000000000000000..194aa28b78f8a932dc725c468f2355cbdfbba6d0 GIT binary patch literal 19029 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 X - Anime Website + + Anime, Manga Information Page
diff --git a/src/components/anime-details/DetailListItem.jsx b/src/components/anime-details/DetailListItem.jsx index df5846d..d0998f0 100644 --- a/src/components/anime-details/DetailListItem.jsx +++ b/src/components/anime-details/DetailListItem.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import { memo } from "react"; import { NavLink } from "react-router-dom"; const DetailListItem = ({ items, title }) => { @@ -18,4 +18,4 @@ const DetailListItem = ({ items, title }) => { ); }; -export default DetailListItem; +export default memo(DetailListItem); diff --git a/src/components/anime-details/DetailStatus.jsx b/src/components/anime-details/DetailStatus.jsx index 3a7f168..27e21b4 100644 --- a/src/components/anime-details/DetailStatus.jsx +++ b/src/components/anime-details/DetailStatus.jsx @@ -1,3 +1,5 @@ +import { memo } from "react"; + const DetailStatus = ({ type, content, className }) => { return ( @@ -7,4 +9,4 @@ const DetailStatus = ({ type, content, className }) => { ); }; -export default DetailStatus; +export default memo(DetailStatus); diff --git a/src/components/anime/AnimeItem.jsx b/src/components/anime/AnimeItem.jsx index f55630d..2f3d695 100644 --- a/src/components/anime/AnimeItem.jsx +++ b/src/components/anime/AnimeItem.jsx @@ -2,6 +2,7 @@ import { useNavigate } from "react-router-dom"; import IconStar from "../icons/IconStar"; import IconFavorite from "../icons/IconFavorite"; import Button from "../buttons/Button"; +import { memo } from "react"; const AnimeItem = ({ anime }) => { const navigate = useNavigate(); @@ -39,4 +40,4 @@ const AnimeItem = ({ anime }) => { ); }; -export default AnimeItem; +export default memo(AnimeItem); diff --git a/src/components/anime/AnimeItemSkeleton.jsx b/src/components/anime/AnimeItemSkeleton.jsx index ea45120..b932642 100644 --- a/src/components/anime/AnimeItemSkeleton.jsx +++ b/src/components/anime/AnimeItemSkeleton.jsx @@ -1,6 +1,7 @@ import IconStar from "../icons/IconStar"; import IconFavorite from "../icons/IconFavorite"; import LoadingSkeleton from "../loading/LoadingSkeleton"; +import { memo } from "react"; const AnimeItemSkeleton = () => { return ( @@ -31,4 +32,4 @@ const AnimeItemSkeleton = () => { ); }; -export default AnimeItemSkeleton; +export default memo(AnimeItemSkeleton); diff --git a/src/components/anime/AnimeList.jsx b/src/components/anime/AnimeList.jsx index 8ea0fed..9193e93 100644 --- a/src/components/anime/AnimeList.jsx +++ b/src/components/anime/AnimeList.jsx @@ -5,6 +5,7 @@ import { getListAnime } from "../../apis/apis"; import { useQuery } from "@tanstack/react-query"; import { toast } from "react-toastify"; import { useNavigate } from "react-router-dom"; +import { memo } from "react"; const AnimeList = ({ type }) => { const { data, isError, isLoading } = useQuery(["list-anime", type], () => @@ -39,4 +40,4 @@ const AnimeList = ({ type }) => { ); }; -export default AnimeList; +export default memo(AnimeList); diff --git a/src/components/buttons/Button.jsx b/src/components/buttons/Button.jsx index 521b18f..542ca8b 100644 --- a/src/components/buttons/Button.jsx +++ b/src/components/buttons/Button.jsx @@ -1,3 +1,5 @@ +import { memo } from "react"; + const Button = ({ className = "", onClick = () => {}, children }) => { return ( - - -
- {isLoading && ( -
- {new Array(4).fill(0).map(() => ( - - ))} -
- )} - -
- {!isLoading && - data.pages.map((pageData) => - pageData.data.map((item) => ( - <> - {type === "anime" ? ( - - ) : ( - - )} - - )) - )} -
-
-
- - - ); -}; - -export default SearchContainer; diff --git a/src/main.jsx b/src/main.jsx index 49b4372..a5a0c05 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,7 +1,7 @@ import { render } from "react-dom"; import { lazy, Suspense } from "react"; +import { ToastContainer } from "react-toastify"; import { BrowserRouter, Route, Routes } from "react-router-dom"; - import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import LoadingComponent from "./components/loading/LoadingComponent"; @@ -11,14 +11,12 @@ const HomePage = lazy(() => import("./page/HomePage")); const AnimePage = lazy(() => import("./page/AnimePage")); const SearchPage = lazy(() => import("./page/SearchPage")); const AnimeDetailPage = lazy(() => import("./page/AnimeDetailPage")); -const CharacterPage = lazy(() => import("./page/CharacterPage")); const CharacterDetailPage = lazy(() => import("./page/CharacterDetailPage")); const Error404Page = lazy(() => import("./page/Error404Page")); import "swiper/css"; import "react-toastify/dist/ReactToastify.css"; import "./index.scss"; -import { ToastContainer } from "react-toastify"; const queryClient = new QueryClient(); @@ -31,12 +29,15 @@ render( } /> } /> } /> - } /> + } + /> } /> - } /> + } /> } /> diff --git a/src/page/AnimeDetailPage.jsx b/src/page/AnimeDetailPage.jsx index d36d5bb..3fb749b 100644 --- a/src/page/AnimeDetailPage.jsx +++ b/src/page/AnimeDetailPage.jsx @@ -1,17 +1,18 @@ import { useNavigate, useParams } from "react-router-dom"; -import DetailStatus from "../components/anime-details/DetailStatus"; -import IconStar from "../components/icons/IconStar"; -import IconUserGroup from "../components/icons/IconUserGroup"; -import IconFavorite from "../components/icons/IconFavorite"; -import IconRank from "../components/icons/IconRank"; - import { getRating } from "../utils/getRating"; -import DetailListItem from "../components/anime-details/DetailListItem"; -import LoadingComponent from "../components/loading/LoadingComponent"; import { useQuery } from "@tanstack/react-query"; import { getAnimeDetail } from "../apis/apis"; import { toast } from "react-toastify"; +import { + DetailListItem, + DetailStatus, + IconFavorite, + IconRank, + IconStar, + IconUserGroup, + LoadingComponent, +} from "../components"; const AnimeDetailPage = () => { const { animeID } = useParams(); diff --git a/src/page/AnimePage.jsx b/src/page/AnimePage.jsx index 3a1f268..9882118 100644 --- a/src/page/AnimePage.jsx +++ b/src/page/AnimePage.jsx @@ -1,4 +1,4 @@ -import AnimeList from "../components/anime/AnimeList"; +import { AnimeList } from "../components"; const AnimePage = () => { return ( diff --git a/src/page/CharacterDetailPage.jsx b/src/page/CharacterDetailPage.jsx index 36c81e5..71d782c 100644 --- a/src/page/CharacterDetailPage.jsx +++ b/src/page/CharacterDetailPage.jsx @@ -1,11 +1,9 @@ import { useNavigate, useParams } from "react-router-dom"; import { useQuery } from "@tanstack/react-query"; +import { toast } from "react-toastify"; -import IconFavorite from "../components/icons/IconFavorite"; -import IconEmail from "../components/icons/IconEmail"; -import LoadingComponent from "../components/loading/LoadingComponent"; import { getCharacterDetail } from "../apis/apis"; -import { toast } from "react-toastify"; +import { IconEmail, IconFavorite, LoadingComponent } from "../components"; const CharacterDetailPage = () => { const navigate = useNavigate(); diff --git a/src/page/CharacterPage.jsx b/src/page/CharacterPage.jsx deleted file mode 100644 index 595751e..0000000 --- a/src/page/CharacterPage.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import SearchContainer from "../components/search/SearchContainer"; - -const CharacterPage = () => { - return ; -}; - -export default CharacterPage; diff --git a/src/page/Error404Page.jsx b/src/page/Error404Page.jsx index 5fac6bb..fb99ea5 100644 --- a/src/page/Error404Page.jsx +++ b/src/page/Error404Page.jsx @@ -1,6 +1,7 @@ import { useNavigate } from "react-router-dom"; -import Button from "../components/buttons/Button"; + import errorImg from "../images/404.png"; +import { Button } from "../components"; const Error404Page = () => { const navigate = useNavigate(); diff --git a/src/page/SearchPage.jsx b/src/page/SearchPage.jsx index d602476..57d6053 100644 --- a/src/page/SearchPage.jsx +++ b/src/page/SearchPage.jsx @@ -1,7 +1,113 @@ -import SearchContainer from "../components/search/SearchContainer"; +import { v4 } from "uuid"; +import { toast } from "react-toastify"; +import { useNavigate } from "react-router-dom"; +import { useEffect, useRef, useState } from "react"; +import InfiniteScroll from "react-infinite-scroller"; +import { useInfiniteQuery } from "@tanstack/react-query"; -const SearchPage = () => { - return ; +import { search } from "../apis/apis"; +import { AnimeItem, AnimeItemSkeleton, CharacterItem } from "../components"; + +const SearchPage = ({ type }) => { + const navigate = useNavigate(); + const [query, setQuery] = useState("naruto"); + const inputRef = useRef(null); + const searchBtnRef = useRef(null); + + const url = `https://api.jikan.moe/v4/${type}?q=${query}`; + + const { + data, + hasNextPage, + fetchNextPage, + isError, + isLoading, + isFetchingNextPage, + } = useInfiniteQuery( + [`search-${type}`, query], + ({ pageParam = url }) => search(pageParam), + { + getNextPageParam: (lastPage, _) => + lastPage.pagination.has_next_page + ? `${url}&page=${lastPage.pagination.current_page + 1}` + : undefined, + } + ); + + if (isError) { + toast.error("Something went wrong! Please try again!"); + return navigate("/"); + } + + useEffect(() => { + const handlerEnterKeyPress = (e) => { + if (e.code === "Enter") { + setQuery(inputRef.current.value); + } + }; + + document.addEventListener("keyup", handlerEnterKeyPress); + + return () => { + document.removeEventListener("keyup", handlerEnterKeyPress); + }; + }, []); + + return ( +
+
+
+ + +
+ +
+ {isLoading && ( +
+ {new Array(4).fill(0).map(() => ( + + ))} +
+ )} + +
+ {!isLoading && + data.pages.map((pageData) => + pageData.data.map((item) => ( + <> + {type === "anime" ? ( + + ) : ( + + )} + + )) + )} + {isFetchingNextPage && ( + <> + {new Array(4).fill(0).map(() => ( + + ))} + + )} +
+
+
+
+
+ ); }; export default SearchPage; diff --git a/src/utils/fetcher.jsx b/src/utils/fetcher.jsx deleted file mode 100644 index 3c44991..0000000 --- a/src/utils/fetcher.jsx +++ /dev/null @@ -1 +0,0 @@ -export const fetcher = (...args) => fetch(...args).then((res) => res.json()); diff --git a/src/utils/request.jsx b/src/utils/request.jsx deleted file mode 100644 index e69de29..0000000