summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2024-01-16 16:08:43 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2024-01-16 16:08:43 +0700
commita70fd5b6d9c7a769ac1aaa22a7d037ba3be27a05 (patch)
tree825d6b5de089bb22003bb2a517d371dc291f1962 /src
parentd9dafa74857959974e9d379dc1a3abfbaf2af83d (diff)
Update improve product detail performance
Diffstat (limited to 'src')
-rw-r--r--src/core/components/elements/Navbar/NavbarDesktop.jsx124
-rw-r--r--src/core/components/elements/Navbar/NavbarMobile.jsx69
-rw-r--r--src/core/components/elements/Skeleton/TopBannerSkeleton.jsx24
-rw-r--r--src/fonts/Inter/inter.css85
-rw-r--r--src/pages/_app.jsx15
-rw-r--r--src/pages/_document.jsx31
6 files changed, 152 insertions, 196 deletions
diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx
index d9f5658e..9bcd4df2 100644
--- a/src/core/components/elements/Navbar/NavbarDesktop.jsx
+++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx
@@ -2,74 +2,72 @@ import {
ChevronDownIcon,
HeartIcon,
ShoppingCartIcon,
- DocumentCheckIcon
-} from '@heroicons/react/24/outline'
-import Link from '../Link/Link'
-import Image from 'next/image'
-import DesktopView from '../../views/DesktopView'
-import dynamic from 'next/dynamic'
-import IndoteknikLogo from '@/images/logo.png'
-import Category from '@/lib/category/components/Category'
-import { useCallback, useContext, useEffect, useState } from 'react'
-import useAuth from '@/core/hooks/useAuth'
-import NavbarUserDropdown from './NavbarUserDropdown'
-import { getCartApi, getCountCart } from '@/core/utils/cart'
-import whatsappUrl from '@/core/utils/whatsappUrl'
-import { useRouter } from 'next/router'
-import { getAuth, setAuth } from '@/core/utils/auth'
-import { createSlug, getIdFromSlug } from '@/core/utils/slug'
-import { TopBannerSkeleton } from '../Skeleton/TopBannerSkeleton'
-import { useProductContext } from '@/contexts/ProductContext'
-import Cardheader from '@/lib/cart/components/Cartheader'
-
-const Search = dynamic(() => import('./Search'))
-const TopBanner = dynamic(() => import('./TopBanner'), {
- loading: () => <TopBannerSkeleton />
-})
+ DocumentCheckIcon,
+} from '@heroicons/react/24/outline';
+import Link from '../Link/Link';
+import Image from 'next/image';
+import DesktopView from '../../views/DesktopView';
+import dynamic from 'next/dynamic';
+import IndoteknikLogo from '@/images/logo.png';
+import Category from '@/lib/category/components/Category';
+import { useCallback, useContext, useEffect, useState } from 'react';
+import useAuth from '@/core/hooks/useAuth';
+import NavbarUserDropdown from './NavbarUserDropdown';
+import { getCartApi, getCountCart } from '@/core/utils/cart';
+import whatsappUrl from '@/core/utils/whatsappUrl';
+import { useRouter } from 'next/router';
+import { getAuth, setAuth } from '@/core/utils/auth';
+import { createSlug, getIdFromSlug } from '@/core/utils/slug';
+import { TopBannerSkeleton } from '../Skeleton/TopBannerSkeleton';
+import { useProductContext } from '@/contexts/ProductContext';
+import Cardheader from '@/lib/cart/components/Cartheader';
+
+const Search = dynamic(() => import('./Search'), { ssr: false });
+const TopBanner = dynamic(() => import('./TopBanner'), { ssr: false });
const NavbarDesktop = () => {
- const [isOpenCategory, setIsOpenCategory] = useState(false)
- const auth = useAuth()
+ const [isOpenCategory, setIsOpenCategory] = useState(false);
+ const auth = useAuth();
- const [cartCount, setCartCount] = useState(0)
+ const [cartCount, setCartCount] = useState(0);
- const [templateWA, setTemplateWA] = useState(null)
- const [payloadWA, setPayloadWa] = useState(null)
- const [urlPath, setUrlPath] = useState(null)
+ const [templateWA, setTemplateWA] = useState(null);
+ const [payloadWA, setPayloadWa] = useState(null);
+ const [urlPath, setUrlPath] = useState(null);
- const router = useRouter()
+ const router = useRouter();
- const { product } = useProductContext()
+ const { product } = useProductContext();
useEffect(() => {
if (router.pathname === '/shop/product/[slug]') {
setPayloadWa({
name: product?.name,
manufacture: product?.manufacture.name,
- url: createSlug('/shop/product/', product?.name, product?.id, true)
- })
- setTemplateWA('product')
+ url: createSlug('/shop/product/', product?.name, product?.id, true),
+ });
+ setTemplateWA('product');
- setUrlPath(router.asPath)
+ setUrlPath(router.asPath);
}
- }, [product, router])
+ }, [product, router]);
useEffect(() => {
const handleCartChange = () => {
const cart = async () => {
- const listCart = await getCountCart()
- setCartCount(listCart)
- }
- cart()
- }
- handleCartChange()
+ const listCart = await getCountCart();
+ setCartCount(listCart);
+ };
+ cart();
+ };
+ handleCartChange();
- window.addEventListener('localStorageChange', handleCartChange)
+ window.addEventListener('localStorageChange', handleCartChange);
return () => {
- window.removeEventListener('localStorageChange', handleCartChange)
- }
- }, [])
+ window.removeEventListener('localStorageChange', handleCartChange);
+ };
+ }, []);
return (
<DesktopView>
@@ -93,7 +91,12 @@ const NavbarDesktop = () => {
<nav className='pt-6 sticky top-0 z-50 bg-white border-b-2 border-danger-500'>
<div className='container mx-auto flex gap-x-6'>
<Link href='/'>
- <Image src={IndoteknikLogo} alt='Indoteknik Logo' width={210} height={210 / 3} />
+ <Image
+ src={IndoteknikLogo}
+ alt='Indoteknik Logo'
+ width={210}
+ height={210 / 3}
+ />
</Link>
<div className='flex-1 flex items-center'>
<Search />
@@ -128,7 +131,12 @@ const NavbarDesktop = () => {
rel='noreferrer'
className='flex items-center gap-x-1 !text-gray_r-12/80'
>
- <Image src='/images/socials/Whatsapp-2.png' alt='Whatsapp' width={48} height={48} />
+ <Image
+ src='/images/socials/Whatsapp-2.png'
+ alt='Whatsapp'
+ width={48}
+ height={48}
+ />
<div>
<div className='font-semibold'>Whatsapp</div>
0812 8080 622 (Chat)
@@ -146,9 +154,15 @@ const NavbarDesktop = () => {
className='w-3/12 p-4 font-semibold border border-gray_r-6 rounded-t-xl flex items-center relative'
>
<div>Kategori Produk</div>
- <ChevronDownIcon className={`ml-auto w-6 ${isOpenCategory ? 'rotate-180' : ''}`} />
-
- <div className={`category-mega-box-wrapper ${isOpenCategory ? 'show' : ''}`}>
+ <ChevronDownIcon
+ className={`ml-auto w-6 ${isOpenCategory ? 'rotate-180' : ''}`}
+ />
+
+ <div
+ className={`category-mega-box-wrapper ${
+ isOpenCategory ? 'show' : ''
+ }`}
+ >
<Category />
</div>
</button>
@@ -220,7 +234,7 @@ const NavbarDesktop = () => {
</div>
</nav>
</DesktopView>
- )
-}
+ );
+};
-export default NavbarDesktop
+export default NavbarDesktop;
diff --git a/src/core/components/elements/Navbar/NavbarMobile.jsx b/src/core/components/elements/Navbar/NavbarMobile.jsx
index 704e91b6..92bd5627 100644
--- a/src/core/components/elements/Navbar/NavbarMobile.jsx
+++ b/src/core/components/elements/Navbar/NavbarMobile.jsx
@@ -1,51 +1,60 @@
-import Image from 'next/image'
-import MobileView from '../../views/MobileView'
-import Link from '../Link/Link'
-import { Bars3Icon, HeartIcon, ShoppingCartIcon } from '@heroicons/react/24/outline'
-import useSidebar from '@/core/hooks/useSidebar'
-import dynamic from 'next/dynamic'
-import IndoteknikLogo from '@/images/logo.png'
-import { useEffect, useState } from 'react'
-import { getCart, getCountCart } from '@/core/utils/cart'
-import TopBanner from './TopBanner'
+import Image from 'next/image';
+import MobileView from '../../views/MobileView';
+import Link from '../Link/Link';
+import {
+ Bars3Icon,
+ HeartIcon,
+ ShoppingCartIcon,
+} from '@heroicons/react/24/outline';
+import useSidebar from '@/core/hooks/useSidebar';
+import dynamic from 'next/dynamic';
+import IndoteknikLogo from '@/images/logo.png';
+import { useEffect, useState } from 'react';
+import { getCart, getCountCart } from '@/core/utils/cart';
+// import TopBanner from './TopBanner';
-const Search = dynamic(() => import('./Search'))
+const Search = dynamic(() => import('./Search'));
const NavbarMobile = () => {
- const { Sidebar, open } = useSidebar()
+ const { Sidebar, open } = useSidebar();
- const [cartCount, setCartCount] = useState(0)
+ const [cartCount, setCartCount] = useState(0);
useEffect(() => {
const handleCartChange = () => {
const cart = async () => {
- const listCart = await getCountCart()
- setCartCount(listCart)
- }
- cart()
- }
- handleCartChange()
+ const listCart = await getCountCart();
+ setCartCount(listCart);
+ };
+ cart();
+ };
+ handleCartChange();
- window.addEventListener('localStorageChange', handleCartChange)
+ window.addEventListener('localStorageChange', handleCartChange);
return () => {
- window.removeEventListener('localStorageChange', handleCartChange)
- }
- }, [])
+ window.removeEventListener('localStorageChange', handleCartChange);
+ };
+ }, []);
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='/'>
- <Image src={IndoteknikLogo} alt='Indoteknik Logo' width={120} height={40} />
+ <Image
+ src={IndoteknikLogo}
+ alt='Indoteknik Logo'
+ width={120}
+ height={40}
+ />
</Link>
<div className='flex gap-x-3'>
- <Link href='/my/wishlist'>
+ <Link href='/my/wishlist' aria-label='Wishlist'>
<HeartIcon className='w-6 text-gray_r-12' />
</Link>
- <Link href='/shop/cart' className='relative'>
+ <Link href='/shop/cart' className='relative' aria-label='Cart'>
<ShoppingCartIcon className='w-6 text-gray_r-12' />
{cartCount > 0 && (
<span className='absolute -top-2 -right-2 badge-solid-red rounded-full w-5 h-5 flex items-center justify-center'>
@@ -62,7 +71,7 @@ const NavbarMobile = () => {
</nav>
{Sidebar}
</MobileView>
- )
-}
+ );
+};
-export default NavbarMobile
+export default NavbarMobile;
diff --git a/src/core/components/elements/Skeleton/TopBannerSkeleton.jsx b/src/core/components/elements/Skeleton/TopBannerSkeleton.jsx
index f7d2e748..8d1a51d2 100644
--- a/src/core/components/elements/Skeleton/TopBannerSkeleton.jsx
+++ b/src/core/components/elements/Skeleton/TopBannerSkeleton.jsx
@@ -1,19 +1,17 @@
-import useDevice from '@/core/hooks/useDevice'
-import classNames from 'classnames'
-import Skeleton from 'react-loading-skeleton'
+import useDevice from '@/core/hooks/useDevice';
+import classNames from 'classnames';
+import { Skeleton } from '@chakra-ui/react';
const TopBannerSkeleton = () => {
- const { isDesktop, isMobile } = useDevice()
+ const { isDesktop, isMobile } = useDevice();
const deviceClassName = {
- 'h-10': isDesktop,
- 'h-2.5': isMobile
- }
- const combinedClassName = classNames(deviceClassName)
+ '!h-[36px]': isDesktop,
+ 'h-2.5': isMobile,
+ };
+ const combinedClassName = classNames(deviceClassName);
- return (
- <Skeleton className={combinedClassName} count={1} containerClassName='w-full h-full block' />
- )
-}
+ return <Skeleton className={combinedClassName} />;
+};
-export { TopBannerSkeleton }
+export { TopBannerSkeleton };
diff --git a/src/fonts/Inter/inter.css b/src/fonts/Inter/inter.css
index de6ce273..3a1de02a 100644
--- a/src/fonts/Inter/inter.css
+++ b/src/fonts/Inter/inter.css
@@ -1,57 +1,6 @@
@font-face {
font-family: 'Inter';
font-style: normal;
- font-weight: 100;
- font-display: swap;
- src: url('Inter-Thin.woff2?v=3.19') format('woff2'),
- url('Inter-Thin.woff?v=3.19') format('woff');
-}
-@font-face {
- font-family: 'Inter';
- font-style: italic;
- font-weight: 100;
- font-display: swap;
- src: url('Inter-ThinItalic.woff2?v=3.19') format('woff2'),
- url('Inter-ThinItalic.woff?v=3.19') format('woff');
-}
-
-@font-face {
- font-family: 'Inter';
- font-style: normal;
- font-weight: 200;
- font-display: swap;
- src: url('Inter-ExtraLight.woff2?v=3.19') format('woff2'),
- url('Inter-ExtraLight.woff?v=3.19') format('woff');
-}
-@font-face {
- font-family: 'Inter';
- font-style: italic;
- font-weight: 200;
- font-display: swap;
- src: url('Inter-ExtraLightItalic.woff2?v=3.19') format('woff2'),
- url('Inter-ExtraLightItalic.woff?v=3.19') format('woff');
-}
-
-@font-face {
- font-family: 'Inter';
- font-style: normal;
- font-weight: 300;
- font-display: swap;
- src: url('Inter-Light.woff2?v=3.19') format('woff2'),
- url('Inter-Light.woff?v=3.19') format('woff');
-}
-@font-face {
- font-family: 'Inter';
- font-style: italic;
- font-weight: 300;
- font-display: swap;
- src: url('Inter-LightItalic.woff2?v=3.19') format('woff2'),
- url('Inter-LightItalic.woff?v=3.19') format('woff');
-}
-
-@font-face {
- font-family: 'Inter';
- font-style: normal;
font-weight: 400;
font-display: swap;
src: url('Inter-Regular.woff2?v=3.19') format('woff2'),
@@ -117,40 +66,6 @@
url('Inter-BoldItalic.woff?v=3.19') format('woff');
}
-@font-face {
- font-family: 'Inter';
- font-style: normal;
- font-weight: 800;
- font-display: swap;
- src: url('Inter-ExtraBold.woff2?v=3.19') format('woff2'),
- url('Inter-ExtraBold.woff?v=3.19') format('woff');
-}
-@font-face {
- font-family: 'Inter';
- font-style: italic;
- font-weight: 800;
- font-display: swap;
- src: url('Inter-ExtraBoldItalic.woff2?v=3.19') format('woff2'),
- url('Inter-ExtraBoldItalic.woff?v=3.19') format('woff');
-}
-
-@font-face {
- font-family: 'Inter';
- font-style: normal;
- font-weight: 900;
- font-display: swap;
- src: url('Inter-Black.woff2?v=3.19') format('woff2'),
- url('Inter-Black.woff?v=3.19') format('woff');
-}
-@font-face {
- font-family: 'Inter';
- font-style: italic;
- font-weight: 900;
- font-display: swap;
- src: url('Inter-BlackItalic.woff2?v=3.19') format('woff2'),
- url('Inter-BlackItalic.woff?v=3.19') format('woff');
-}
-
/* -------------------------------------------------------
Variable font.
Usage:
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index aa545863..9067fd03 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -1,6 +1,6 @@
import '@/fonts/Inter/inter.css';
import '@/styles/globals.css';
-import 'react-loading-skeleton/dist/skeleton.css';
+// import 'react-loading-skeleton/dist/skeleton.css';
import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
@@ -9,8 +9,6 @@ import { AnimatePresence, motion } from 'framer-motion';
import { QueryClient, QueryClientProvider } from 'react-query';
import useDevice from '@/core/hooks/useDevice';
-import { ProductProvider } from '@/contexts/ProductContext';
-import { ProductCartProvider } from '@/contexts/ProductCartContext';
import theme from '../../chakra.theme';
const NextProgress = dynamic(() => import('next-progress'), { ssr: false });
@@ -18,6 +16,17 @@ const ChakraProvider = dynamic(
() => import('@chakra-ui/react').then((mod) => mod.ChakraProvider),
{ ssr: false }
);
+const ProductProvider = dynamic(
+ () => import('@/contexts/ProductContext').then((mod) => mod.ProductProvider),
+ { ssr: false }
+);
+const ProductCartProvider = dynamic(
+ () =>
+ import('@/contexts/ProductCartContext').then(
+ (mod) => mod.ProductCartProvider
+ ),
+ { ssr: false }
+);
const SessionProvider = dynamic(
() => import('next-auth/react').then((mod) => mod.SessionProvider),
{ ssr: false }
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index 3762c63b..8eb3f15e 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -1,16 +1,23 @@
-import { Html, Head, Main, NextScript } from 'next/document'
-import Script from 'next/script'
+import { Html, Head, Main, NextScript } from 'next/document';
+import Script from 'next/script';
export default function MyDocument() {
- const env = process.env.NODE_ENV
+ const env = process.env.NODE_ENV;
return (
<Html>
<Head>
+ <link rel='preconnect' href='https://connect.facebook.net' />
+ <link rel='preconnect' href='https://googleads.g.doubleclick.net' />
+ <link rel='preconnect' href={process.env.NEXT_PUBLIC_ODOO_API_HOST} />
+
<link rel='icon' href='/favicon.ico' />
<link rel='manifest' href='/manifest.json' />
<link rel='apple-touch-icon' href='/icon.jpg'></link>
- <link rel='apple-touch-startup-image' href='/images/splash/launch.png' />
+ <link
+ rel='apple-touch-startup-image'
+ href='/images/splash/launch.png'
+ />
<meta name='mobile-web-app-capable' content='yes' />
<meta name='apple-mobile-web-app-capable' content='yes' />
@@ -20,7 +27,11 @@ export default function MyDocument() {
<link rel='prefetch' href='/images/logo-indoteknik-gear.png' />
- <meta name='facebook-domain-verification' content='328wmjs7hcnz74rwsqzxvq50rmbtm2' />
+ <meta
+ name='facebook-domain-verification'
+ content='328wmjs7hcnz74rwsqzxvq50rmbtm2'
+ />
+
<Script
async
strategy='beforeInteractive'
@@ -36,7 +47,7 @@ export default function MyDocument() {
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-10501937-1');
- `
+ `,
}}
/>
@@ -55,7 +66,7 @@ export default function MyDocument() {
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-G1W8MNZ11P');
- `
+ `,
}}
/>
@@ -68,7 +79,7 @@ export default function MyDocument() {
f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-PHRB7RP');
- `
+ `,
}}
/>
@@ -87,7 +98,7 @@ export default function MyDocument() {
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
- gtag('config', 'AW-954540379');`
+ gtag('config', 'AW-954540379');`,
}}
/>
@@ -119,5 +130,5 @@ export default function MyDocument() {
<NextScript />
</body>
</Html>
- )
+ );
}