diff options
| author | Factiven <[email protected]> | 2023-05-16 22:40:02 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-16 22:40:02 +0700 |
| commit | 9a5754fdba9d778f820fe89b44d1e21ca9f0bb4d (patch) | |
| tree | 8bd574163e760216bc91f7b3c164232b6982efe8 /components/searchBar.js | |
| parent | Update v3.5.6 (diff) | |
| download | moopa-9a5754fdba9d778f820fe89b44d1e21ca9f0bb4d.tar.xz moopa-9a5754fdba9d778f820fe89b44d1e21ca9f0bb4d.zip | |
Update v3.5.7 (#12)
* Merge request (#11)
* Update v3.5.5
> Now Skip button will hide if player is not in focused state.
> Added some options to player.
> Manga images should be displayed now.
* Update videoPlayer.js
* Revamp hero section #1
* UI Improvement
> Updating main page
> Updated Genres selection using params method
> Added search bar v1.0 on main page ( [ctrl + space] to access search bar )
* update meta
* Update [...id].js
* Update [...id].js
> Back to ssr I guess
* update episode selector
* Update [...info].js
* Update UI
> Added On-Going section for AniList user
* Update content.js
* added dynamic og
* Update og.jsx
* Update og
* Update og.jsx
* update og and id fallback
> Added fallback for anime info if it's not found
* Update v3.5.7
> Added On-Going section for AniList user
> Added Genre section
> Added dynamic Open Graph when sharing anime
> Added Episode Selector above information
Diffstat (limited to 'components/searchBar.js')
| -rw-r--r-- | components/searchBar.js | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/components/searchBar.js b/components/searchBar.js new file mode 100644 index 0000000..35e9b45 --- /dev/null +++ b/components/searchBar.js @@ -0,0 +1,144 @@ +import { useState, useEffect, useRef } from "react"; +import { motion as m, AnimatePresence } from "framer-motion"; +import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; +import { useAniList } from "../lib/useAnilist"; +import Image from "next/image"; +import Link from "next/link"; +import { useRouter } from "next/router"; + +const SearchBar = () => { + const [isOpen, setIsOpen] = useState(false); + const searchBoxRef = useRef(null); + + const router = useRouter(); + + const { aniAdvanceSearch } = useAniList(); + const [data, setData] = useState(null); + const [query, setQuery] = useState(""); + + useEffect(() => { + if (isOpen) { + searchBoxRef.current.querySelector("input").focus(); + } + const handleKeyDown = (e) => { + if (e.ctrlKey && e.code === "Space") { + setIsOpen((prev) => !prev); + setData(null); + setQuery(""); + } + }; + + document.addEventListener("keydown", handleKeyDown); + + const handleClick = (e) => { + if (searchBoxRef.current && !searchBoxRef.current.contains(e.target)) { + setIsOpen(false); + } + }; + document.addEventListener("click", handleClick); + + return () => { + document.removeEventListener("keydown", handleKeyDown); + document.removeEventListener("click", handleClick); + }; + }, [isOpen]); + + async function search() { + const data = await aniAdvanceSearch({ + search: query, + type: "ANIME", + perPage: 10, + }); + setData(data); + } + + useEffect(() => { + if (query) { + search(); + } + }, [query]); + + function handleSubmit(e) { + e.preventDefault(); + if (data?.media.length) { + router.push(`/anime/${data?.media[0].id}`); + } + } + + return ( + <AnimatePresence> + {isOpen && ( + <m.div + initial={{ opacity: 0, y: -100 }} + animate={{ opacity: 1, y: 0 }} + exit={{ opacity: 0, y: -100 }} + className="fixed top-0 w-screen flex justify-center z-50" + > + <div + ref={searchBoxRef} + className={` bg-[#1c1c1fef] text-white p-4 ${ + isOpen ? "flex" : "hidden" + } flex-col w-[80%] backdrop-blur-sm rounded-b-lg`} + > + <form onSubmit={handleSubmit}> + <input + type="text" + className="w-full rounded-lg px-4 py-2 mb-2 bg-[#474747]" + placeholder="Search..." + onChange={(e) => setQuery(e.target.value)} + /> + </form> + <div className="flex flex-col gap-2 p-2 font-karla"> + {data?.media.map((i) => ( + <Link + key={i.id} + href={i.type === "ANIME" ? `/anime/${i.id}` : `/`} + className="flex hover:bg-[#3e3e3e] rounded-md" + > + <Image + src={i.coverImage.extraLarge} + alt="search results" + width={500} + height={500} + className="object-cover w-14 h-14 rounded-md" + /> + <div className="flex items-center justify-between w-full px-5"> + <div> + <h1>{i.title.userPreferred}</h1> + <h5 className="text-sm font-light text-[#878787] flex gap-2"> + {i.status + ?.toLowerCase() + .replace(/^\w/, (c) => c.toUpperCase())}{" "} + {i.status && i.season && <>·</>}{" "} + {i.season + ?.toLowerCase() + .replace(/^\w/, (c) => c.toUpperCase())}{" "} + {(i.status || i.season) && i.episodes && <>·</>}{" "} + {i.episodes || 0} Episodes + </h5> + </div> + <div className="text-sm text-[#b5b5b5] "> + <h1> + {i.type + ?.toLowerCase() + .replace(/^\w/, (c) => c.toUpperCase())} + </h1> + </div> + </div> + </Link> + ))} + </div> + {query && ( + <button className="flex items-center gap-2 justify-center"> + <MagnifyingGlassIcon className="h-5 w-5" /> + <Link href={`/search/${query}`}>More Results...</Link> + </button> + )} + </div> + </m.div> + )} + </AnimatePresence> + ); +}; + +export default SearchBar; |