summaryrefslogtreecommitdiff
path: root/src/core/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/components')
-rw-r--r--src/core/components/elements/Footer/BasicFooter.jsx2
-rw-r--r--src/core/components/elements/Footer/PromoOffer.tsx112
-rw-r--r--src/core/components/elements/Footer/style/promoOffer.module.css39
-rw-r--r--src/core/components/elements/Navbar/NavbarDesktop.jsx161
-rw-r--r--src/core/components/elements/Navbar/NavbarMobile.jsx4
-rw-r--r--src/core/components/elements/Navbar/TopBanner.jsx40
-rw-r--r--src/core/components/elements/Navbar/style/NavbarDesktop.module.css14
-rw-r--r--src/core/components/elements/Sidebar/Sidebar.jsx7
-rw-r--r--src/core/components/layouts/BasicLayout.jsx2
9 files changed, 327 insertions, 54 deletions
diff --git a/src/core/components/elements/Footer/BasicFooter.jsx b/src/core/components/elements/Footer/BasicFooter.jsx
index 6129143d..4beea604 100644
--- a/src/core/components/elements/Footer/BasicFooter.jsx
+++ b/src/core/components/elements/Footer/BasicFooter.jsx
@@ -259,7 +259,7 @@ const InformationCenter = () => (
<li className='text-gray_r-12/80 flex items-center'>
<PhoneArrowUpRightIcon className='w-[18px] mr-2' />
<a href='tel:02129338828' target='_blank' rel='noreferrer'>
- (021) 2933-8828 / 29
+ (021) 2933-8828
</a>
</li>
<li className='text-gray_r-12/80 flex items-center'>
diff --git a/src/core/components/elements/Footer/PromoOffer.tsx b/src/core/components/elements/Footer/PromoOffer.tsx
new file mode 100644
index 00000000..a5432b6a
--- /dev/null
+++ b/src/core/components/elements/Footer/PromoOffer.tsx
@@ -0,0 +1,112 @@
+
+import React from "react";
+// import { useGeneralSetting } from "@/common/state-management/general-setting";
+import { FormEvent, useEffect, useState } from "react";
+import toast from "react-hot-toast";
+import style from "../Footer/style/promoOffer.module.css"
+const PromoOffer = ()=>{
+ // const { data, isLoading, fetchData } = useGeneralSetting();
+ const [formData, setFormData] = useState<FormData>({
+ email: "",
+ name: "",
+ telephone: "",
+ message: "",
+ });
+
+ useEffect(() => {
+ // fetchData();
+ }, []);
+
+ type FormData = {
+ email: string;
+ name: string;
+ telephone: string;
+ message: string;
+ };
+
+ const [errors, setErrors] = useState({
+ email: false,
+ name: false,
+ message: false,
+ });
+
+
+const handleGetOffer = async (e: FormEvent) => {
+ e.preventDefault();
+ let loadingToast;
+ try {
+ loadingToast = toast.loading("Mengirimkan formulir...");
+ const response = await fetch("/api/contactus", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ ...formData, from: "newsletter" }),
+ });
+
+ if (response.ok) {
+ toast.dismiss(loadingToast);
+ toast.success("Terima kasih telah menghubungi kami");
+ setFormData({
+ email: "",
+ name: "",
+ telephone: "",
+ message: "",
+ });
+ } else {
+ toast.dismiss(loadingToast);
+ toast.error("Gagal mengirimkan formulir. Silakan coba lagi nanti.");
+ }
+ } catch (error) {
+ toast.dismiss(loadingToast);
+ console.error("Gagal mengirimkan formulir", error);
+ toast.error("Terjadi kesalahan. Silakan coba lagi nanti.");
+ }
+ };
+
+
+
+
+ return(
+ <div className=" py-3 mb-3">
+ <div className="md:flex container mx-auto md:justify-between md:items-center md:gap-x-20">
+ <div className="">
+ <span className="text-black font-semibold text-sm md:text-lg">
+ Dapatkan Promo Menarik Setiap Bulan{" "}
+ </span>
+ <p>
+ Promo produk dengan penawaran terbatas setiap bulannya!
+ </p>
+ </div>
+ <div className=" flex-1 flex items-center h-full justify-end text-sm text-slate-950">
+ <form onSubmit={handleGetOffer} className={style['form-input']}>
+ <div className="flex justify-start w-full">
+ <div className="flex justify-end">
+ <input
+ type="email"
+ value={formData.email}
+ onChange={(e) =>
+ setFormData({ ...formData, email: e.target.value })
+ }
+ className={style['input']}
+ placeholder="Masukkan email anda disini"
+ />
+ <button
+ type="submit"
+ className={style['button']}
+ >
+ Dapatkan
+ </button>
+ </div>
+
+
+ </div>
+ </form>
+
+ </div>
+ </div>
+ </div>
+ )
+ };
+
+ export default PromoOffer;
diff --git a/src/core/components/elements/Footer/style/promoOffer.module.css b/src/core/components/elements/Footer/style/promoOffer.module.css
new file mode 100644
index 00000000..3184182d
--- /dev/null
+++ b/src/core/components/elements/Footer/style/promoOffer.module.css
@@ -0,0 +1,39 @@
+.form-input {
+ @apply
+ h-full
+ w-[514px]
+ text-slate-950
+ flex
+ justify-center;
+}
+
+.input{
+ @apply w-[320px]
+ sm:w-[320px]
+ md:w-[500px]
+ xl:w-[514px]
+ lg:w-[514px]
+ 2xl:w-[514px]
+ text-black
+ py-2
+ h-11
+ md:py-3
+ px-4
+ bg-[#FDF1C7]
+ rounded-3xl
+ focus:outline-none
+ ;
+}
+
+.button{
+ @apply bg-[#FAD147]
+ absolute
+ py-1.5
+ rounded-3xl
+ text-black
+ md:py-2.5
+ px-4
+ h-11
+ z-0
+ ;
+} \ No newline at end of file
diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx
index 9de761a2..6454c414 100644
--- a/src/core/components/elements/Navbar/NavbarDesktop.jsx
+++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx
@@ -5,16 +5,19 @@ import { createSlug } from '@/core/utils/slug';
import whatsappUrl from '@/core/utils/whatsappUrl';
import IndoteknikLogo from '@/images/logo.png';
import Cardheader from '@/lib/cart/components/Cartheader';
+import Quotationheader from "../../../../../src/lib/quotation/components/Quotationheader.jsx"
import Category from '@/lib/category/components/Category';
+import { useProductCartContext } from '@/contexts/ProductCartContext';
import {
ChevronDownIcon,
DocumentCheckIcon,
HeartIcon,
+ ArrowUpRightIcon,
} from '@heroicons/react/24/outline';
import dynamic from 'next/dynamic';
import Image from 'next/image';
import { useRouter } from 'next/router';
-import { useEffect, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
import DesktopView from '../../views/DesktopView';
import Link from '../Link/Link';
import NavbarUserDropdown from './NavbarUserDropdown';
@@ -27,6 +30,8 @@ import {
MenuList,
useDisclosure,
} from '@chakra-ui/react';
+import style from "./style/NavbarDesktop.module.css";
+import useTransactions from '@/lib/transaction/hooks/useTransactions';
const Search = dynamic(() => import('./Search'), { ssr: false });
const TopBanner = dynamic(() => import('./TopBanner'), { ssr: false });
@@ -36,7 +41,8 @@ const NavbarDesktop = () => {
const auth = useAuth();
const [cartCount, setCartCount] = useState(0);
-
+ const [quotationCount, setQuotationCount] = useState(0);
+ const [pendingTransactions, setPendingTransactions] = useState([])
const [templateWA, setTemplateWA] = useState(null);
const [payloadWA, setPayloadWa] = useState(null);
const [urlPath, setUrlPath] = useState(null);
@@ -45,8 +51,64 @@ const NavbarDesktop = () => {
const { product } = useProductContext();
const { isOpen, onOpen, onClose } = useDisclosure();
+
+ const query = {
+ context: 'quotation',
+ site:
+ (auth?.webRole === null && auth?.site ? auth.site : null),
+ };
+
+ const { transactions } = useTransactions({ query });
+ const data = transactions?.data?.saleOrders.filter(
+ (transaction) => transaction.status === 'draft'
+ );
+
+ const [showPopup, setShowPopup] = useState(false);
+ const [isTop, setIsTop] = useState(true);
+
+ const handleTopBannerLoad = useCallback(() => {
+ const showTimer = setTimeout(() => {
+ setShowPopup(true);
+ }, 500);
+
+ const hideTimer = setTimeout(() => {
+ // setShowPopup(false);
+ }, 9500);
+
+ return () => {
+ clearTimeout(showTimer);
+ clearTimeout(hideTimer);
+ };
+ }, []);
+
+ useEffect(() => {
+ const handleScroll = () => {
+ setIsTop(window.scrollY < 100);
+ };
+
+ window.addEventListener('scroll', handleScroll);
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ };
+ }, []);
+
+ useEffect(() => {
+ const handleScroll = () => {
+ setIsTop(window.scrollY < 100);
+ };
+
+ window.addEventListener('scroll', handleScroll);
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ };
+ }, []);
useEffect(() => {
+ setPendingTransactions(data);
+ }, [transactions.data]);
+
+
+ useEffect(() => {
if (router.pathname === '/shop/product/[slug]') {
setPayloadWa({
name: product?.name,
@@ -54,11 +116,11 @@ const NavbarDesktop = () => {
url: createSlug('/shop/product/', product?.name, product?.id, true),
});
setTemplateWA('product');
-
+
setUrlPath(router.asPath);
}
}, [product, router]);
-
+
useEffect(() => {
const handleCartChange = () => {
const cart = async () => {
@@ -67,18 +129,34 @@ const NavbarDesktop = () => {
};
cart();
};
- handleCartChange();
-
+ handleCartChange();
+
window.addEventListener('localStorageChange', handleCartChange);
-
+
return () => {
window.removeEventListener('localStorageChange', handleCartChange);
};
}, []);
+ useEffect(() => {
+ const handleQuotationChange = () => {
+ const quotation = async () => {
+ setQuotationCount(pendingTransactions?.length);
+ };
+ quotation();
+ };
+ handleQuotationChange();
+
+ window.addEventListener('localStorageChange', handleQuotationChange);
+
+ return () => {
+ window.removeEventListener('localStorageChange', handleQuotationChange);
+ };
+ }, [pendingTransactions]);
+
return (
<DesktopView>
- <TopBanner />
+ <TopBanner onLoad={handleTopBannerLoad} />
<div className='py-2 bg-warning-400' id='desktop-nav-top'>
<div className='container mx-auto flex justify-between'>
<div className='flex items-start gap-5'>
@@ -138,17 +216,7 @@ const NavbarDesktop = () => {
<Search />
</div>
<div className='flex gap-x-4 items-center'>
- <Link
- href='/my/transactions'
- target='_blank'
- rel='noreferrer'
- className='flex items-center gap-x-2 !text-gray_r-12/80'
- >
- <DocumentCheckIcon className='w-7' />
- Daftar
- <br />
- Quotation
- </Link>
+ <Quotationheader quotationCount={quotationCount} data={pendingTransactions} />
<Cardheader cartCount={cartCount} />
@@ -203,45 +271,76 @@ const NavbarDesktop = () => {
</div>
</button>
<div className='w-6/12 flex px-1 divide-x divide-gray_r-6'>
+
+ <Link
+ href="/shop/promo"
+ className={`${
+ router.asPath === '/shop/promo' && 'bg-gray_r-3'
+ } flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition group relative`} // Added relative position
+ target="_blank"
+ rel="noreferrer"
+ >
+ {showPopup && (
+ <div className='w-full h-full relative justify-end items-start'>
+ <Image
+ src='/images/penawaran-terbatas.jpg'
+ alt='penawaran terbatas'
+ width={1440}
+ height={160}
+ quality={100}
+ // className={`fixed ${isTop ? 'md:top-[145px] lg:top-[160px] ' : 'lg:top-[85px] top-[80px]'} rounded-3xl md:left-1/4 lg:left-1/4 xl:left-1/4 left-2/3 w-40 h-12 p-2 z-50 transition-all duration-300 animate-pulse`}
+ className={`inline-block relative -top-8 transition-all duration-300 z-20 animate-pulse`}
+ />
+ </div>
+ )}
+ <p className="absolute inset-0 flex justify-center items-center group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200 z-10">Semua Promo</p>
+ </Link>
+ {/* {showPopup && router.pathname === '/' && (
+ <div className={`fixed ${isTop ? 'top-[170px]' : 'top-[90px]'} rounded-3xl left-[700px] w-fit object-center bg-green-50 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20 text-center p-2 z-50 transition-all duration-300`}>
+ <p className='w-36 h-3'>
+ Penawaran Terbatas
+ </p>
+ </div>
+ )} */}
+
+
<Link
href='/shop/brands'
- className={`${
+ className={`${
router.asPath === '/shop/brands' && 'bg-gray_r-3'
- } p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition`}
+ } p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition group`}
target='_blank'
rel='noreferrer'
>
- Semua Brand
+ <p className="group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200">Semua Brand</p>
</Link>
<Link
href='/shop/search?orderBy=stock'
className={`${
router.asPath === '/shop/search?orderBy=stock' &&
'bg-gray_r-3'
- } p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition`}
+ } p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition group`}
target='_blank'
rel='noreferrer'
>
- Ready Stock
+ <p className="group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200">Ready Stock</p>
</Link>
<Link
href='https://blog.indoteknik.com/'
- className='p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition'
+ className='p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition group'
target='_blank'
rel='noreferrer noopener'
>
- Blog Indoteknik
+ <p className="group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200">Blog Indoteknik</p>
</Link>
- <Link
+ {/* <Link
href='/video'
- className={`${
- router.asPath === '/video' && 'bg-gray_r-3'
- } p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition`}
+ className='p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition'
target='_blank'
rel='noreferrer'
>
Indoteknik TV
- </Link>
+ </Link> */}
</div>
<div className='w-3/12 flex gap-x-1 relative'>
diff --git a/src/core/components/elements/Navbar/NavbarMobile.jsx b/src/core/components/elements/Navbar/NavbarMobile.jsx
index bcf45e0a..90314671 100644
--- a/src/core/components/elements/Navbar/NavbarMobile.jsx
+++ b/src/core/components/elements/Navbar/NavbarMobile.jsx
@@ -11,7 +11,7 @@ import Image from 'next/image';
import { useEffect, useState } from 'react';
import MobileView from '../../views/MobileView';
import Link from '../Link/Link';
-// import TopBanner from './TopBanner';
+import TopBanner from './TopBanner';
const Search = dynamic(() => import('./Search'));
@@ -39,7 +39,7 @@ const NavbarMobile = () => {
return (
<MobileView>
- {/* <TopBanner /> */}
+ <TopBanner />
<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='/'>
diff --git a/src/core/components/elements/Navbar/TopBanner.jsx b/src/core/components/elements/Navbar/TopBanner.jsx
index 722a7501..302db5c4 100644
--- a/src/core/components/elements/Navbar/TopBanner.jsx
+++ b/src/core/components/elements/Navbar/TopBanner.jsx
@@ -1,39 +1,45 @@
import Image from 'next/image';
-import { useQuery } from 'react-query';
-
+import { useQuery } from 'react-query';import useDevice from '@/core/hooks/useDevice'
import odooApi from '@/core/api/odooApi';
import SmoothRender from '~/components/ui/smooth-render';
import Link from '../Link/Link';
+import { useEffect } from 'react';
-const TopBanner = () => {
+const TopBanner = ({ onLoad }) => {
const topBanner = useQuery({
queryKey: 'topBanner',
queryFn: async () => await odooApi('GET', '/api/v1/banner?type=top-banner'),
refetchOnWindowFocus: false,
});
- const backgroundColor = topBanner.data?.[0]?.backgroundColor || 'transparent';
+ // const backgroundColor = topBanner.data?.[0]?.backgroundColor || 'transparent';
const hasData = topBanner.data?.length > 0;
const data = topBanner.data?.[0] || null;
+ useEffect(() => {
+ if (hasData) {
+ onLoad();
+ }
+ }, [hasData, onLoad]);
+
return (
<SmoothRender
isLoaded={hasData}
- height='36px'
+ // height='36px'
duration='700ms'
delay='300ms'
- style={{ backgroundColor }}
- >
- <Link href={data?.url}>
- <Image
- src={data?.image}
- alt={data?.name}
- width={1440}
- height={40}
- className='object-cover object-center h-full mx-auto'
- />
- </Link>
- </SmoothRender>
+ className='h-auto'
+ >
+ <Link
+ href={data?.url}
+ className="block bg-cover bg-center h-3 md:h-6 lg:h-[36px]"
+ style={{
+ backgroundImage: `url('${data?.image}')`,
+ }}
+ >
+ </Link>
+
+ </SmoothRender>
);
};
diff --git a/src/core/components/elements/Navbar/style/NavbarDesktop.module.css b/src/core/components/elements/Navbar/style/NavbarDesktop.module.css
new file mode 100644
index 00000000..9cddb127
--- /dev/null
+++ b/src/core/components/elements/Navbar/style/NavbarDesktop.module.css
@@ -0,0 +1,14 @@
+/* navbarDesktop.module.css */
+@keyframes blink {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0;
+ }
+}
+
+.blink {
+ animation: blink 0.8s infinite;
+}
+
diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx
index 38fcdef8..55838890 100644
--- a/src/core/components/elements/Sidebar/Sidebar.jsx
+++ b/src/core/components/elements/Sidebar/Sidebar.jsx
@@ -117,6 +117,9 @@ const Sidebar = ({ active, close }) => {
</>
)}
</div>
+ <SidebarLink className={itemClassName} href='/shop/promo'>
+ Semua Promo
+ </SidebarLink>
<SidebarLink className={itemClassName} href='/shop/brands'>
Semua Brand
</SidebarLink>
@@ -128,9 +131,9 @@ const Sidebar = ({ active, close }) => {
>
Blog Indoteknik
</SidebarLink>
- <SidebarLink className={itemClassName} href='/video'>
+ {/* <SidebarLink className={itemClassName} href='/video'>
Indoteknik TV
- </SidebarLink>
+ </SidebarLink> */}
<SidebarLink className={itemClassName} href='/tentang-kami'>
Tentang Indoteknik
</SidebarLink>
diff --git a/src/core/components/layouts/BasicLayout.jsx b/src/core/components/layouts/BasicLayout.jsx
index a4f3a856..ba51022d 100644
--- a/src/core/components/layouts/BasicLayout.jsx
+++ b/src/core/components/layouts/BasicLayout.jsx
@@ -93,4 +93,4 @@ const BasicLayout = ({ children }) => {
);
};
-export default BasicLayout;
+export default BasicLayout; \ No newline at end of file