summaryrefslogtreecommitdiff
path: root/src/pages
diff options
context:
space:
mode:
authorIT Fixcomart <it@fixcomart.co.id>2024-01-19 02:32:43 +0000
committerIT Fixcomart <it@fixcomart.co.id>2024-01-19 02:32:43 +0000
commit8bcadf6d43a44169c422305522784424c30c7b02 (patch)
tree4666802b65784a949db4acad665a81de7297fc74 /src/pages
parent065396828266e2de42cb0182c81ea2d7a5b00e2b (diff)
parent91086d8b1af2e1c0ca9db38d037f6331c9e6131a (diff)
Merged in Feature/perf/product-detail (pull request #127)
Feature/perf/product detail
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/_app.jsx108
-rw-r--r--src/pages/_document.jsx36
-rw-r--r--src/pages/shop/cart.jsx2
-rw-r--r--src/pages/shop/product/[slug].jsx118
4 files changed, 97 insertions, 167 deletions
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index 3fe1d3cf..9067fd03 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -1,58 +1,82 @@
-import '@/fonts/Inter/inter.css'
-import '@/styles/globals.css'
-import 'react-loading-skeleton/dist/skeleton.css'
+import '@/fonts/Inter/inter.css';
+import '@/styles/globals.css';
+// import 'react-loading-skeleton/dist/skeleton.css';
-import NextProgress from 'next-progress'
-import { useRouter, Router } from 'next/router'
-import { AnimatePresence, motion } from 'framer-motion'
-import { Toaster } from 'react-hot-toast'
-import { QueryClient, QueryClientProvider } from 'react-query'
-import useDevice from '@/core/hooks/useDevice'
-import { useEffect, useState } from 'react'
-import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner'
-import { SessionProvider } from 'next-auth/react'
-import { ProductProvider } from '@/contexts/ProductContext'
-import { ProductCartProvider } from '@/contexts/ProductCartContext'
-import { ChakraProvider } from '@chakra-ui/react'
-import theme from '../../chakra.theme'
+import { useEffect, useState } from 'react';
+import dynamic from 'next/dynamic';
+import { useRouter, Router } from 'next/router';
+import { AnimatePresence, motion } from 'framer-motion';
+import { QueryClient, QueryClientProvider } from 'react-query';
-const queryClient = new QueryClient()
+import useDevice from '@/core/hooks/useDevice';
+import theme from '../../chakra.theme';
+
+const NextProgress = dynamic(() => import('next-progress'), { ssr: false });
+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 }
+);
+const LogoSpinner = dynamic(
+ () => import('@/core/components/elements/Spinner/LogoSpinner'),
+ { ssr: false }
+);
+const Toaster = dynamic(
+ () => import('react-hot-toast').then((mod) => mod.Toaster),
+ { ssr: false }
+);
+
+const queryClient = new QueryClient();
function MyApp({ Component, pageProps: { session, ...pageProps } }) {
- const router = useRouter()
- const { isMobile } = useDevice()
+ const router = useRouter();
+ const { isMobile } = useDevice();
- const [animateLoader, setAnimateLoader] = useState(false)
+ const [animateLoader, setAnimateLoader] = useState(false);
useEffect(() => {
- const handleRouteChangeStart = () => setAnimateLoader(true)
- const handleRouteChangeComplete = () => setAnimateLoader(false)
+ const handleRouteChangeStart = () => setAnimateLoader(true);
+ const handleRouteChangeComplete = () => setAnimateLoader(false);
- Router.events.on('routeChangeStart', handleRouteChangeStart)
- Router.events.on('routeChangeComplete', handleRouteChangeComplete)
- Router.events.on('routeChangeError', handleRouteChangeComplete)
+ Router.events.on('routeChangeStart', handleRouteChangeStart);
+ Router.events.on('routeChangeComplete', handleRouteChangeComplete);
+ Router.events.on('routeChangeError', handleRouteChangeComplete);
return () => {
- Router.events.off('routeChangeStart', handleRouteChangeStart)
- Router.events.off('routeChangeComplete', handleRouteChangeComplete)
- Router.events.off('routeChangeError', handleRouteChangeComplete)
- }
- }, [])
+ Router.events.off('routeChangeStart', handleRouteChangeStart);
+ Router.events.off('routeChangeComplete', handleRouteChangeComplete);
+ Router.events.off('routeChangeError', handleRouteChangeComplete);
+ };
+ }, []);
- const [toasterStyle, setToasterStyle] = useState({})
+ const [toasterStyle, setToasterStyle] = useState({});
useEffect(() => {
- let elems = document.querySelectorAll('nav')
- let totalNavHeight = 0
+ let elems = document.querySelectorAll('nav');
+ let totalNavHeight = 0;
elems.forEach(function (elem) {
- totalNavHeight += elem.offsetHeight
- })
+ totalNavHeight += elem.offsetHeight;
+ });
setToasterStyle({
- marginTop: isMobile ? totalNavHeight - 8 : totalNavHeight
- })
- }, [isMobile])
+ marginTop: isMobile ? totalNavHeight - 8 : totalNavHeight,
+ });
+ }, [isMobile]);
return (
<SessionProvider session={session}>
@@ -63,7 +87,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) {
animate={{ opacity: 1 }}
exit={{ opacity: 0.4 }}
transition={{
- duration: 0.1
+ duration: 0.1,
}}
className='fixed w-screen h-screen z-[500] bg-white flex justify-center items-center'
>
@@ -76,7 +100,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) {
containerStyle={toasterStyle}
toastOptions={{
duration: 3000,
- className: 'border border-gray_r-8'
+ className: 'border border-gray_r-8',
}}
/>
<NextProgress color='#F01C21' options={{ showSpinner: false }} />
@@ -90,7 +114,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) {
</ProductProvider>
</QueryClientProvider>
</SessionProvider>
- )
+ );
}
-export default MyApp
+export default MyApp;
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index 3762c63b..fc9f2ee0 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -1,16 +1,24 @@
-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='prefetch' href='/images/logo-indoteknik-gear.png' />
+
<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' />
@@ -18,9 +26,11 @@ export default function MyDocument() {
<meta name='apple-mobile-web-app-title' content='Indoteknik.com' />
<meta name='theme-color' content='#fff' />
- <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'
@@ -28,6 +38,7 @@ export default function MyDocument() {
/>
<Script
+ async
id='google-analytics-ua'
strategy='beforeInteractive'
dangerouslySetInnerHTML={{
@@ -36,7 +47,7 @@ export default function MyDocument() {
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-10501937-1');
- `
+ `,
}}
/>
@@ -47,6 +58,7 @@ export default function MyDocument() {
/>
<Script
+ async
id='google-analytics-ga'
strategy='beforeInteractive'
dangerouslySetInnerHTML={{
@@ -55,11 +67,12 @@ export default function MyDocument() {
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-G1W8MNZ11P');
- `
+ `,
}}
/>
<Script
+ async
id='google-tag-manager'
strategy='afterInteractive'
dangerouslySetInnerHTML={{
@@ -68,7 +81,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');
- `
+ `,
}}
/>
@@ -79,6 +92,7 @@ export default function MyDocument() {
/>
<Script
+ async
id='google-ads'
strategy='afterInteractive'
dangerouslySetInnerHTML={{
@@ -87,7 +101,7 @@ export default function MyDocument() {
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
- gtag('config', 'AW-954540379');`
+ gtag('config', 'AW-954540379');`,
}}
/>
@@ -119,5 +133,5 @@ export default function MyDocument() {
<NextScript />
</body>
</Html>
- )
+ );
}
diff --git a/src/pages/shop/cart.jsx b/src/pages/shop/cart.jsx
index 34cae86a..7475b23d 100644
--- a/src/pages/shop/cart.jsx
+++ b/src/pages/shop/cart.jsx
@@ -8,7 +8,7 @@ import dynamic from 'next/dynamic';
import Link from 'next/link';
const AppLayout = dynamic(() => import('@/core/components/layouts/AppLayout'));
-const CartDetail = dynamic(() => import('~/modules/cart/components/Detail'));
+const CartDetail = dynamic(() => import('~/pages/shop/cart'));
export default function Cart() {
return (
diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx
index 667373b4..73e8987c 100644
--- a/src/pages/shop/product/[slug].jsx
+++ b/src/pages/shop/product/[slug].jsx
@@ -1,114 +1,6 @@
-import Seo from '@/core/components/Seo';
-import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner';
-import { getIdFromSlug } from '@/core/utils/slug';
-import productApi from '@/lib/product/api/productApi';
-import PageNotFound from '@/pages/404';
-import dynamic from 'next/dynamic';
-import { useRouter } from 'next/router';
-import cookie from 'cookie';
-import axios from 'axios';
-import { useProductContext } from '@/contexts/ProductContext';
-import { useEffect } from 'react';
-import { updateItemCart } from '@/core/utils/cart';
+import ProductDetailPage, {
+ getServerSideProps,
+} from '~/pages/shop/product/[slug]';
-const BasicLayout = dynamic(() =>
- import('@/core/components/layouts/BasicLayout')
-);
-const Product = dynamic(() =>
- import('@/lib/product/components/Product/Product')
-);
-
-export async function getServerSideProps(context) {
- const { slug } = context.query;
- const cookies = context.req.headers.cookie;
- const cookieObj = cookies ? cookie.parse(cookies) : {};
- const auth = cookieObj.auth ? JSON.parse(cookieObj.auth) : {};
- const tier = auth.pricelist ? auth.pricelist : false;
-
- let response = await axios(
- `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/product-detail?id=` +
- getIdFromSlug(slug) +
- '&auth=' +
- tier
- );
- let product = response.data;
- // let productSolr = await productApi({ id: getIdFromSlug(slug), headers: { Token: authToken } })
- // let productSolr = null
- if (product?.length == 1) {
- product = product[0];
- } else {
- product = null;
- }
-
- return {
- props: { product },
- };
-}
-
-export default function ProductDetail({ product }) {
- const router = useRouter();
- const { setProduct } = useProductContext();
-
- useEffect(() => {
- if (product) {
- setProduct(product);
- }
- }, [product, setProduct]);
-
- useEffect(() => {
- const { action, variantId, qty } = router.query;
- const addToCart = async () => {
- const data = {
- productId: variantId,
- quantity: qty,
- selected: true,
- programLineId: null,
- source: action,
- };
-
- await updateItemCart(data);
- const redirectURL =
- action === 'buy' ? '/shop/checkout?source=buy' : '/shop/cart';
- router.push(redirectURL);
- };
-
- if (action && variantId && qty) {
- addToCart();
- }
- }, [router]);
-
- if (!product) return <PageNotFound />;
-
- return (
- <BasicLayout>
- <Seo
- title={product?.name || '' + ' - Indoteknik.com' || ''}
- description='Temukan pilihan produk B2B Industri &amp; Alat Teknik untuk Perusahaan, UMKM &amp; Pemerintah dengan lengkap, mudah dan transparan.'
- openGraph={{
- url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath,
- images: [
- {
- url: product?.image,
- width: 800,
- height: 800,
- alt: product?.name,
- },
- ],
- type: 'product',
- }}
- additionalMetaTags={[
- {
- name: 'keywords',
- content: `${product?.name}, Harga ${product?.name}, Beli ${product?.name}, Spesifikasi ${product?.name}`,
- },
- ]}
- />
- {!product && (
- <div className='container mx-auto flex justify-center pt-10'>
- <LogoSpinner width={36} height={36} />
- </div>
- )}
- {product && <Product product={product} />}
- </BasicLayout>
- );
-}
+export { getServerSideProps };
+export default ProductDetailPage;