From 6a59e3aa0ed8491c02c913625aeae7042ef15a5f Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Wed, 11 Aug 2021 08:46:29 +0430 Subject: [PATCH] add search to anime --- src/App.tsx | 5 ++ src/screens/anime/AnimeSearchSingle.tsx | 109 ++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 src/screens/anime/AnimeSearchSingle.tsx diff --git a/src/App.tsx b/src/App.tsx index a98f417c..02a05d42 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -26,6 +26,7 @@ import Categories from 'screens/settings/Categories'; import Backup from 'screens/settings/Backup'; import Library from 'screens/manga/Library'; import SearchSingle from 'screens/manga/SearchSingle'; +import AnimeSearchSingle from 'screens/anime/AnimeSearchSingle'; import SourceConfigure from 'screens/manga/SourceConfigure'; import Manga from 'screens/manga/Manga'; import Anime from 'screens/anime/Anime'; @@ -144,6 +145,10 @@ export default function App() { {/* Anime Routes */} + + + + diff --git a/src/screens/anime/AnimeSearchSingle.tsx b/src/screens/anime/AnimeSearchSingle.tsx new file mode 100644 index 00000000..489f5e1c --- /dev/null +++ b/src/screens/anime/AnimeSearchSingle.tsx @@ -0,0 +1,109 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +import React, { useContext, useEffect, useState } from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import TextField from '@material-ui/core/TextField'; +import Button from '@material-ui/core/Button'; +import { useParams } from 'react-router-dom'; +import AnimeGrid from 'components/anime/AnimeGrid'; +import NavbarContext from 'context/NavbarContext'; +import client from 'util/client'; + +const useStyles = makeStyles((theme) => ({ + root: { + TextField: { + margin: theme.spacing(1), + width: '25ch', + }, + }, +})); + +export default function AnimeSearchSingle() { + const { setTitle, setAction } = useContext(NavbarContext); + useEffect(() => { setTitle('Search'); setAction(<>); }, []); + + const { sourceId } = useParams<{ sourceId: string }>(); + const classes = useStyles(); + const [error, setError] = useState(false); + const [mangas, setMangas] = useState([]); + const [message, setMessage] = useState(''); + const [searchTerm, setSearchTerm] = useState(''); + const [hasNextPage, setHasNextPage] = useState(false); + const [lastPageNum, setLastPageNum] = useState(1); + + const textInput = React.createRef(); + + useEffect(() => { + client.get(`/api/v1/anime/source/${sourceId}`) + .then((response) => response.data) + .then((data: { name: string }) => setTitle(`Search: ${data.name}`)); + }, []); + + function processInput() { + if (textInput.current) { + const { value } = textInput.current; + if (value === '') { + setError(true); + setMessage('Type something to search'); + } else { + setError(false); + setSearchTerm(value); + setMangas([]); + setMessage('loading...'); + } + } + } + + useEffect(() => { + if (searchTerm.length > 0) { + client.get(`/api/v1/anime/source/${sourceId}/search/${searchTerm}/${lastPageNum}`) + .then((response) => response.data) + .then((data: { mangaList: IManga[], hasNextPage: boolean }) => { + setMessage(''); + if (data.mangaList.length > 0) { + setMangas([ + ...mangas, + ...data.mangaList.map((it) => ({ + title: it.title, thumbnailUrl: it.thumbnailUrl, id: it.id, + }))]); + setHasNextPage(data.hasNextPage); + } else { + setMessage('search query returned nothing.'); + } + }); + } + }, [searchTerm]); + + const mangaGrid = ( + + ); + + return ( + <> +
+ e.key === 'Enter' && processInput()} + /> + +
+ {mangaGrid} + + ); +}