summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrisusilo <tri.susilo@altama.co.id>2023-12-05 02:59:30 +0000
committertrisusilo <tri.susilo@altama.co.id>2023-12-05 02:59:30 +0000
commit80caa8f6ad5fecc213fd1533b972c6173102721e (patch)
treef70c8ec03cf2a1cdb8eb3f30ecd83e200986b70b
parenteca358fd93f1ea5d88c6a6fcc315624cc3bbb910 (diff)
parent4ac372ff318ee78e5d5019a1dbe95bf47b661766 (diff)
Merged in Feature/popup_information (pull request #118)
Feature/popup information
-rw-r--r--public/images/socials/tiktok.pngbin0 -> 3436 bytes
-rw-r--r--public/images/socials/youtube.webpbin0 -> 12624 bytes
-rw-r--r--src-migrate/common/components/elements/Seo.tsx34
-rw-r--r--src-migrate/modules/page-content/index.tsx15
-rw-r--r--src-migrate/modules/popup-information/index.tsx38
-rw-r--r--src-migrate/pages/register.tsx2
-rw-r--r--src/core/api/odooApi.js71
-rw-r--r--src/core/components/elements/Footer/BasicFooter.jsx280
-rw-r--r--src/lib/product/components/Product/ProductDesktop.jsx6
-rw-r--r--src/lib/product/components/Product/ProductMobile.jsx2
-rw-r--r--src/lib/product/components/ProductCard.jsx31
-rw-r--r--src/lib/product/components/ProductSearch.jsx17
-rw-r--r--src/pages/index.jsx98
13 files changed, 441 insertions, 153 deletions
diff --git a/public/images/socials/tiktok.png b/public/images/socials/tiktok.png
new file mode 100644
index 00000000..0347362a
--- /dev/null
+++ b/public/images/socials/tiktok.png
Binary files differ
diff --git a/public/images/socials/youtube.webp b/public/images/socials/youtube.webp
new file mode 100644
index 00000000..3e023fcc
--- /dev/null
+++ b/public/images/socials/youtube.webp
Binary files differ
diff --git a/src-migrate/common/components/elements/Seo.tsx b/src-migrate/common/components/elements/Seo.tsx
new file mode 100644
index 00000000..2245663a
--- /dev/null
+++ b/src-migrate/common/components/elements/Seo.tsx
@@ -0,0 +1,34 @@
+import { useRouter } from 'next/router'
+import React from 'react'
+import { NextSeo } from "next-seo"
+import { MetaTag, NextSeoProps } from 'next-seo/lib/types';
+
+const Seo = (props: NextSeoProps) => {
+ const router = useRouter()
+
+ const additionalMetaTags: MetaTag[] = [
+ {
+ property: 'fb:app_id',
+ content: '270830718811'
+ },
+ {
+ property: 'fb:page_id',
+ content: '101759953569'
+ },
+ ]
+
+ if (!!props.additionalMetaTags) additionalMetaTags.push(...props.additionalMetaTags)
+
+ return (
+ <NextSeo
+ defaultTitle='Indoteknik.com: B2B Industrial Supply & Solution'
+ canonical={process.env.NEXT_PUBLIC_SELF_HOST + router.asPath}
+ description={props.title}
+ {...props}
+ openGraph={{ siteName: 'Indoteknik.com', ...props.openGraph }}
+ additionalMetaTags={additionalMetaTags}
+ />
+ )
+}
+
+export default Seo \ No newline at end of file
diff --git a/src-migrate/modules/page-content/index.tsx b/src-migrate/modules/page-content/index.tsx
index cbd58633..608079f8 100644
--- a/src-migrate/modules/page-content/index.tsx
+++ b/src-migrate/modules/page-content/index.tsx
@@ -1,3 +1,4 @@
+import { useMemo } from "react"
import { useQuery } from "react-query"
import PageContentSkeleton from "~/common/components/skeleton/PageContentSkeleton"
import { PageContentProps } from "~/common/types/pageContent"
@@ -10,12 +11,18 @@ type Props = {
const PageContent = ({ path }: Props) => {
const { data, isLoading } = useQuery<PageContentProps>(`page-content:${path}`, async () => await getPageContent({ path }))
- if (isLoading) {
- return <PageContentSkeleton />
- }
+ const parsedContent = useMemo<string>(() => {
+ if (!data) return ''
+ return data.content.replaceAll(
+ 'src="/web/image',
+ `src="${process.env.NEXT_PUBLIC_ODOO_API_HOST}/web/image`
+ )
+ }, [data])
+
+ if (isLoading) return <PageContentSkeleton />
return (
- <div dangerouslySetInnerHTML={{ __html: data?.content || '' }}></div>
+ <div dangerouslySetInnerHTML={{ __html: parsedContent || '' }}></div>
)
}
diff --git a/src-migrate/modules/popup-information/index.tsx b/src-migrate/modules/popup-information/index.tsx
new file mode 100644
index 00000000..0d48a92a
--- /dev/null
+++ b/src-migrate/modules/popup-information/index.tsx
@@ -0,0 +1,38 @@
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import Modal from '~/common/components/elements/Modal';
+import { getAuth } from '~/common/libs/auth';
+import PageContent from '../page-content';
+import Link from 'next/link';
+
+const PagePopupInformation = () => {
+ const router = useRouter();
+ const isHomePage = router.pathname === '/';
+ const auth = getAuth();
+ const [active, setActive] = useState<boolean>(false);
+
+ useEffect(() => {
+ if (isHomePage && !auth) {
+ setActive(true);
+ }
+ }, [isHomePage, auth]);
+ return (
+ <div className='group'>
+ <Modal
+ active={active}
+ className='w-10/12 md:w-fit'
+ close={() => setActive(false)}
+ mode='desktop'
+ >
+ <div>
+ <PageContent path='/onbording-popup' />
+ <Link href={'/register'} className='btn-yellow w-full mt-2'>
+ Daftar Sekarang
+ </Link>
+ </div>
+ </Modal>
+ </div>
+ );
+};
+
+export default PagePopupInformation;
diff --git a/src-migrate/pages/register.tsx b/src-migrate/pages/register.tsx
index bd5c37f4..1246c6f5 100644
--- a/src-migrate/pages/register.tsx
+++ b/src-migrate/pages/register.tsx
@@ -1,6 +1,7 @@
import BasicLayout from "@/core/components/layouts/BasicLayout"
import { useWindowSize } from "usehooks-ts"
+import Seo from "~/common/components/elements/Seo"
import Register from "~/modules/register"
const RegisterPage = () => {
@@ -10,6 +11,7 @@ const RegisterPage = () => {
return (
<Layout>
+ <Seo title="Register - Indoteknik.com" />
<Register />
</Layout>
)
diff --git a/src/core/api/odooApi.js b/src/core/api/odooApi.js
index fe9fcdd2..3349ff4b 100644
--- a/src/core/api/odooApi.js
+++ b/src/core/api/odooApi.js
@@ -1,22 +1,24 @@
-import axios from 'axios'
-import camelcaseObjectDeep from 'camelcase-object-deep'
-import { getCookie, setCookie } from 'cookies-next'
-import { getAuth } from '../utils/auth'
+import axios from 'axios';
+import camelcaseObjectDeep from 'camelcase-object-deep';
+import { getCookie, setCookie } from 'cookies-next';
+import { deleteAuth, getAuth } from '../utils/auth';
const renewToken = async () => {
- let token = await axios.get(process.env.NEXT_PUBLIC_ODOO_API_HOST + '/api/token')
- setCookie('token', token.data.result)
- return token.data.result
-}
+ let token = await axios.get(
+ process.env.NEXT_PUBLIC_ODOO_API_HOST + '/api/token'
+ );
+ setCookie('token', token.data.result);
+ return token.data.result;
+};
const getToken = async () => {
- let token = getCookie('token')
- if (token == undefined) token = await renewToken()
- return token
-}
+ let token = getCookie('token');
+ if (token == undefined) token = await renewToken();
+ return token;
+};
-const maxConnectionAttempt = 15
-let connectionAttempt = 0
+const maxConnectionAttempt = 15;
+let connectionAttempt = 0;
/**
* The `odooApi` function is used to make API requests to an Odoo backend with customizable parameters such as `method`, `url`, `data`, and `headers`.
@@ -30,31 +32,40 @@ let connectionAttempt = 0
* @returns {Promise} - A Promise that resolves to the API response data or an empty array.
*/
const odooApi = async (method, url, data = {}, headers = {}) => {
- connectionAttempt++
+ connectionAttempt++;
try {
- let token = await getToken()
- const auth = getAuth()
+ let token = await getToken();
+ const auth = getAuth();
let axiosParameter = {
method,
url: process.env.NEXT_PUBLIC_ODOO_API_HOST + url,
- headers: { Authorization: token, ...headers }
- }
- if (auth) axiosParameter.headers['Token'] = auth.token
+ headers: { Authorization: token, ...headers },
+ };
+ if (auth) axiosParameter.headers['Token'] = auth.token;
if (method.toUpperCase() == 'POST')
- axiosParameter.headers['Content-Type'] = 'application/x-www-form-urlencoded'
+ axiosParameter.headers['Content-Type'] =
+ 'application/x-www-form-urlencoded';
if (Object.keys(data).length > 0)
- axiosParameter.data = new URLSearchParams(Object.entries(data)).toString()
+ axiosParameter.data = new URLSearchParams(
+ Object.entries(data)
+ ).toString();
- let res = await axios(axiosParameter)
- if (res.data.status.code == 401 && connectionAttempt < maxConnectionAttempt) {
- await renewToken()
- return odooApi(method, url, data, headers)
+ let res = await axios(axiosParameter);
+ if (res.data.status.code == 401) {
+ if (connectionAttempt < maxConnectionAttempt) {
+ await renewToken();
+ return odooApi(method, url, data, headers);
+ } else {
+ await deleteAuth();
+ window.location.href = '/login';
+ return false;
+ }
}
- return camelcaseObjectDeep(res.data.result) || []
+ return camelcaseObjectDeep(res.data.result) || [];
} catch (error) {
- console.log(error)
+ console.log(error);
}
-}
+};
-export default odooApi
+export default odooApi;
diff --git a/src/core/components/elements/Footer/BasicFooter.jsx b/src/core/components/elements/Footer/BasicFooter.jsx
index 23bca677..28a3764c 100644
--- a/src/core/components/elements/Footer/BasicFooter.jsx
+++ b/src/core/components/elements/Footer/BasicFooter.jsx
@@ -1,14 +1,14 @@
-import NextImage from 'next/image'
-import IndoteknikLogo from '@/images/logo.png'
+import NextImage from 'next/image';
+import IndoteknikLogo from '@/images/logo.png';
import {
DevicePhoneMobileIcon,
EnvelopeIcon,
- PhoneArrowUpRightIcon
-} from '@heroicons/react/24/outline'
-import Link from '../Link/Link'
-import MobileView from '../../views/MobileView'
-import DesktopView from '../../views/DesktopView'
-import whatsappUrl from '@/core/utils/whatsappUrl'
+ PhoneArrowUpRightIcon,
+} from '@heroicons/react/24/outline';
+import Link from '../Link/Link';
+import MobileView from '../../views/MobileView';
+import DesktopView from '../../views/DesktopView';
+import whatsappUrl from '@/core/utils/whatsappUrl';
const BasicFooter = () => {
return (
@@ -17,9 +17,16 @@ const BasicFooter = () => {
<footer className='flex flex-wrap p-4 bg-gray_r-3 text-caption-1'>
<div className='w-1/2 flex flex-col gap-y-8 pr-2'>
<div>
- <NextImage src={IndoteknikLogo} alt='Logo Indoteknik' width={90} height={30} />
+ <NextImage
+ src={IndoteknikLogo}
+ alt='Logo Indoteknik'
+ width={90}
+ height={30}
+ />
- <div className='font-semibold mt-2'>PT. Indoteknik Dotcom Gemilang</div>
+ <div className='font-semibold mt-2'>
+ PT. Indoteknik Dotcom Gemilang
+ </div>
</div>
<OfficeLocation />
@@ -37,7 +44,8 @@ const BasicFooter = () => {
</div>
<div className='w-full mt-8 leading-5 text-caption-2 text-gray_r-12/80'>
- Copyright © 2007 - {new Date().getFullYear()}, PT. Indoteknik Dotcom Gemilang
+ Copyright © 2007 - {new Date().getFullYear()}, PT. Indoteknik Dotcom
+ Gemilang
</div>
</footer>
</MobileView>
@@ -46,8 +54,15 @@ const BasicFooter = () => {
<footer className='bg-gray_r-3 py-6'>
<div className='container mx-auto flex flex-wrap justify-between'>
<div className='w-3/12'>
- <NextImage src={IndoteknikLogo} alt='Logo Indoteknik' width={180} height={60} />
- <div className='font-semibold mt-2 mb-4'>PT. Indoteknik Dotcom Gemilang</div>
+ <NextImage
+ src={IndoteknikLogo}
+ alt='Logo Indoteknik'
+ width={180}
+ height={60}
+ />
+ <div className='font-semibold mt-2 mb-4'>
+ PT. Indoteknik Dotcom Gemilang
+ </div>
<InformationCenter />
</div>
<CustomerGuide />
@@ -64,7 +79,8 @@ const BasicFooter = () => {
<hr className='w-full my-4 border-gray_r-7' />
<div className='w-full flex justify-between items-center'>
<div className='text-caption-1'>
- Copyright © 2007 - {new Date().getFullYear()}, PT. Indoteknik Dotcom Gemilang
+ Copyright © 2007 - {new Date().getFullYear()}, PT. Indoteknik
+ Dotcom Gemilang
</div>
<div>
<SocialMedias />
@@ -74,39 +90,51 @@ const BasicFooter = () => {
</footer>
</DesktopView>
</>
- )
-}
+ );
+};
-const headerClassName = 'font-semibold mb-4'
+const headerClassName = 'font-semibold mb-4';
const OfficeLocation = () => (
<div>
<div className={headerClassName}>Kantor Pusat</div>
<div className='leading-6 text-gray_r-12/80'>
- <a href='https://goo.gl/maps/3DCJxtki8jUV32pR7' target='_blank' rel='noreferrer' className='text-gray_r-12/80'>
- Jl. Bandengan Utara 85A No. 8-9 RT.3/RW.16, Penjaringan, Kec. Penjaringan, Jakarta Utara</a>
+ <a
+ href='https://goo.gl/maps/3DCJxtki8jUV32pR7'
+ target='_blank'
+ rel='noreferrer'
+ className='text-gray_r-12/80'
+ >
+ Jl. Bandengan Utara 85A No. 8-9 RT.3/RW.16, Penjaringan, Kec.
+ Penjaringan, Jakarta Utara
+ </a>
</div>
</div>
-)
+);
const WarehouseLocation = () => (
<div>
<div className={headerClassName}>Gudang Indoteknik</div>
<div className='leading-6 text-gray_r-12/80'>
- Jl. Bandengan Utara Komp. 85 A dan B, Penjaringan, Kec. Penjaringan, Jakarta Utara
+ Jl. Bandengan Utara Komp. 85 A dan B, Penjaringan, Kec. Penjaringan,
+ Jakarta Utara
</div>
</div>
-)
+);
const AboutUs = () => (
<div>
<div className={headerClassName}>Tentang Kami</div>
<ul className='flex flex-col gap-y-3'>
<li>
- <InternalItemLink href='/tentang-kami'>Company Profile</InternalItemLink>
+ <InternalItemLink href='/tentang-kami'>
+ Company Profile
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/pelanggan-kami'>Pelanggan Kami</InternalItemLink>
+ <InternalItemLink href='/pelanggan-kami'>
+ Pelanggan Kami
+ </InternalItemLink>
</li>
<li>
<InternalItemLink href='/hubungi-kami'>Hubungi Kami</InternalItemLink>
@@ -115,30 +143,42 @@ const AboutUs = () => (
<InternalItemLink href='/karir'>Karir</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/syarat-ketentuan'>Syarat & Ketentuan</InternalItemLink>
+ <InternalItemLink href='/syarat-ketentuan'>
+ Syarat & Ketentuan
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/kebijakan-privasi'>Kebijakan Privasi</InternalItemLink>
+ <InternalItemLink href='/kebijakan-privasi'>
+ Kebijakan Privasi
+ </InternalItemLink>
</li>
</ul>
</div>
-)
+);
const CustomerGuide = () => (
<div>
<div className={headerClassName}>Bantuan & Panduan</div>
<ul className='flex flex-col gap-y-3'>
<li>
- <InternalItemLink href='/metode-pembayaran'>Metode Pembayaran</InternalItemLink>
+ <InternalItemLink href='/metode-pembayaran'>
+ Metode Pembayaran
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/metode-pengiriman'>Metode Pengiriman</InternalItemLink>
+ <InternalItemLink href='/metode-pengiriman'>
+ Metode Pengiriman
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/panduan-belanja'>Panduan Belanja</InternalItemLink>
+ <InternalItemLink href='/panduan-belanja'>
+ Panduan Belanja
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/panduan-quotation'>Panduan Quotation</InternalItemLink>
+ <InternalItemLink href='/panduan-quotation'>
+ Panduan Quotation
+ </InternalItemLink>
</li>
<li>
<InternalItemLink href='/pengembalian-barang-dana'>
@@ -146,40 +186,56 @@ const CustomerGuide = () => (
</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/informasi-garansi'>Informasi Garansi</InternalItemLink>
+ <InternalItemLink href='/informasi-garansi'>
+ Informasi Garansi
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/panduan-pick-up-service'>Panduan Pick Up Service</InternalItemLink>
+ <InternalItemLink href='/panduan-pick-up-service'>
+ Panduan Pick Up Service
+ </InternalItemLink>
</li>
</ul>
</div>
-)
+);
const Form = () => (
<div>
<div className={headerClassName}>Formulir</div>
<ul className='flex flex-col gap-y-3'>
<li>
- <InternalItemLink href='/my/request-for-quotation'>Request for Quotation</InternalItemLink>
+ <InternalItemLink href='/my/request-for-quotation'>
+ Request for Quotation
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/kunjungan-sales'>Kunjungan Sales</InternalItemLink>
+ <InternalItemLink href='/my/kunjungan-sales'>
+ Kunjungan Sales
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/kunjungan-service'>Kunjungan Service</InternalItemLink>
+ <InternalItemLink href='/my/kunjungan-service'>
+ Kunjungan Service
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/pembayaran-tempo'>Pembayaran Tempo</InternalItemLink>
+ <InternalItemLink href='/my/pembayaran-tempo'>
+ Pembayaran Tempo
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/surat-dukungan'>Surat Dukungan</InternalItemLink>
+ <InternalItemLink href='/my/surat-dukungan'>
+ Surat Dukungan
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/daftar-merchant'>Daftar Merchant</InternalItemLink>
+ <InternalItemLink href='/my/daftar-merchant'>
+ Daftar Merchant
+ </InternalItemLink>
</li>
</ul>
</div>
-)
+);
const InformationCenter = () => (
<div>
@@ -187,11 +243,15 @@ const InformationCenter = () => (
<ul className='flex flex-col gap-y-3'>
<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</a>
+ <a href='tel:02129338828' target='_blank' rel='noreferrer'>
+ (021) 2933-8828 / 29
+ </a>
</li>
<li className='text-gray_r-12/80 flex items-center'>
<EnvelopeIcon className='w-[18px] mr-2' />
- <a href='mailto:sales@indoteknik.com' target='_blank' rel='noreferrer'>sales@indoteknik.com</a>
+ <a href='mailto:sales@indoteknik.com' target='_blank' rel='noreferrer'>
+ sales@indoteknik.com
+ </a>
</li>
<li className='text-gray_r-12/80 flex items-center'>
<DevicePhoneMobileIcon className='w-[18px] mr-2' />
@@ -201,7 +261,7 @@ const InformationCenter = () => (
</li>
</ul>
</div>
-)
+);
const OpenHours = () => (
<div>
@@ -217,44 +277,124 @@ const OpenHours = () => (
</li>
</ul>
</div>
-)
+);
const SocialMedias = () => (
<div>
<div className={headerClassName + 'block md:hidden'}>Temukan Kami</div>
- <div className='flex flex-wrap gap-3 mt-2'>
+ <div className='flex flex-wrap gap-3 mt-2 items-center'>
+ <a
+ target='_blank'
+ rel='noreferrer'
+ href='https://www.youtube.com/@indoteknikb2bindustriale-c778'
+ >
+ <NextImage
+ src='/images/socials/youtube.webp'
+ alt='Youtube - Indoteknik.com'
+ width={24}
+ height={24}
+ />
+ </a>
+ <a
+ target='_blank'
+ rel='noreferrer'
+ href='https://www.tiktok.com/@indoteknikcom'
+ >
+ <NextImage
+ src='/images/socials/tiktok.png'
+ alt='TikTok - Indoteknik.com'
+ width={24}
+ height={24}
+ />
+ </a>
<a target='_blank' rel='noreferrer' href={whatsappUrl(null)}>
- <NextImage src='/images/socials/Whatsapp.png' alt='Whatsapp Logo' width={24} height={24} />
+ <NextImage
+ src='/images/socials/Whatsapp.png'
+ alt='Whatsapp - Indoteknik.com'
+ width={24}
+ height={24}
+ />
</a>
- <a target='_blank' rel='noreferrer' href='https://www.facebook.com/indoteknikcom'>
- <NextImage src='/images/socials/Facebook.png' alt='Facebook Logo' width={24} height={24} />
+ <a
+ target='_blank'
+ rel='noreferrer'
+ href='https://www.facebook.com/indoteknikcom'
+ >
+ <NextImage
+ src='/images/socials/Facebook.png'
+ alt='Facebook - Indoteknik.com'
+ width={24}
+ height={24}
+ />
</a>
- <a target='_blank' rel='noreferrer' href='https://www.instagram.com/indoteknikcom/'>
+ <a
+ target='_blank'
+ rel='noreferrer'
+ href='https://www.instagram.com/indoteknikcom/'
+ >
<NextImage
src='/images/socials/Instagram.png'
- alt='Instagram Logo'
+ alt='Instagram - Indoteknik.com'
width={24}
height={24}
/>
</a>
- <a target='_blank' rel='noreferrer' href='https://www.linkedin.com/company/pt-indoteknik-dotcom-gemilang/'>
- <NextImage src='/images/socials/Linkedin.png' alt='Linkedin Logo' width={24} height={24} />
+ <a
+ target='_blank'
+ rel='noreferrer'
+ href='https://www.linkedin.com/company/pt-indoteknik-dotcom-gemilang/'
+ >
+ <NextImage
+ src='/images/socials/Linkedin.png'
+ alt='Linkedin - Indoteknik.com'
+ width={24}
+ height={24}
+ />
</a>
- <a target='_blank' rel='noreferrer' href='https://goo.gl/maps/GF8EmDjpQTHZPsJ1A'>
- <NextImage src='/images/socials/g_maps.png' alt='Linkedin Logo' width={24} height={24} />
+ <a
+ target='_blank'
+ rel='noreferrer'
+ href='https://goo.gl/maps/GF8EmDjpQTHZPsJ1A'
+ >
+ <NextImage
+ src='/images/socials/g_maps.png'
+ alt='Maps - Indoteknik.com'
+ width={24}
+ height={24}
+ />
</a>
</div>
</div>
-)
+);
const Payments = () => (
<div>
<div className={headerClassName}>Pembayaran</div>
<div className='flex flex-wrap gap-2'>
- <NextImage src='/images/payments/bca.png' alt='Bank BCA Logo' width={48} height={24} />
- <NextImage src='/images/payments/bni.png' alt='Bank BNI Logo' width={48} height={24} />
- <NextImage src='/images/payments/bri.png' alt='Bank BRI Logo' width={48} height={24} />
- <NextImage src='/images/payments/gopay.png' alt='Gopay Logo' width={48} height={24} />
+ <NextImage
+ src='/images/payments/bca.png'
+ alt='Bank BCA Logo'
+ width={48}
+ height={24}
+ />
+ <NextImage
+ src='/images/payments/bni.png'
+ alt='Bank BNI Logo'
+ width={48}
+ height={24}
+ />
+ <NextImage
+ src='/images/payments/bri.png'
+ alt='Bank BRI Logo'
+ width={48}
+ height={24}
+ />
+ <NextImage
+ src='/images/payments/gopay.png'
+ alt='Gopay Logo'
+ width={48}
+ height={24}
+ />
<NextImage
src='/images/payments/mandiri.png'
alt='Bank Mandiri Logo'
@@ -273,15 +413,25 @@ const Payments = () => (
width={48}
height={24}
/>
- <NextImage src='/images/payments/visa.png' alt='Visa Logo' width={48} height={24} />
+ <NextImage
+ src='/images/payments/visa.png'
+ alt='Visa Logo'
+ width={48}
+ height={24}
+ />
</div>
</div>
-)
+);
const InternalItemLink = ({ href, children }) => (
- <Link href={href} className='!text-gray_r-12/80 font-normal line-clamp-1' target="_blank" rel="noopener noreferrer">
+ <Link
+ href={href}
+ className='!text-gray_r-12/80 font-normal line-clamp-1'
+ target='_blank'
+ rel='noopener noreferrer'
+ >
{children}
</Link>
-)
+);
-export default BasicFooter
+export default BasicFooter;
diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx
index a8cca416..5f034c09 100644
--- a/src/lib/product/components/Product/ProductDesktop.jsx
+++ b/src/lib/product/components/Product/ProductDesktop.jsx
@@ -441,11 +441,11 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => {
{sellingProductFormat(product?.qtySold) + ' Terjual'}
</div>
)}
- {lowestPrice?.isFlashsale && lowestPrice?.price.discountPercentage > 0 ? (
+ {product?.flashSale?.id && lowestPrice?.price.discountPercentage > 0 ? (
<>
<div className='flex gap-x-1 items-center mt-2'>
<div className='badge-solid-red text-caption-1'>
- {lowestPrice?.price?.discountPercentage}%
+ {Math.floor(lowestPrice?.price?.discountPercentage)}%
</div>
<div className='text-gray_r-9 line-through text-caption-1'>
{currencyFormat(lowestPrice?.price?.price)}
@@ -584,7 +584,7 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => {
<>
<div className='flex items-center gap-x-1 justify-center'>
<div className='badge-solid-red text-caption-1'>
- {variant?.price?.discountPercentage}%
+ {Math.floor(variant?.price?.discountPercentage)}%
</div>
<div className='line-through text-caption-1 text-gray_r-11'>
{currencyFormat(variant?.price?.price)}
diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx
index ef2c0002..e23e2fb9 100644
--- a/src/lib/product/components/Product/ProductMobile.jsx
+++ b/src/lib/product/components/Product/ProductMobile.jsx
@@ -260,7 +260,7 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
{activeVariant.isFlashsale && activeVariant?.price?.discountPercentage > 0 ? (
<>
<div className='flex gap-x-1 items-center'>
- <div className='badge-solid-red'>{activeVariant?.price?.discountPercentage}%</div>
+ <div className='badge-solid-red'>{Math.floor(activeVariant?.price?.discountPercentage)}%</div>
<div className='text-gray_r-11 line-through text-caption-1'>
{currencyFormat(activeVariant?.price?.price)}
</div>
diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx
index 9500a3fd..fa555bcf 100644
--- a/src/lib/product/components/ProductCard.jsx
+++ b/src/lib/product/components/ProductCard.jsx
@@ -12,6 +12,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
const callForPriceWhatsapp = whatsappUrl('product', {
name: product.name,
+ manufacture: product.manufacture?.name,
url: createSlug('/shop/product/', product.name, product.id, true)
})
@@ -41,7 +42,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
<div className='flex gap-x-1 items-center p-2 justify-center'>
<div className='bg-yellow-400 rounded-lg p-1 h-6 w-19 flex items-center justify-center '>
<span className='text-sm font-bold text-black'>
- {product?.lowestPrice.discountPercentage}%
+ {Math.floor(product?.lowestPrice.discountPercentage)}%
</span>
</div>
<div className='bg-red-600 border border-solid border-yellow-400 p-2 rounded-full h-6 flex w-fit items-center justify-center gap-x-2'>
@@ -102,7 +103,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
{product?.lowestPrice.priceDiscount > 0 ? (
currencyFormat(product?.lowestPrice.priceDiscount)
) : (
- <a href={callForPriceWhatsapp}>Call for Inquiry</a>
+ <a rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp}>
+ Call for Inquiry
+ </a>
)}
</div>
</>
@@ -117,7 +120,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
</div>
</>
) : (
- <a href={callForPriceWhatsapp}>Call for Inquiry</a>
+ <a rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp}>
+ Call for Inquiry
+ </a>
)}
</div>
)}
@@ -125,7 +130,11 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
<div className='flex w-full items-center gap-x-1 '>
{product?.stockTotal > 0 && <div className='badge-solid-red'>Ready Stock</div>}
{/* <div className='badge-gray'>{product?.stockTotal > 5 ? '> 5' : '< 5'}</div> */}
- {product?.qtySold > 0 && <div className='text-gray_r-9 text-[11px]'>{sellingProductFormat(product?.qtySold) + ' Terjual'}</div>}
+ {product?.qtySold > 0 && (
+ <div className='text-gray_r-9 text-[11px]'>
+ {sellingProductFormat(product?.qtySold) + ' Terjual'}
+ </div>
+ )}
</div>
</div>
</div>
@@ -205,7 +214,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
{product?.lowestPrice?.priceDiscount > 0 ? (
currencyFormat(product?.lowestPrice?.priceDiscount)
) : (
- <a href={callForPriceWhatsapp}>Call for Inquiry</a>
+ <a rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp}>
+ Call for Inquiry
+ </a>
)}
</div>
</>
@@ -220,7 +231,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
</div>
</>
) : (
- <a href={callForPriceWhatsapp}>Call for Inquiry</a>
+ <a rel='noopener noreferrer' target='_blank' href={callForPriceWhatsapp}>
+ Call for Inquiry
+ </a>
)}
</div>
)}
@@ -228,7 +241,11 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
<div className='flex w-full items-center gap-x-1 '>
{product?.stockTotal > 0 && <div className='badge-solid-red'>Ready Stock</div>}
{/* <div className='badge-gray'>{product?.stockTotal > 5 ? '> 5' : '< 5'}</div> */}
- {product?.qtySold > 0 && <div className='text-gray_r-9 text-[11px]'>{sellingProductFormat(product?.qtySold) + ' Terjual'}</div>}
+ {product?.qtySold > 0 && (
+ <div className='text-gray_r-9 text-[11px]'>
+ {sellingProductFormat(product?.qtySold) + ' Terjual'}
+ </div>
+ )}
</div>
</div>
</div>
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index a4e9ecbb..29bb987e 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -20,6 +20,7 @@ import odooApi from '@/core/api/odooApi'
import { formatCurrency } from '@/core/utils/formatValue'
import axios from 'axios'
import Skeleton from 'react-loading-skeleton'
+import { createSlug } from '@/core/utils/slug'
const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null }) => {
const router = useRouter()
@@ -87,13 +88,16 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null })
const brand = await axios(
`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/brands?params=search&q=${search}`
)
+ console.log('ini brand', brand)
if (brand.data.length > 0) {
setIsBrand(brand?.data[0])
} else {
setIsBrand(null)
}
}
- checkIfBrand()
+ if (router.pathname.includes('search')) {
+ checkIfBrand()
+ }
}, [q])
const brands = []
@@ -362,11 +366,12 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null, brand = null })
{isBrand && isBrand.logo && (
<div className='mb-3'>
<h1 className='text-2xl mb-2 font-semibold'>Brand Pencarian {q}</h1>
- <Image
- src={isBrand?.logo}
- alt=''
- className='object-cover object-center h-[100px]'
- />
+ <Link
+ href={createSlug('/shop/brands/', isBrand.name, isBrand.id)}
+ className='inline'
+ >
+ <Image src={isBrand?.logo} alt='' className='object-cover object-center h-24' />
+ </Link>
</div>
)}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 64f3ac10..65d953d2 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -1,46 +1,64 @@
-import dynamic from 'next/dynamic'
-import MobileView from '@/core/components/views/MobileView'
-import DesktopView from '@/core/components/views/DesktopView'
-import { useRef } from 'react'
-import Seo from '@/core/components/Seo'
-import DelayRender from '@/core/components/elements/DelayRender/DelayRender'
-import { HeroBannerSkeleton } from '@/components/skeleton/BannerSkeleton'
-import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton'
-import PromotinProgram from '@/lib/promotinProgram/components/HomePage'
-import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBrandSkeleton'
-import { FlashSaleSkeleton } from '@/lib/flashSale/skeleton/FlashSaleSkeleton'
+import dynamic from 'next/dynamic';
+import MobileView from '@/core/components/views/MobileView';
+import DesktopView from '@/core/components/views/DesktopView';
+import { useRef } from 'react';
+import Seo from '@/core/components/Seo';
+import DelayRender from '@/core/components/elements/DelayRender/DelayRender';
+import { HeroBannerSkeleton } from '@/components/skeleton/BannerSkeleton';
+import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton';
+import PromotinProgram from '@/lib/promotinProgram/components/HomePage';
+import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBrandSkeleton';
+import { FlashSaleSkeleton } from '@/lib/flashSale/skeleton/FlashSaleSkeleton';
+import PagePopupIformation from '~/modules/popup-information';
-const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const BasicLayout = dynamic(() =>
+ import('@/core/components/layouts/BasicLayout')
+);
const HeroBanner = dynamic(() => import('@/components/ui/HeroBanner'), {
- loading: () => <HeroBannerSkeleton />
-})
-const HeroBannerSecondary = dynamic(() => import('@/components/ui/HeroBannerSecondary'), {
- loading: () => <HeroBannerSkeleton />
-})
+ loading: () => <HeroBannerSkeleton />,
+});
+const HeroBannerSecondary = dynamic(
+ () => import('@/components/ui/HeroBannerSecondary'),
+ {
+ loading: () => <HeroBannerSkeleton />,
+ }
+);
const PopularProduct = dynamic(() => import('@/components/ui/PopularProduct'), {
- loading: () => <PopularProductSkeleton />
-})
+ loading: () => <PopularProductSkeleton />,
+});
-const PreferredBrand = dynamic(() => import('@/lib/home/components/PreferredBrand'), {
- loading: () => <PreferredBrandSkeleton />
-})
+const PreferredBrand = dynamic(
+ () => import('@/lib/home/components/PreferredBrand'),
+ {
+ loading: () => <PreferredBrandSkeleton />,
+ }
+);
-const FlashSale = dynamic(() => import('@/lib/flashSale/components/FlashSale'), {
- loading: () => <FlashSaleSkeleton />
-})
-const BannerSection = dynamic(() => import('@/lib/home/components/BannerSection'))
-const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId'))
-const CustomerReviews = dynamic(() => import('@/lib/review/components/CustomerReviews'))
-const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList'))
+const FlashSale = dynamic(
+ () => import('@/lib/flashSale/components/FlashSale'),
+ {
+ loading: () => <FlashSaleSkeleton />,
+ }
+);
+const BannerSection = dynamic(() =>
+ import('@/lib/home/components/BannerSection')
+);
+const CategoryHomeId = dynamic(() =>
+ import('@/lib/home/components/CategoryHomeId')
+);
+const CustomerReviews = dynamic(() =>
+ import('@/lib/review/components/CustomerReviews')
+);
+const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList'));
export default function Home() {
- const bannerRef = useRef(null)
- const wrapperRef = useRef(null)
+ const bannerRef = useRef(null);
+ const wrapperRef = useRef(null);
const handleOnLoad = () => {
wrapperRef.current.style.height =
- bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px'
- }
+ bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px';
+ };
return (
<BasicLayout>
@@ -51,14 +69,19 @@ export default function Home() {
{
name: 'keywords',
content:
- 'indoteknik, indoteknik.com, toko teknik, toko perkakas, jual genset, jual fogging, jual krisbow, harga krisbow, harga alat safety, harga pompa air'
- }
+ 'indoteknik, indoteknik.com, toko teknik, toko perkakas, jual genset, jual fogging, jual krisbow, harga krisbow, harga alat safety, harga pompa air',
+ },
]}
/>
<DesktopView>
+ <PagePopupIformation />
<div className='container mx-auto'>
- <div className='flex min-h-[400px] h-[460px]' ref={wrapperRef} onLoad={handleOnLoad}>
+ <div
+ className='flex min-h-[400px] h-[460px]'
+ ref={wrapperRef}
+ onLoad={handleOnLoad}
+ >
<div className='w-2/12'>
<HeroBannerSecondary />
</div>
@@ -85,6 +108,7 @@ export default function Home() {
</DesktopView>
<MobileView>
+ <PagePopupIformation />
<DelayRender renderAfter={200}>
<HeroBanner />
</DelayRender>
@@ -114,5 +138,5 @@ export default function Home() {
</div>
</MobileView>
</BasicLayout>
- )
+ );
}