diff options
| author | trisusilo <tri.susilo@altama.co.id> | 2023-12-05 02:59:30 +0000 |
|---|---|---|
| committer | trisusilo <tri.susilo@altama.co.id> | 2023-12-05 02:59:30 +0000 |
| commit | 80caa8f6ad5fecc213fd1533b972c6173102721e (patch) | |
| tree | f70c8ec03cf2a1cdb8eb3f30ecd83e200986b70b | |
| parent | eca358fd93f1ea5d88c6a6fcc315624cc3bbb910 (diff) | |
| parent | 4ac372ff318ee78e5d5019a1dbe95bf47b661766 (diff) | |
Merged in Feature/popup_information (pull request #118)
Feature/popup information
| -rw-r--r-- | public/images/socials/tiktok.png | bin | 0 -> 3436 bytes | |||
| -rw-r--r-- | public/images/socials/youtube.webp | bin | 0 -> 12624 bytes | |||
| -rw-r--r-- | src-migrate/common/components/elements/Seo.tsx | 34 | ||||
| -rw-r--r-- | src-migrate/modules/page-content/index.tsx | 15 | ||||
| -rw-r--r-- | src-migrate/modules/popup-information/index.tsx | 38 | ||||
| -rw-r--r-- | src-migrate/pages/register.tsx | 2 | ||||
| -rw-r--r-- | src/core/api/odooApi.js | 71 | ||||
| -rw-r--r-- | src/core/components/elements/Footer/BasicFooter.jsx | 280 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductDesktop.jsx | 6 | ||||
| -rw-r--r-- | src/lib/product/components/Product/ProductMobile.jsx | 2 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 31 | ||||
| -rw-r--r-- | src/lib/product/components/ProductSearch.jsx | 17 | ||||
| -rw-r--r-- | src/pages/index.jsx | 98 |
13 files changed, 441 insertions, 153 deletions
diff --git a/public/images/socials/tiktok.png b/public/images/socials/tiktok.png Binary files differnew file mode 100644 index 00000000..0347362a --- /dev/null +++ b/public/images/socials/tiktok.png diff --git a/public/images/socials/youtube.webp b/public/images/socials/youtube.webp Binary files differnew file mode 100644 index 00000000..3e023fcc --- /dev/null +++ b/public/images/socials/youtube.webp 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> - ) + ); } |
