summaryrefslogtreecommitdiff
path: root/src/components/layouts/Header.js
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-01-24 15:54:48 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-01-24 15:54:48 +0700
commitee4297280c1305c7e03bedd4df63ccf136c28c6c (patch)
tree62eb00777f42542a37c63687dd1536f8f56df894 /src/components/layouts/Header.js
parent23b31aa10302cc990f3fb083b8189233b2e9e08d (diff)
Merapihkan struktur folder
Diffstat (limited to 'src/components/layouts/Header.js')
-rw-r--r--src/components/layouts/Header.js164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/components/layouts/Header.js b/src/components/layouts/Header.js
new file mode 100644
index 00000000..5cd0a1bc
--- /dev/null
+++ b/src/components/layouts/Header.js
@@ -0,0 +1,164 @@
+import Image from "next/image";
+import { useCallback, useEffect, useRef, useState } from "react";
+import Head from "next/head";
+import { useRouter } from "next/router";
+import axios from "axios";
+import {
+ MagnifyingGlassIcon,
+ Bars3Icon,
+ ShoppingCartIcon,
+ ChevronRightIcon,
+ Cog6ToothIcon
+} from "@heroicons/react/24/outline";
+
+// Helpers
+import { useAuth } from "@/core/utils/auth";
+// Components
+import Link from "../elements/Link";
+// Images
+import Logo from "@/images/logo.png";
+import greeting from "@/core/utils/greeting";
+
+const menus = [
+ { name: 'Semua Brand', href: '/shop/brands' },
+ { name: 'Blog Indoteknik', href: '/' },
+ { name: 'Kategori', href: '/' },
+];
+
+export default function Header({ title }) {
+ const router = useRouter();
+ const { q = '' } = router.query;
+ const [searchQuery, setSearchQuery] = useState(q);
+ const [suggestions, setSuggestions] = useState([]);
+ const searchQueryRef = useRef();
+ const [isMenuActive, setIsMenuActive] = useState(false);
+ const [auth] = useAuth();
+
+ useEffect(() => {
+ if (q) {
+ searchQueryRef.current.blur();
+ setSuggestions([]);
+ };
+ }, [q]);
+
+ const clickSuggestion = (value) => {
+ router.push(`/shop/search?q=${value}`, undefined, { scroll: false });
+ };
+
+ const getSuggestion = useCallback(async () => {
+ if (searchQuery.trim().length > 0) {
+ let result = await axios(`${process.env.SELF_HOST}/api/shop/suggest?q=${searchQuery.trim()}`);
+ setSuggestions(result.data.suggest.mySuggester[searchQuery.trim()].suggestions);
+ } else {
+ setSuggestions([]);
+ }
+ }, [searchQuery]);
+
+ useEffect(() => {
+ if (document.activeElement == searchQueryRef.current) getSuggestion();
+ }, [getSuggestion]);
+
+ const openMenu = () => setIsMenuActive(true);
+ const closeMenu = () => setIsMenuActive(false);
+
+ const searchSubmit = (e) => {
+ e.preventDefault();
+ if (searchQuery.length > 0) {
+ router.push(`/shop/search?q=${searchQuery}`, undefined, { scroll: false });
+ } else {
+ searchQueryRef.current.focus();
+ }
+ }
+
+ return (
+ <>
+ <Head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+ <title>{title}</title>
+ </Head>
+
+ <div className={'menu-wrapper' + (isMenuActive ? ' active ' : '')}>
+ <div className="flex gap-x-2 items-center border-b border-gray_r-6 p-4">
+ { auth && (
+ <Link href="/my/menu" className="w-full flex items-center text-gray_r-12" onClick={closeMenu}>
+ <div>
+ <p className="text-gray_r-11 text-caption-2">{ greeting() },</p>
+ <h1>{auth.name}</h1>
+ </div>
+ <div className="ml-auto">
+ <Cog6ToothIcon className="w-5" />
+ </div>
+ </Link>
+ ) }
+
+ { !auth && (
+ <>
+ <Link href="/login" onClick={closeMenu} className="w-full py-2 btn-light text-gray_r-12">Masuk</Link>
+ <Link href="/register" onClick={closeMenu} className="w-full py-2 btn-yellow text-gray_r-12">Daftar</Link>
+ </>
+ ) }
+ </div>
+ <div className="flex flex-col">
+ { menus.map((menu, index) => (
+ <Link className="flex w-full font-normal text-gray_r-11 border-b border-gray_r-6 p-4" href={menu.href} key={index} onClick={closeMenu}>
+ <span>{ menu.name }</span>
+ <div className="ml-auto">
+ <ChevronRightIcon className="text-gray_r-12 w-5" />
+ </div>
+ </Link>
+ )) }
+ </div>
+ </div>
+ <div className={isMenuActive ? 'menu-overlay block opacity-100' : 'menu-overlay hidden opacity-0'} onClick={closeMenu}></div>
+
+ <div className="sticky-header">
+ <div className="flex justify-between items-center">
+ <Link href="/" scroll={false}>
+ <Image src={Logo} alt="Logo Indoteknik" width={120} height={40} />
+ </Link>
+ <div className="flex gap-x-4">
+ <Link href="/shop/cart">
+ <ShoppingCartIcon className="w-6 text-gray_r-12" />
+ </Link>
+ <button onClick={openMenu}>
+ <Bars3Icon className="w-6 text-gray_r-12" />
+ </button>
+ </div>
+ </div>
+ <form onSubmit={searchSubmit} className="relative flex mt-2">
+ <input
+ ref={searchQueryRef}
+ type="text"
+ name="q"
+ onChange={(e) => setSearchQuery(e.target.value)}
+ onFocus={getSuggestion}
+ value={searchQuery}
+ className="form-input rounded-r-none border-r-0 focus:border-gray_r-7"
+ placeholder="Ketikan nama, merek, part number"
+ autoComplete="off"
+ />
+
+ <button
+ type="submit"
+ aria-label="search"
+ className="btn-light bg-transparent px-2 py-1 rounded-l-none border-l-0"
+ >
+ <MagnifyingGlassIcon className="w-6" />
+ </button>
+
+ {suggestions.length > 1 && (
+ <div className="absolute w-full top-[50px] rounded-b bg-gray_r-2 border border-gray_r-6">
+ {suggestions.map((suggestion, index) => (
+ <p onClick={() => clickSuggestion(suggestion.term)} className="w-full p-2" key={index}>{suggestion.term}</p>
+ ))}
+ </div>
+ )}
+ </form>
+ </div>
+
+ {suggestions.length > 1 && (
+ <div className="menu-overlay !z-40" onClick={() => setSuggestions([])}></div>
+ )}
+ </>
+ )
+} \ No newline at end of file