diff options
Diffstat (limited to 'src/core/components/elements')
| -rw-r--r-- | src/core/components/elements/Navbar/Navbar.jsx | 36 | ||||
| -rw-r--r-- | src/core/components/elements/Navbar/Search.jsx | 89 |
2 files changed, 125 insertions, 0 deletions
diff --git a/src/core/components/elements/Navbar/Navbar.jsx b/src/core/components/elements/Navbar/Navbar.jsx new file mode 100644 index 00000000..e7f447eb --- /dev/null +++ b/src/core/components/elements/Navbar/Navbar.jsx @@ -0,0 +1,36 @@ +import Image from "next/image" +import IndoteknikLogo from "@/images/logo.png" +import { Bars3Icon, HeartIcon, ShoppingCartIcon } from "@heroicons/react/24/outline" +import Link from "../Link/Link" +import Search from "./Search" +import useSidebar from "@/core/hooks/useSidebar" + +const Navbar = () => { + const { Sidebar, open } = useSidebar() + return ( + <> + <nav className="px-4 py-2 pb-3 sticky top-0 z-50 bg-white shadow"> + <div className="flex justify-between items-center mb-2"> + <Link href="/"> + <Image src={IndoteknikLogo} alt="Indoteknik Logo" width={120} height={40} /> + </Link> + <div className="flex gap-x-3"> + <button type="button"> + <HeartIcon className="w-6 text-gray_r-12" /> + </button> + <Link href="/shop/cart"> + <ShoppingCartIcon className="w-6 text-gray_r-12" /> + </Link> + <button type="button" onClick={open}> + <Bars3Icon className="w-6 text-gray_r-12" /> + </button> + </div> + </div> + <Search /> + </nav> + { Sidebar } + </> + ) +} + +export default Navbar
\ No newline at end of file diff --git a/src/core/components/elements/Navbar/Search.jsx b/src/core/components/elements/Navbar/Search.jsx new file mode 100644 index 00000000..cca1a97c --- /dev/null +++ b/src/core/components/elements/Navbar/Search.jsx @@ -0,0 +1,89 @@ +import searchSuggestApi from "@/core/api/searchSuggestApi" +import { MagnifyingGlassIcon } from "@heroicons/react/24/outline" +import { useCallback, useEffect, useRef, useState } from "react" +import Link from "../Link/Link" +import { useRouter } from "next/router" + +const Search = () => { + const router = useRouter() + const queryRef = useRef() + const [ query, setQuery ] = useState('') + const [ suggestions, setSuggestions ] = useState([]) + + useEffect(() => { + setQuery(router.query.q) + }, [router.query]) + + const loadSuggestion = useCallback(() => { + if (query && document.activeElement == queryRef.current) { + (async () => { + const dataSuggestion = await searchSuggestApi({ query }) + setSuggestions(dataSuggestion.data.suggestions) + })() + return + } else { + setSuggestions([]) + } + }, [ query ]) + + useEffect(() => { + if (query && document.activeElement == queryRef.current) { + loadSuggestion() + } else { + setSuggestions([]) + } + }, [ loadSuggestion, query ]) + + const handleSubmit = (e) => { + e.preventDefault() + if (query) { + router.push(`/shop/search?q=${query}`) + } else { + queryRef.current.focus() + } + } + + const onInputBlur = () => { + setTimeout(() => { + setSuggestions([]) + }, 100) + } + + return ( + <form + onSubmit={handleSubmit} + className="flex relative" + > + <input + type="text" + ref={queryRef} + className="form-input p-3 rounded-r-none border-r-0 focus:border-gray_r-6" + placeholder="Ketik nama, part number, merk" + value={query} + onChange={(e) => setQuery(e.target.value)} + onBlur={onInputBlur} + onFocus={loadSuggestion} + /> + <button + type="submit" + className="rounded-r border border-l-0 border-gray_r-6 px-2" + > + <MagnifyingGlassIcon className="w-6" /> + </button> + + { suggestions.length > 1 && ( + <> + <div className="absolute w-full top-[50px] rounded-b bg-gray_r-1 border border-gray_r-6 divide-y divide-gray_r-6"> + {suggestions.map((suggestion, index) => ( + <Link href={`/shop/search?q=${suggestion.term}`} key={index} className="px-3 py-3 !text-gray_r-12 font-normal"> + {suggestion.term} + </Link> + ))} + </div> + </> + ) } + </form> + ) +} + +export default Search
\ No newline at end of file |
