summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/favicon.icobin25931 -> 1150 bytes
-rw-r--r--public/images/default-banner-brand.jpgbin0 -> 53938 bytes
-rw-r--r--public/images/page-not-found.svg9
-rw-r--r--public/images/socials/WHATSAPP.svg24
-rw-r--r--src/core/api/searchSpellApi.js14
-rw-r--r--src/core/api/searchSuggestApi.js4
-rw-r--r--src/core/components/elements/CountDown/CountDown.jsx64
-rw-r--r--src/core/components/elements/Footer/BasicFooter.jsx69
-rw-r--r--src/core/components/elements/Footer/SimpleFooter.jsx3
-rw-r--r--src/core/components/elements/Navbar/NavbarDesktop.jsx12
-rw-r--r--src/core/components/elements/Navbar/NavbarMobile.jsx4
-rw-r--r--src/core/components/elements/Navbar/NavbarUserDropdown.jsx1
-rw-r--r--src/core/components/elements/Navbar/Search.jsx10
-rw-r--r--src/core/components/elements/Navbar/TopBanner.jsx25
-rw-r--r--src/core/components/elements/Sidebar/Sidebar.jsx5
-rw-r--r--src/core/components/layouts/BasicLayout.jsx28
-rw-r--r--src/core/utils/slug.js6
-rw-r--r--src/core/utils/whatsappUrl.js24
-rw-r--r--src/lib/auth/components/CompanyProfile.jsx2
-rw-r--r--src/lib/auth/components/Menu.jsx7
-rw-r--r--src/lib/auth/components/PersonalProfile.jsx4
-rw-r--r--src/lib/auth/components/RegisterDesktop.jsx14
-rw-r--r--src/lib/auth/components/RegisterMobile.jsx11
-rw-r--r--src/lib/auth/hooks/useRegister.js13
-rw-r--r--src/lib/brand/components/Brand.jsx29
-rw-r--r--src/lib/cart/components/Cart.jsx156
-rw-r--r--src/lib/category/components/Category.jsx11
-rw-r--r--src/lib/checkout/components/Checkout.jsx18
-rw-r--r--src/lib/checkout/components/FinishCheckout.jsx2
-rw-r--r--src/lib/checkout/email/FinishCheckoutEmail.jsx3
-rw-r--r--src/lib/content/components/PageContent.jsx19
-rw-r--r--src/lib/flashSale/api/flashSaleApi.js8
-rw-r--r--src/lib/flashSale/components/FlashSale.jsx66
-rw-r--r--src/lib/form/components/KunjunganService.jsx70
-rw-r--r--src/lib/form/components/MediaRelations.jsx237
-rw-r--r--src/lib/form/components/Merchant.jsx264
-rw-r--r--src/lib/form/components/PembayaranTempo.jsx2
-rw-r--r--src/lib/form/components/SuratDukungan.jsx140
-rw-r--r--src/lib/home/components/HeroBanner.jsx9
-rw-r--r--src/lib/home/components/PreferredBrand.jsx2
-rw-r--r--src/lib/invoice/components/Invoices.jsx12
-rw-r--r--src/lib/product/api/productApi.js4
-rw-r--r--src/lib/product/api/productSearchApi.js4
-rw-r--r--src/lib/product/components/Product/ProductDesktop.jsx209
-rw-r--r--src/lib/product/components/Product/ProductMobile.jsx25
-rw-r--r--src/lib/product/components/ProductCard.jsx10
-rw-r--r--src/lib/product/components/ProductSearch.jsx64
-rw-r--r--src/lib/quotation/components/Quotation.jsx9
-rw-r--r--src/lib/transaction/components/Transaction.jsx2
-rw-r--r--src/lib/transaction/components/Transactions.jsx19
-rw-r--r--src/lib/variant/components/VariantCard.jsx9
-rw-r--r--src/pages/404.jsx22
-rw-r--r--src/pages/_app.jsx35
-rw-r--r--src/pages/_document.jsx22
-rw-r--r--src/pages/activate.jsx8
-rw-r--r--src/pages/api/shop/finish-checkout.js2
-rw-r--r--src/pages/api/shop/midtrans-payment.js15
-rw-r--r--src/pages/api/shop/search.js54
-rw-r--r--src/pages/api/shop/spell.js18
-rw-r--r--src/pages/blog/[slug].jsx7
-rw-r--r--src/pages/blog/index.jsx12
-rw-r--r--src/pages/contact-us.jsx12
-rw-r--r--src/pages/faqs.jsx12
-rw-r--r--src/pages/hubungi-kami.jsx17
-rw-r--r--src/pages/index.jsx26
-rw-r--r--src/pages/informasi-garansi.jsx17
-rw-r--r--src/pages/karir.jsx17
-rw-r--r--src/pages/kebijakan-privasi.jsx17
-rw-r--r--src/pages/metode-pembayaran.jsx17
-rw-r--r--src/pages/metode-pengiriman.jsx17
-rw-r--r--src/pages/my/daftar-merchant.jsx15
-rw-r--r--src/pages/my/invoices/[id].jsx (renamed from src/pages/my/invoice/[id].jsx)2
-rw-r--r--src/pages/my/invoices/index.jsx (renamed from src/pages/my/invoices.jsx)2
-rw-r--r--src/pages/my/kunjungan-sales.jsx2
-rw-r--r--src/pages/my/kunjungan-service.jsx3
-rw-r--r--src/pages/my/media-relations.jsx15
-rw-r--r--src/pages/my/menu.jsx1
-rw-r--r--src/pages/my/pembayaran-tempo.jsx2
-rw-r--r--src/pages/my/quotations/[id].jsx (renamed from src/pages/my/transaction/[id].jsx)2
-rw-r--r--src/pages/my/quotations/index.jsx26
-rw-r--r--src/pages/my/surat-dukungan.jsx3
-rw-r--r--src/pages/my/transactions/[id].jsx27
-rw-r--r--src/pages/my/transactions/index.jsx (renamed from src/pages/my/transactions.jsx)2
-rw-r--r--src/pages/panduan-belanja.jsx17
-rw-r--r--src/pages/panduan-pick-up-service.jsx17
-rw-r--r--src/pages/panduan-quotation.jsx17
-rw-r--r--src/pages/pelanggan-kami.jsx17
-rw-r--r--src/pages/pengembalian-barang-dana.jsx17
-rw-r--r--src/pages/shop/category/[slug].jsx37
-rw-r--r--src/pages/shop/product/[slug].jsx49
-rw-r--r--src/pages/shop/quotation/finish.jsx2
-rw-r--r--src/pages/sitemap/blogs.xml.js31
-rw-r--r--src/pages/sitemap/brands.xml.js31
-rw-r--r--src/pages/sitemap/categories.xml.js41
-rw-r--r--src/pages/sitemap/products.xml.js5
-rw-r--r--src/pages/sitemap/products/[id].xml.js32
-rw-r--r--src/pages/sitemap/products/[page].js35
-rw-r--r--src/pages/syarat-ketentuan.jsx17
-rw-r--r--src/pages/tentang-kami.jsx (renamed from src/pages/about-us.jsx)2
99 files changed, 2068 insertions, 504 deletions
diff --git a/public/favicon.ico b/public/favicon.ico
index 718d6fea..2fd36c90 100644
--- a/public/favicon.ico
+++ b/public/favicon.ico
Binary files differ
diff --git a/public/images/default-banner-brand.jpg b/public/images/default-banner-brand.jpg
new file mode 100644
index 00000000..e9b0d625
--- /dev/null
+++ b/public/images/default-banner-brand.jpg
Binary files differ
diff --git a/public/images/page-not-found.svg b/public/images/page-not-found.svg
new file mode 100644
index 00000000..d7a4c8aa
--- /dev/null
+++ b/public/images/page-not-found.svg
@@ -0,0 +1,9 @@
+<svg width="396" height="233" viewBox="0 0 396 233" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<rect width="396" height="232.69" fill="url(#pattern0)"/>
+<defs>
+<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
+<use xlink:href="#image0_147_212" transform="matrix(0.000544075 0 0 0.000925926 -0.0223121 0)"/>
+</pattern>
+<image id="image0_147_212" width="1920" height="1080" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAAQ4CAMAAADfDTFxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAwBQTFRFZDE72OTmmM6iaHF4/vXWmqWoiiYw2+fopqmqlX4lr5AbiIe3/e672KoM5eTveYiN73R75O3u+tBFx9TZpaDI1aqujJaa+ckoZbZzVmJpMT1214+VzOfQ2XR87/T0e24v1OLk+957WbBoWVOavMnM8vH39JoEtdXE/OWXOUdKcn2CqbCy8YOJwRQk1NjZ4gYTtBokurq64uTlk5aa5Bcji8iWTVlh7WUK7WRsTjdC6UROTKlb3kRMZ2Si5SYx9/n6zM/S+MHEM25HRlNafnmw4T1GPqRQstq5mZ+jgb+ToCAqS0KS9KKnwsPEwwAT2tvct73AcnCps7rQr7Ma0sXJgIeMZF83ebuGnqLDPTWK5zU/8fLzho6TaKg0PUhR8pKYlJe+i5yg0eDjvcbXqa/K++Dicrt/7LgF0dLUMohF1gUT+MMQ9rG14XmAQEtU5ktS+tDTcbNW61lgMSeCiq4sY2tyrrq9zBMd3zM93+nqM1tI4xgW61Rd8PX26DcOsLKz0N/iuMpttrouKDtCs8DEm7Sg4LC0oVhTjlIq592WycnJ0Zug1+PmRj+Ps7e75ufonb5YMVVq8/f41xAa3Fxk4g0Xrc+Q6tV2Mp5E+L8A3MxT28Ewv8PGoK6x4Jaa5OOu19uU2Wlwqri82oSKusbIMz9Jxz8YNHxU36KnzMzMUUuVPjxGv7+/4CEtqc+7////o7O3hoaG/e/wx58SZV2hsa7Q8vnzmJPAy8ng2Nbn3ujq2O3c5+/wf8OK5fPoxsvM0+Hk1uPlcWuovrvY3OfpGi41pdStv+DFMpdIubq8WFc7//vv1N3kTE9A/fDw+9dgoocgjo6O9/f31OTgPlBWMphEMpJG+fv7n8ux+/z8/f7+YG914ers093fXng4/P39lSMt4L7CtS8fr7ix9agCZKlv383P4MDC0Nri3ufMQZJA97MBf66IqLW51boOQodVZ5J+3unpp5yg07e7tcDPT2CISEOItMizvtilMnxG4tNp1+Tm2dbZWX5rW1Ze////ehIWDwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAOYwSURBVHja7L1bTGVXmqBZcQQKS4QQSSDiUDpjRYAYBwEJSgwSAhkPA4ZMgVU4UqgMKIVFGCpHEVJQJl9CHaWMLjQPVbKVXZai+9D9UP3WktWVkhF3DDjAASWFFSG7NG1nRUj1NFLVS057VA8zXTU6w+F6Lvuy9t5rrb32Pt+nVnVmxuFc9jlrfXv9/7/+9QcZAAAA0M4fcAkAAAAQMAAAAAIGAAAABAwAAICAAQAAAAEDAAAgYAAAAEDAAAAACBgAAAAQMAAAAAIGAABAwAAAAICAAQAAEDAAAAAgYAAAAAQMAAAACBgAAAABAwAAAAIGAABAwAAAAAgYAAAAEDAAAAACBgAAAAQMAACAgAEAAAABAwAAIGAAAABAwAAAAAgYAAAAAQMAAAACBgAAQMAAAACAgAEAABAwAAAAIGAAAAAEDAAAAAgYAAAAAQMAACBgAAAAQMAAAAAIGAAAABAwAAAAAgYAAAAEDAAAgIABAAAAAQMAACBgAAAABAwAAAAIGAAAAAEDAAAAAgYAAEDAAAAAgIABAAAQMAAAACBgAAAABAwAAICAAQAAAAEDAAAgYAAAAEDAAAAACBgAAAAQMAAAAAIGAAAABAwAAICAAQAAEDAAAAAgYAAAAAQMAAAACBgAAAABAwAAAAIGAABAwAAAAICAAQAAEDAAAAACBgAAAAQMAACAgAEAAAABAwAAIGAAAABAwAAAAAgYAAAAEDAAAAACBgAAQMAAAACAgAEAABAwAAAAIGAAAAAEDAAAAAgYAAAAAQMAAAACBgAAQMAAAACAgAEAABAwAAAAAgYAAAAEDAAAgIABAAAAAQMAACBgAAAAQMAAAAAIGAAAABAwAAAAAgYAAEDAAAAAgIABAAAQMAAAACBgAAAABAwAAAAIGAAA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"/>
+</defs>
+</svg>
diff --git a/public/images/socials/WHATSAPP.svg b/public/images/socials/WHATSAPP.svg
new file mode 100644
index 00000000..02a3cfad
--- /dev/null
+++ b/public/images/socials/WHATSAPP.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 283.46 283.46" style="enable-background:new 0 0 283.46 283.46;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#FFFFFF;}
+ .st1{fill:#4FB84A;}
+</style>
+<g>
+ <path class="st0" d="M260.49,140.6c0.01,58.15-42.59,108.17-99.35,117.23c-24.14,3.85-47.31,0.8-69.49-9.48
+ c-1.88-0.87-3.56-1.1-5.69-0.59c-18.45,4.46-36.95,8.76-55.43,13.08c-5.59,1.31-8.04-1.1-6.86-6.8c3.85-18.6,7.71-37.2,11.64-55.78
+ c0.54-2.57,0.09-4.75-1.04-7.13C1.85,123.01,42.4,40.71,116.07,25c65.86-14.05,128.92,27.21,142.19,93.05
+ C259.79,125.64,260.29,133.35,260.49,140.6z"/>
+ <path class="st1" d="M55.23,228.54c2.09-10.27,3.73-19.95,6.12-29.44c1.39-5.54,0.66-10.11-1.91-15.18
+ C39.26,144.11,47.78,99.38,81.45,70.1c18.86-16.4,41.2-23.43,66.22-22.05c40.78,2.24,75.97,32.36,85.09,73.17
+ c10.96,49.05-21.7,100.17-70.88,110.37c-23.02,4.77-44.74,1.46-65.36-9.55c-3.03-1.62-5.78-1.97-9.17-1.09
+ C76.92,223.64,66.39,225.93,55.23,228.54z"/>
+ <path class="st0" d="M172.37,198.61c-12.61-0.32-24.66-4.66-35.72-11.76c-19.98-12.81-37.15-28.49-48.42-49.73
+ c-5.1-9.61-7.99-19.98-5.55-30.94c2.11-9.47,8.46-16.24,16.2-21.56c3.78-2.59,9.1-0.84,11.15,3.41c3.65,7.6,6.97,15.36,10.29,23.11
+ c1.23,2.87,0.44,5.63-1.35,8.08c-1.39,1.91-2.88,3.75-4.29,5.65c-3.02,4.1-3.19,7.43-0.26,11.62c6.06,8.66,13.93,15.57,21.96,22.3
+ c4.48,3.76,9.17,7.27,14.39,9.96c5.19,2.68,8.76,2.52,12.35-1.91c5.46-6.73,11.45-8.63,19.6-5.1c4.96,2.15,10.47,3.02,15.69,4.6
+ c6.84,2.08,9.09,8.1,5.07,14.02c-5.23,7.71-11.03,14.86-20.8,17.06C179.53,198.17,176.32,198.6,172.37,198.61z"/>
+</g>
+</svg>
diff --git a/src/core/api/searchSpellApi.js b/src/core/api/searchSpellApi.js
new file mode 100644
index 00000000..4794c3e1
--- /dev/null
+++ b/src/core/api/searchSpellApi.js
@@ -0,0 +1,14 @@
+import axios from 'axios'
+
+const searchSpellApi = async ({ query }) => {
+ const dataSearchSpell = await axios(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/spell?q=${query.trim()}`
+ )
+ return dataSearchSpell
+}
+
+searchSpellApi.defaultProps = {
+ query: ''
+}
+
+export default searchSpellApi
diff --git a/src/core/api/searchSuggestApi.js b/src/core/api/searchSuggestApi.js
index 3dabfbd6..c65405e3 100644
--- a/src/core/api/searchSuggestApi.js
+++ b/src/core/api/searchSuggestApi.js
@@ -1,8 +1,10 @@
import axios from 'axios'
const searchSuggestApi = async ({ query }) => {
+ query = query.replace('&', '').trim()
+ if (!query) return {}
const dataSearchSuggest = await axios(
- `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/suggest?q=${query.trim()}`
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/suggest?q=${query}`
)
return dataSearchSuggest
}
diff --git a/src/core/components/elements/CountDown/CountDown.jsx b/src/core/components/elements/CountDown/CountDown.jsx
new file mode 100644
index 00000000..91a1f68e
--- /dev/null
+++ b/src/core/components/elements/CountDown/CountDown.jsx
@@ -0,0 +1,64 @@
+import { useEffect, useState } from 'react'
+
+const CountDown = ({ initialTime }) => {
+ const days = Math.floor(initialTime / 86400)
+ const hours = Math.floor((initialTime % 86400) / 3600)
+ const minutes = Math.floor((initialTime % 3600) / 60)
+ const seconds = initialTime % 60
+
+ const [timeLeft, setTimeLeft] = useState({
+ day: days,
+ hour: hours,
+ minute: minutes,
+ second: seconds
+ })
+
+ useEffect(() => {
+ const timer = setInterval(() => {
+ const totalSeconds =
+ timeLeft.day * 86400 + timeLeft.hour * 3600 + timeLeft.minute * 60 + timeLeft.second
+ const secondsLeft = totalSeconds - 1
+ if (secondsLeft < 0) {
+ clearInterval(timer)
+ } else {
+ const days = Math.floor(secondsLeft / 86400)
+ const hours = Math.floor((secondsLeft % 86400) / 3600)
+ const minutes = Math.floor((secondsLeft % 3600) / 60)
+ const seconds = secondsLeft % 60
+ setTimeLeft({ day: days, hour: hours, minute: minutes, second: seconds })
+ }
+ }, 1000)
+ return () => clearInterval(timer)
+ }, [timeLeft])
+
+ return (
+ <div className='flex gap-x-2.5 w-fit'>
+ <div className='flex flex-col items-center'>
+ <span className='bg-red-600 text-white font-semibold w-10 h-10 flex items-center justify-center rounded'>
+ {timeLeft.day.toString().padStart(2, '0')}
+ </span>
+ <span className='text-caption-1 text-gray-700 mt-1'>Hari</span>
+ </div>
+ <div className='flex flex-col items-center'>
+ <span className='bg-red-600 text-white font-semibold w-10 h-10 flex items-center justify-center rounded'>
+ {timeLeft.hour.toString().padStart(2, '0')}
+ </span>
+ <span className='text-caption-1 text-gray-700 mt-1'>Jam</span>
+ </div>
+ <div className='flex flex-col items-center'>
+ <span className='bg-red-600 text-white font-semibold w-10 h-10 flex items-center justify-center rounded'>
+ {timeLeft.minute.toString().padStart(2, '0')}
+ </span>
+ <span className='text-caption-1 text-gray-700 mt-1'>Menit</span>
+ </div>
+ <div className='flex flex-col items-center'>
+ <span className='bg-red-600 text-white font-semibold w-10 h-10 flex items-center justify-center rounded'>
+ {timeLeft.second.toString().padStart(2, '0')}
+ </span>
+ <span className='text-caption-1 text-gray-700 mt-1'>Detik</span>
+ </div>
+ </div>
+ )
+}
+
+export default CountDown
diff --git a/src/core/components/elements/Footer/BasicFooter.jsx b/src/core/components/elements/Footer/BasicFooter.jsx
index 42698cb2..d340ff3e 100644
--- a/src/core/components/elements/Footer/BasicFooter.jsx
+++ b/src/core/components/elements/Footer/BasicFooter.jsx
@@ -8,6 +8,7 @@ import {
import Link from '../Link/Link'
import MobileView from '../../views/MobileView'
import DesktopView from '../../views/DesktopView'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const BasicFooter = () => {
return (
@@ -22,6 +23,7 @@ const BasicFooter = () => {
</div>
<OfficeLocation />
+ <AboutUs />
{/* <WarehouseLocation /> */}
<InformationCenter />
<OpenHours />
@@ -29,7 +31,7 @@ const BasicFooter = () => {
</div>
<div className='w-1/2 flex flex-col gap-y-4 pl-1.5'>
- <AboutUs />
+ <Form />
<CustomerGuide />
<Payments />
</div>
@@ -49,6 +51,7 @@ const BasicFooter = () => {
<InformationCenter />
</div>
<CustomerGuide />
+ <Form />
<AboutUs />
<div className='w-3/12'>
<div className='grid grid-cols-1 gap-y-4'>
@@ -99,31 +102,22 @@ const AboutUs = () => (
<div className={`${headerClassName} mb-3`}>Tentang Kami</div>
<ul className='flex flex-col gap-y-2'>
<li>
- <InternalItemLink href='/'>Company Profile</InternalItemLink>
- </li>
- <li>
- <InternalItemLink href='/'>Karir</InternalItemLink>
- </li>
- <li>
- <InternalItemLink href='/'>Pelanggan Kami</InternalItemLink>
+ <InternalItemLink href='/tentang-kami'>Company Profile</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Menjadi Supplier</InternalItemLink>
+ <InternalItemLink href='/pelanggan-kami'>Pelanggan Kami</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Garansi dan Pengembalian</InternalItemLink>
+ <InternalItemLink href='/hubungi-kami'>Hubungi Kami</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Metode Pembayaran</InternalItemLink>
+ <InternalItemLink href='/karir'>Karir</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Metode Pengiriman</InternalItemLink>
+ <InternalItemLink href='/syarat-ketentuan'>Syarat & Ketentuan</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Testimonial</InternalItemLink>
- </li>
- <li>
- <InternalItemLink href='/'>Kebijakan Privacy</InternalItemLink>
+ <InternalItemLink href='/kebijakan-privasi'>Kebijakan Privasi</InternalItemLink>
</li>
</ul>
</div>
@@ -131,34 +125,53 @@ const AboutUs = () => (
const CustomerGuide = () => (
<div>
- <div className={`${headerClassName} mb-3`}>Panduan Pelanggan</div>
+ <div className={`${headerClassName} mb-3`}>Bantuan & Panduan</div>
<ul className='flex flex-col gap-y-2'>
<li>
- <InternalItemLink href='/'>Panduan Belanja</InternalItemLink>
+ <InternalItemLink href='/metode-pembayaran'>Metode Pembayaran</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>F.A.Q</InternalItemLink>
+ <InternalItemLink href='/metode-pengiriman'>Metode Pengiriman</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Kebijakan Privasi</InternalItemLink>
+ <InternalItemLink href='/panduan-belanja'>Panduan Belanja</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Pengajuan Tempo</InternalItemLink>
+ <InternalItemLink href='/panduan-quotation'>Panduan Quotation</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Garansi Produk</InternalItemLink>
+ <InternalItemLink href='/pengembalian-barang-dana'>
+ Pengembalian Barang & Dana
+ </InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Online Quotation</InternalItemLink>
+ <InternalItemLink href='/informasi-garansi'>Informasi Garansi</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Pengiriman</InternalItemLink>
+ <InternalItemLink href='/panduan-pick-up-service'>Panduan Pick Up Service</InternalItemLink>
+ </li>
+ </ul>
+ </div>
+)
+
+const Form = () => (
+ <div>
+ <div className={`${headerClassName} mb-3`}>Formulir</div>
+ <ul className='flex flex-col gap-y-2'>
+ <li>
+ <InternalItemLink href='/my/kunjungan-sales'>Kunjungan Sales</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Pembayaran</InternalItemLink>
+ <InternalItemLink href='/my/kunjungan-service'>Kunjungan Service</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/'>Syarat & Ketentuan</InternalItemLink>
+ <InternalItemLink href='/my/pembayaran-tempo'>Pembayaran Tempo</InternalItemLink>
+ </li>
+ <li>
+ <InternalItemLink href='/my/surat-dukungan'>Surat Dukungan</InternalItemLink>
+ </li>
+ <li>
+ <InternalItemLink href='/my/daftar-merchant'>Daftar Merchant</InternalItemLink>
</li>
</ul>
</div>
@@ -178,7 +191,7 @@ const InformationCenter = () => (
</li>
<li className='text-gray_r-12/80 flex items-center'>
<DevicePhoneMobileIcon className='w-[18px] mr-2' />
- <a href='https://wa.me/628128080622' target='_blank' rel='noreferrer'>
+ <a href={whatsappUrl()} target='_blank' rel='noreferrer'>
0812-8080-622
</a>
</li>
@@ -205,7 +218,7 @@ const OpenHours = () => (
const SocialMedias = () => (
<div>
<div className={headerClassName + 'block md:hidden'}>Temukan Kami</div>
- <div className='flex flex-wrap gap-2'>
+ <div className='flex flex-wrap gap-2 mt-2'>
<NextImage src='/images/socials/Whatsapp.png' alt='Whatsapp Logo' width={24} height={24} />
<NextImage src='/images/socials/Facebook.png' alt='Facebook Logo' width={24} height={24} />
<NextImage src='/images/socials/Twitter.png' alt='Twitter Logo' width={24} height={24} />
diff --git a/src/core/components/elements/Footer/SimpleFooter.jsx b/src/core/components/elements/Footer/SimpleFooter.jsx
index 41ca6094..26f7f786 100644
--- a/src/core/components/elements/Footer/SimpleFooter.jsx
+++ b/src/core/components/elements/Footer/SimpleFooter.jsx
@@ -1,3 +1,4 @@
+import whatsappUrl from '@/core/utils/whatsappUrl'
import {
DevicePhoneMobileIcon,
EnvelopeIcon,
@@ -20,7 +21,7 @@ const SimpleFooter = () => (
</li>
<li className='text-gray_r-12/80 flex items-center'>
<DevicePhoneMobileIcon className='w-[18px] mr-2' />
- <a href='https://wa.me/628128080622' target='_blank' rel='noreferrer'>
+ <a href={whatsappUrl()} target='_blank' rel='noreferrer'>
0812-8080-622
</a>
</li>
diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx
index 837d436c..3da0035a 100644
--- a/src/core/components/elements/Navbar/NavbarDesktop.jsx
+++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx
@@ -14,6 +14,8 @@ import { useEffect, useState } from 'react'
import useAuth from '@/core/hooks/useAuth'
import NavbarUserDropdown from './NavbarUserDropdown'
import { getCart } from '@/core/utils/cart'
+import TopBanner from './TopBanner'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const Search = dynamic(() => import('./Search'))
@@ -38,19 +40,17 @@ const NavbarDesktop = () => {
return (
<DesktopView>
+ <TopBanner />
<div className='py-3 bg-warning-400' id='desktop-nav-top'>
<div className='container mx-auto flex justify-between'>
- <Link href='/' className='!text-gray_r-12'>
+ <Link href='/tentang-kami' className='!text-gray_r-12'>
Tentang Indoteknik.com
</Link>
<div className='flex gap-x-6'>
- <Link href='/' className='!text-gray_r-12'>
+ <Link href='/my/pembayaran-tempo' className='!text-gray_r-12'>
Pembayaran Tempo
</Link>
<Link href='/' className='!text-gray_r-12'>
- F.A.Q
- </Link>
- <Link href='/' className='!text-gray_r-12'>
Fitur Layanan
</Link>
</div>
@@ -90,7 +90,7 @@ const NavbarDesktop = () => {
Wishlist
</Link>
<a
- href='https://wa.me/628128080622'
+ href={whatsappUrl()}
target='_blank'
rel='noreferrer'
className='flex items-center gap-x-1 !text-gray_r-12/80'
diff --git a/src/core/components/elements/Navbar/NavbarMobile.jsx b/src/core/components/elements/Navbar/NavbarMobile.jsx
index 0502dba5..7ac967fa 100644
--- a/src/core/components/elements/Navbar/NavbarMobile.jsx
+++ b/src/core/components/elements/Navbar/NavbarMobile.jsx
@@ -7,6 +7,7 @@ import dynamic from 'next/dynamic'
import IndoteknikLogo from '@/images/logo.png'
import { useEffect, useState } from 'react'
import { getCart } from '@/core/utils/cart'
+import TopBanner from './TopBanner'
const Search = dynamic(() => import('./Search'))
@@ -30,6 +31,7 @@ const NavbarMobile = () => {
return (
<MobileView>
+ <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='/'>
@@ -45,7 +47,7 @@ const NavbarMobile = () => {
{cartCount}
</span>
</Link>
- <button type='button' onClick={open}>
+ <button type='button' aria-label='sidebarMenuButton' onClick={open}>
<Bars3Icon className='w-6 text-gray_r-12' />
</button>
</div>
diff --git a/src/core/components/elements/Navbar/NavbarUserDropdown.jsx b/src/core/components/elements/Navbar/NavbarUserDropdown.jsx
index 1d2429a7..7848124c 100644
--- a/src/core/components/elements/Navbar/NavbarUserDropdown.jsx
+++ b/src/core/components/elements/Navbar/NavbarUserDropdown.jsx
@@ -13,6 +13,7 @@ const NavbarUserDropdown = () => {
return (
<div className='navbar-user-dropdown-wrapper'>
<div className='navbar-user-dropdown'>
+ <Link href='/my/quotations'>Daftar Quotation</Link>
<Link href='/my/transactions'>Daftar Transaksi</Link>
<Link href='/my/invoices'>Invoice & Faktur Pajak</Link>
<Link href='/my/wishlist'>Wishlist</Link>
diff --git a/src/core/components/elements/Navbar/Search.jsx b/src/core/components/elements/Navbar/Search.jsx
index 3046782b..47a9c235 100644
--- a/src/core/components/elements/Navbar/Search.jsx
+++ b/src/core/components/elements/Navbar/Search.jsx
@@ -13,7 +13,7 @@ const Search = () => {
const loadSuggestion = useCallback(() => {
if (query && document.activeElement == queryRef.current) {
searchSuggestApi({ query }).then((response) => {
- setSuggestions(response.data.suggestions)
+ setSuggestions(response.data?.suggestions || [])
})
} else {
setSuggestions([])
@@ -56,11 +56,15 @@ const Search = () => {
onBlur={onInputBlur}
onFocus={loadSuggestion}
/>
- <button type='submit' className='rounded-r border border-l-0 border-gray_r-6 px-2'>
+ <button
+ type='submit'
+ aria-label='SearchButton'
+ className='rounded-r border border-l-0 border-gray_r-6 px-2'
+ >
<MagnifyingGlassIcon className='w-6' />
</button>
- {suggestions.length > 1 && (
+ {suggestions.length > 0 && (
<>
<div className='absolute w-full top-[50px] rounded-b bg-gray_r-1 border border-gray_r-6 divide-y divide-gray_r-6 z-50'>
{suggestions.map((suggestion, index) => (
diff --git a/src/core/components/elements/Navbar/TopBanner.jsx b/src/core/components/elements/Navbar/TopBanner.jsx
new file mode 100644
index 00000000..48b23a3d
--- /dev/null
+++ b/src/core/components/elements/Navbar/TopBanner.jsx
@@ -0,0 +1,25 @@
+import odooApi from '@/core/api/odooApi'
+import { useQuery } from 'react-query'
+import Image from 'next/image'
+
+const TopBanner = () => {
+ const fetchTopBanner = async () => await odooApi('GET', '/api/v1/banner?type=top-banner')
+ const topBanner = useQuery('topBanner', fetchTopBanner)
+
+ return (
+ topBanner.isFetched &&
+ topBanner.data?.length > 0 && (
+ <div style={{ backgroundColor: topBanner.data[0]?.backgroundColor || 'transparent' }}>
+ <Image
+ src={topBanner.data[0].image}
+ alt={topBanner.data[0].name}
+ width={1440}
+ height={40}
+ className='object-cover object-center h-full mx-auto'
+ />
+ </div>
+ )
+ )
+}
+
+export default TopBanner
diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx
index c8fd8bab..7ea8f7c4 100644
--- a/src/core/components/elements/Sidebar/Sidebar.jsx
+++ b/src/core/components/elements/Sidebar/Sidebar.jsx
@@ -126,12 +126,9 @@ const Sidebar = ({ active, close }) => {
<SidebarLink className={itemClassName} href='/video'>
Indoteknik TV
</SidebarLink>
- <SidebarLink className={itemClassName} href='/about-us'>
+ <SidebarLink className={itemClassName} href='/tentang-kami'>
Tentang Indoteknik
</SidebarLink>
- <SidebarLink className={itemClassName} href='/faqs'>
- F.A.Q
- </SidebarLink>
<SidebarLink className={itemClassName} href='/contact-us'>
Hubungi Kami
</SidebarLink>
diff --git a/src/core/components/layouts/BasicLayout.jsx b/src/core/components/layouts/BasicLayout.jsx
index 1a7185cd..df42e403 100644
--- a/src/core/components/layouts/BasicLayout.jsx
+++ b/src/core/components/layouts/BasicLayout.jsx
@@ -1,5 +1,7 @@
import dynamic from 'next/dynamic'
import BasicFooter from '../elements/Footer/BasicFooter'
+import Image from 'next/image'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const Navbar = dynamic(() => import('../elements/Navbar/Navbar'))
const AnimationLayout = dynamic(() => import('./AnimationLayout'))
@@ -8,7 +10,31 @@ const BasicLayout = ({ children }) => {
return (
<>
<Navbar />
- <AnimationLayout>{children}</AnimationLayout>
+ <AnimationLayout>
+ {children}
+ <div className='fixed bottom-4 right-4 sm:bottom-10 sm:right-8 z-50'>
+ <a
+ href={whatsappUrl(null)}
+ className='py-2 pl-3 pr-4 rounded-full bg-[#4FB84A] border border-green-300 flex items-center'
+ >
+ <Image
+ src='/images/socials/WHATSAPP.svg'
+ alt='Whatsapp'
+ className='block sm:hidden'
+ width={36}
+ height={36}
+ />
+ <Image
+ src='/images/socials/WHATSAPP.svg'
+ alt='Whatsapp'
+ className='hidden sm:block'
+ width={44}
+ height={44}
+ />
+ <span className='text-white font-bold ml-1.5'>Whatsapp</span>
+ </a>
+ </div>
+ </AnimationLayout>
<BasicFooter />
</>
)
diff --git a/src/core/utils/slug.js b/src/core/utils/slug.js
index d5eecd3e..e91bcf83 100644
--- a/src/core/utils/slug.js
+++ b/src/core/utils/slug.js
@@ -9,7 +9,7 @@ import toTitleCase from './toTitleCase'
* @param {number} id - The ID to be appended to the slug.
* @returns {string} - The generated slug with the prefix, name, and ID.
*/
-const createSlug = (prefix, name, id) => {
+const createSlug = (prefix, name, id, withHost = false) => {
let slug =
name
?.trim()
@@ -19,7 +19,9 @@ const createSlug = (prefix, name, id) => {
id
let splitSlug = slug.split('-')
let filterSlugFromEmptyChar = splitSlug.filter((x) => x != '')
- return prefix + filterSlugFromEmptyChar.join('-')
+ slug = prefix + filterSlugFromEmptyChar.join('-')
+ if (withHost) slug = process.env.NEXT_PUBLIC_SELF_HOST + slug
+ return slug
}
/**
diff --git a/src/core/utils/whatsappUrl.js b/src/core/utils/whatsappUrl.js
new file mode 100644
index 00000000..6ca9722b
--- /dev/null
+++ b/src/core/utils/whatsappUrl.js
@@ -0,0 +1,24 @@
+const whatsappUrl = (template = 'default', payload) => {
+ let url = 'https://wa.me/628128080622'
+ let text = ''
+ switch (template) {
+ case 'product':
+ text = `Halo, saya mau tanya ${payload.name}, bisa tolong bantu saya?\n\nBerikut ini linknya: ${payload.url}`
+ break
+ case 'productWeight':
+ text = `Mau tanya untuk berat ${payload.name}, bisa minta tolong informasikan beratnya?\n\nBerikut ini linknya: ${payload.url}`
+ break
+ case 'productSearch':
+ text = `Saya lagi cari-cari produk ${payload.name}, bisa bantu saya cari produknya?`
+ break
+ case null:
+ break;
+ default:
+ text = 'Halo, saya mau tanya-tanya seputar produk, bisa tolong bantu saya?'
+ break
+ }
+ if (text) url += `?text=${encodeURI(text)}`
+ return url
+}
+
+export default whatsappUrl
diff --git a/src/lib/auth/components/CompanyProfile.jsx b/src/lib/auth/components/CompanyProfile.jsx
index 854aa246..13d4a194 100644
--- a/src/lib/auth/components/CompanyProfile.jsx
+++ b/src/lib/auth/components/CompanyProfile.jsx
@@ -76,7 +76,7 @@ const CompanyProfile = () => {
Dibawah ini adalah data usaha yang anda masukkan, periksa kembali data usaha anda.
</div>
</div>
- <div className='p-2 bg-gray_r-3 rounded'>
+ <div className='ml-2 p-2 bg-gray_r-3 rounded'>
{!isOpen && <ChevronDownIcon className='w-6' />}
{isOpen && <ChevronUpIcon className='w-6' />}
</div>
diff --git a/src/lib/auth/components/Menu.jsx b/src/lib/auth/components/Menu.jsx
index 9a73609d..8a8e2e8a 100644
--- a/src/lib/auth/components/Menu.jsx
+++ b/src/lib/auth/components/Menu.jsx
@@ -9,10 +9,13 @@ const Menu = () => {
return (
<div className='grid grid-cols-1 bg-white border border-gray_r-6 rounded py-2 px-4'>
<div className='mt-4 mb-1 font-medium'>Menu</div>
- <LinkItem href='/my/transactions' active={routeStartWith('/my/transaction')}>
+ <LinkItem href='/my/quotations' active={routeStartWith('/my/quotations')}>
+ Daftar Quotation
+ </LinkItem>
+ <LinkItem href='/my/transactions' active={routeStartWith('/my/transactions')}>
Daftar Transaksi
</LinkItem>
- <LinkItem href='/my/invoices' active={routeStartWith('/my/invoice')}>
+ <LinkItem href='/my/invoices' active={routeStartWith('/my/invoices')}>
Invoice & Faktur Pajak
</LinkItem>
<LinkItem href='/my/wishlist' active={routeStartWith('/my/wishlist')}>
diff --git a/src/lib/auth/components/PersonalProfile.jsx b/src/lib/auth/components/PersonalProfile.jsx
index 4a533ae9..bca54e24 100644
--- a/src/lib/auth/components/PersonalProfile.jsx
+++ b/src/lib/auth/components/PersonalProfile.jsx
@@ -9,7 +9,7 @@ import editPersonalProfileApi from '../api/editPersonalProfileApi'
const PersonalProfile = () => {
const auth = useAuth()
- const [isOpen, setIsOpen] = useState(false)
+ const [isOpen, setIsOpen] = useState(true)
const toggle = () => setIsOpen(!isOpen)
const { register, setValue, handleSubmit } = useForm({
defaultValues: {
@@ -54,7 +54,7 @@ const PersonalProfile = () => {
Dibawah ini adalah data diri yang anda masukan, periksa kembali data diri anda
</div>
</div>
- <div className='p-2 bg-gray_r-3 rounded'>
+ <div className='ml-2 p-2 bg-gray_r-3 rounded'>
{!isOpen && <ChevronDownIcon className='w-6' />}
{isOpen && <ChevronUpIcon className='w-6' />}
</div>
diff --git a/src/lib/auth/components/RegisterDesktop.jsx b/src/lib/auth/components/RegisterDesktop.jsx
index 482a9ce3..f624fba7 100644
--- a/src/lib/auth/components/RegisterDesktop.jsx
+++ b/src/lib/auth/components/RegisterDesktop.jsx
@@ -4,6 +4,7 @@ import Link from '@/core/components/elements/Link/Link'
import Alert from '@/core/components/elements/Alert/Alert'
import PageContent from '@/lib/content/components/PageContent'
import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import ReCAPTCHA from 'react-google-recaptcha'
const RegisterDesktop = () => {
const {
@@ -16,6 +17,7 @@ const RegisterDesktop = () => {
fullnameRef,
emailRef,
passwordRef,
+ recaptchaRef,
tnd,
setTnd
} = useRegister()
@@ -89,6 +91,7 @@ const RegisterDesktop = () => {
placeholder='••••••••••••'
/>
</div>
+ <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
<div class='flex items-center mt-4 '>
<input
type='checkbox'
@@ -96,11 +99,12 @@ const RegisterDesktop = () => {
className='form-input flex items-start w-fit mr-2'
required
/>
- <label
- onClick={() => setTnd(true)}
- className='inline cursor-pointer text-danger-500'
- >
- Syarat dan Ketentuan
+ <label className='inline'>
+ Dengan ini saya menyetujui{' '}
+ <span onClick={() => setTnd(true)} className='cursor-pointer text-danger-500'>
+ syarat dan ketentuan
+ </span>{' '}
+ yang berlaku
</label>
</div>
<button
diff --git a/src/lib/auth/components/RegisterMobile.jsx b/src/lib/auth/components/RegisterMobile.jsx
index f5c818e7..80ea6ab0 100644
--- a/src/lib/auth/components/RegisterMobile.jsx
+++ b/src/lib/auth/components/RegisterMobile.jsx
@@ -6,6 +6,7 @@ import useRegister from '../hooks/useRegister'
import MobileView from '@/core/components/views/MobileView'
import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
import PageContent from '@/lib/content/components/PageContent'
+import ReCAPTCHA from 'react-google-recaptcha'
const RegisterMobile = () => {
const {
@@ -18,6 +19,7 @@ const RegisterMobile = () => {
fullnameRef,
emailRef,
passwordRef,
+ recaptchaRef,
tnd,
setTnd
} = useRegister()
@@ -93,6 +95,7 @@ const RegisterMobile = () => {
placeholder='••••••••••••'
/>
</div>
+ <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
<div class='flex items-center mt-4 '>
<input
type='checkbox'
@@ -100,8 +103,12 @@ const RegisterMobile = () => {
className='form-input flex items-start w-fit mr-2'
required
/>
- <label onClick={() => setTnd(true)} className='inline cursor-pointer text-danger-500'>
- Syarat dan Ketentuan
+ <label className='inline'>
+ Dengan ini saya menyetujui{' '}
+ <span onClick={() => setTnd(true)} className='cursor-pointer text-danger-500'>
+ syarat dan ketentuan
+ </span>{' '}
+ yang berlaku
</label>
</div>
<button type='submit' className='btn-yellow w-full mt-2' disabled={!isValid || isLoading}>
diff --git a/src/lib/auth/hooks/useRegister.js b/src/lib/auth/hooks/useRegister.js
index 4b0b0d60..1a9412f8 100644
--- a/src/lib/auth/hooks/useRegister.js
+++ b/src/lib/auth/hooks/useRegister.js
@@ -33,8 +33,20 @@ const useRegister = () => {
companyNameRef.current.value = ''
}
+ const recaptchaRef = useRef(null)
+
const handleSubmit = async (e) => {
e.preventDefault()
+
+ const recaptchaValue = recaptchaRef.current.getValue()
+ if (!recaptchaValue) {
+ setAlert({
+ children: 'ReCaptcha harus diisi',
+ type: 'info'
+ })
+ return
+ }
+
setAlert(null)
setIsLoading(true)
const { fullname, email, password, companyName } = inputVal()
@@ -75,6 +87,7 @@ const useRegister = () => {
fullnameRef,
emailRef,
passwordRef,
+ recaptchaRef,
tnd,
setTnd
}
diff --git a/src/lib/brand/components/Brand.jsx b/src/lib/brand/components/Brand.jsx
index 6ebb8aa7..3c411969 100644
--- a/src/lib/brand/components/Brand.jsx
+++ b/src/lib/brand/components/Brand.jsx
@@ -1,5 +1,5 @@
import useBrand from '../hooks/useBrand'
-import Image from '@/core/components/elements/Image/Image'
+import Image from 'next/image'
import { Swiper, SwiperSlide } from 'swiper/react'
import { Pagination, Autoplay } from 'swiper'
@@ -29,6 +29,15 @@ const Brand = ({ id }) => {
<>
<div>
{brand.isLoading && <ImageSkeleton />}
+ {brand.data?.banners?.length == 0 && (
+ <Image
+ src='/images/default-banner-brand.jpg'
+ alt='Brand - Indoteknik'
+ width={1024}
+ height={512}
+ className='w-full h-auto'
+ />
+ )}
{brand.data && (
<>
<Swiper
@@ -43,6 +52,8 @@ const Brand = ({ id }) => {
<Image
src={banner}
alt={`Brand ${brand.data?.name} - Indoteknik`}
+ width={1024}
+ height={512}
className='w-full h-auto'
/>
</SwiperSlide>
@@ -55,6 +66,8 @@ const Brand = ({ id }) => {
src={brand?.data?.logo}
alt={brand?.data?.name}
className='w-32 p-2 border borde-gray_r-6 rounded'
+ width={256}
+ height={128}
/>
)}
{!brand?.data?.logo && (
@@ -69,10 +82,20 @@ const Brand = ({ id }) => {
<Divider />
</>
</MobileView>
+
<DesktopView>
<div className='container mx-auto mt-10 mb-3'>
<div className='min-h-[150px]'>
{brand.isLoading && <ImageSkeleton />}
+ {brand.data?.banners?.length == 0 && (
+ <Image
+ src='/images/default-banner-brand.jpg'
+ alt='Brand - Indoteknik'
+ width={1024}
+ height={512}
+ className='w-full h-auto'
+ />
+ )}
{brand.data && (
<>
<Swiper
@@ -87,6 +110,8 @@ const Brand = ({ id }) => {
<Image
src={banner}
alt={`Brand ${brand.data?.name} - Indoteknik`}
+ width={1024}
+ height={512}
className='w-full h-auto'
/>
</SwiperSlide>
@@ -99,6 +124,8 @@ const Brand = ({ id }) => {
src={brand?.data?.logo}
alt={brand?.data?.name}
className='w-32 p-2 border borde-gray_r-6 rounded'
+ width={1024}
+ height={512}
/>
)}
{!brand?.data?.logo && (
diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx
index d0685fe3..1008bffc 100644
--- a/src/lib/cart/components/Cart.jsx
+++ b/src/lib/cart/components/Cart.jsx
@@ -16,6 +16,7 @@ import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
import ProductCard from '@/lib/product/components/ProductCard'
import productSearchApi from '@/lib/product/api/productSearchApi'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const Cart = () => {
const router = useRouter()
@@ -72,7 +73,7 @@ const Cart = () => {
}, [products])
useEffect(() => {
- const LoadProductSImilar = async () => {
+ const LoadProductSimilar = async () => {
const randProductIndex = Math.floor(Math.random() * products.length)
const productLoad = await productSearchApi({
query: `q=${products?.[randProductIndex].parent.name}&limit=10`
@@ -80,8 +81,8 @@ const Cart = () => {
setProductRecomendation(productLoad)
}
- if (products?.length > 0) LoadProductSImilar()
- }, [products])
+ if (products?.length > 0 && !productRecomendation) LoadProductSimilar()
+ }, [products, productRecomendation])
const updateQuantity = (value, productId, operation = '') => {
let productIndex = products.findIndex((product) => product.id == productId)
@@ -329,91 +330,92 @@ const Cart = () => {
<td colSpan={6}>Keranjang belanja anda masih kosong</td>
</tr>
)}
- {products && products?.map((product) => (
- <tr key={product.id}>
- <td>
- <input
- type='checkbox'
- onClick={() => toggleSelected(product.id)}
- checked={product?.selected}
- className='accent-danger-500 w-4'
- />
- </td>
- <td className='flex'>
- <Link
- href={createSlug(
- '/shop/product/',
- product?.parent.name,
- product?.parent.id
- )}
- className='w-[20%] flex-shrink-0'
- >
- <Image
- src={product?.parent?.image}
- alt={product?.name}
- className='object-contain object-center border border-gray_r-6 h-28 w-full rounded-md'
+ {products &&
+ products?.map((product) => (
+ <tr key={product.id}>
+ <td>
+ <input
+ type='checkbox'
+ onClick={() => toggleSelected(product.id)}
+ checked={product?.selected}
+ className='accent-danger-500 w-4'
/>
- </Link>
- <div className='px-2 text-left'>
+ </td>
+ <td className='flex'>
<Link
href={createSlug(
'/shop/product/',
product?.parent.name,
product?.parent.id
)}
- className='line-clamp-2 leading-6 !text-gray_r-12 font-normal'
+ className='w-[20%] flex-shrink-0'
>
- {product?.parent?.name}
+ <Image
+ src={product?.parent?.image}
+ alt={product?.name}
+ className='object-contain object-center border border-gray_r-6 h-28 w-full rounded-md'
+ />
</Link>
- <div className='text-gray_r-11 mt-2'>
- {product?.code}{' '}
- {product?.attributes.length > 0
- ? `| ${product?.attributes.join(', ')}`
- : ''}
- </div>
- </div>
- </td>
- <td>
- <input
- className='form-input w-16 py-2 text-center bg-gray_r-1'
- type='number'
- value={product?.quantity}
- onChange={(e) => updateQuantity(e.target.value, product?.id)}
- onBlur={(e) => updateQuantity(e.target.value, product?.id, 'BLUR')}
- />
- </td>
- <td>
- {product?.price?.discountPercentage > 0 && (
- <div className='flex gap-x-1 items-center justify-center mt-3'>
- <div className='text-gray_r-11 line-through text-caption-1'>
- {currencyFormat(product?.price?.price)}
+ <div className='px-2 text-left'>
+ <Link
+ href={createSlug(
+ '/shop/product/',
+ product?.parent.name,
+ product?.parent.id
+ )}
+ className='line-clamp-2 leading-6 !text-gray_r-12 font-normal'
+ >
+ {product?.parent?.name}
+ </Link>
+ <div className='text-gray_r-11 mt-2'>
+ {product?.code}{' '}
+ {product?.attributes.length > 0
+ ? `| ${product?.attributes.join(', ')}`
+ : ''}
</div>
- <div className='badge-solid-red'>
- {product?.price?.discountPercentage}%
+ </div>
+ </td>
+ <td>
+ <input
+ className='form-input w-16 py-2 text-center bg-gray_r-1'
+ type='number'
+ value={product?.quantity}
+ onChange={(e) => updateQuantity(e.target.value, product?.id)}
+ onBlur={(e) => updateQuantity(e.target.value, product?.id, 'BLUR')}
+ />
+ </td>
+ <td>
+ {product?.price?.discountPercentage > 0 && (
+ <div className='flex gap-x-1 items-center justify-center mt-3'>
+ <div className='text-gray_r-11 line-through text-caption-1'>
+ {currencyFormat(product?.price?.price)}
+ </div>
+ <div className='badge-solid-red'>
+ {product?.price?.discountPercentage}%
+ </div>
</div>
+ )}
+ <div className='font-normal mt-1'>
+ {currencyFormat(product?.price?.priceDiscount)}
</div>
- )}
- <div className='font-normal mt-1'>
- {currencyFormat(product?.price?.priceDiscount)}
- </div>
- </td>
- <td>
- <div className='text-danger-500 font-medium'>
- {currencyFormat(product?.price?.priceDiscount * product?.quantity)}
- </div>
- </td>
- <td>
- <div className='flex justify-center items-center h-full'>
- <button
- className='btn-red p-1 ml-1'
- onClick={() => setDeleteConfirmation(product)}
- >
- <TrashIcon className='w-4' />
- </button>
- </div>
- </td>
- </tr>
- ))}
+ </td>
+ <td>
+ <div className='text-danger-500 font-medium'>
+ {currencyFormat(product?.price?.priceDiscount * product?.quantity)}
+ </div>
+ </td>
+ <td>
+ <div className='flex justify-center items-center h-full'>
+ <button
+ className='btn-red p-1 ml-1'
+ onClick={() => setDeleteConfirmation(product)}
+ >
+ <TrashIcon className='w-4' />
+ </button>
+ </div>
+ </td>
+ </tr>
+ ))}
</tbody>
</table>
@@ -428,7 +430,7 @@ const Cart = () => {
Tanya stock untuk pembelian anda sebelum melanjutkan pembayaran!
<span>
{' '}
- <a href='https://wa.me/628128080622' className='text-danger-500'>
+ <a href={whatsappUrl()} className='text-danger-500'>
Hubungi Kami
</a>
</span>
diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx
index 9f34362c..884a871f 100644
--- a/src/lib/category/components/Category.jsx
+++ b/src/lib/category/components/Category.jsx
@@ -1,6 +1,7 @@
import odooApi from '@/core/api/odooApi'
import Link from '@/core/components/elements/Link/Link'
import DesktopView from '@/core/components/views/DesktopView'
+import { createSlug } from '@/core/utils/slug'
import { useEffect, useState } from 'react'
const Category = () => {
@@ -32,7 +33,7 @@ const Category = () => {
{categories.map((category) => (
<div key={category.id}>
<Link
- href={`/shop/search?category=${category.name}`}
+ href={createSlug('/shop/category/', category.name, category.id)}
className='category-mega-box__parent'
>
{category.name}
@@ -42,7 +43,7 @@ const Category = () => {
{category.childs.map((child1Category) => (
<div key={child1Category.id}>
<Link
- href={`/shop/search?category=${child1Category.name}`}
+ href={createSlug('/shop/category/', child1Category.name, child1Category.id)}
className='category-mega-box__child-one mb-4'
>
{child1Category.name}
@@ -50,7 +51,11 @@ const Category = () => {
<div className='flex flex-col gap-y-3'>
{child1Category.childs.map((child2Category) => (
<Link
- href={`/shop/search?category=${child2Category.name}`}
+ href={createSlug(
+ '/shop/category/',
+ child2Category.name,
+ child2Category.id
+ )}
className='category-mega-box__child-two'
key={child2Category.id}
>
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 111117c9..f777a3a8 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -20,6 +20,8 @@ import Image from '@/core/components/elements/Image/Image'
import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
import ExpedisiList from '../api/ExpedisiList'
+import whatsappUrl from '@/core/utils/whatsappUrl'
+import { createSlug } from '@/core/utils/slug'
const Checkout = () => {
const router = useRouter()
@@ -166,8 +168,8 @@ const Checkout = () => {
quantity: product.quantity
}))
let data = {
- partner_shipping_id: selectedAddress.shipping.id,
- partner_invoice_id: selectedAddress.invoicing.id,
+ partner_shipping_id: auth.partnerId,
+ partner_invoice_id: auth.partnerId,
order_line: JSON.stringify(productOrder),
delivery_amount : biayaKirim,
type: 'sale_order'
@@ -342,7 +344,7 @@ const Checkout = () => {
<div className='px-4 mb-4'>
<span className='text-danger-500'>
*) Terdapat produk yang belum memiliki harga,{' '}
- <a href='https://wa.me/628128080622' className='underline'>
+ <a href={whatsappUrl()} className='underline'>
Hubungi Kami untuk meminta harga.
</a>
</span>
@@ -465,7 +467,13 @@ const Checkout = () => {
{product.price.priceDiscount > 0 ? (
currencyFormat(product?.price?.priceDiscount * product?.quantity)
) : (
- <a href='https://wa.me/628128080622' className='underline'>
+ <a
+ href={whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='underline'
+ >
Call For Price{' '}
</a>
)}
@@ -562,7 +570,7 @@ const Checkout = () => {
<div className='mt-4'>
<span className='text-danger-500'>
*) Terdapat produk yang belum memiliki harga,{' '}
- <a href='https://wa.me/628128080622' className='underline'>
+ <a href={whatsappUrl()} className='underline'>
Hubungi Kami untuk meminta harga.
</a>
</span>
diff --git a/src/lib/checkout/components/FinishCheckout.jsx b/src/lib/checkout/components/FinishCheckout.jsx
index cd93e3a4..92245e31 100644
--- a/src/lib/checkout/components/FinishCheckout.jsx
+++ b/src/lib/checkout/components/FinishCheckout.jsx
@@ -14,7 +14,7 @@ const FinishCheckout = ({ query }) => {
<p className='text-caption-2 text-warning-800'>No. Transaksi</p>
</div>
<Link
- href='/my/transactions'
+ href='/my/quotations'
className='bg-warning-400 text-warning-900 rounded-b-xl py-4 block'
>
Lihat detail pembelian Anda disini
diff --git a/src/lib/checkout/email/FinishCheckoutEmail.jsx b/src/lib/checkout/email/FinishCheckoutEmail.jsx
index e8f63afa..d40ce7d4 100644
--- a/src/lib/checkout/email/FinishCheckoutEmail.jsx
+++ b/src/lib/checkout/email/FinishCheckoutEmail.jsx
@@ -1,5 +1,6 @@
import currencyFormat from '@/core/utils/currencyFormat'
import toTitleCase from '@/core/utils/toTitleCase'
+import whatsappUrl from '@/core/utils/whatsappUrl'
import {
Body,
Column,
@@ -255,7 +256,7 @@ const FinishCheckoutEmail = ({ transaction, payment, statusPayment }) => {
Jika ada pertanyaan seputar teknis pembayaran {transaction.address.customer.name}{' '}
dapat hubungi kami melalui Email{' '}
<a href='mailto:sales@indoteknik.com'>(sales@indoteknik.com)</a> atau Whatsapp{' '}
- <a href='https://wa.me/628128080622' target='_blank' rel='noreferrer'>
+ <a href={whatsappUrl()} target='_blank' rel='noreferrer'>
(+62 812-8080-622)
</a>
.
diff --git a/src/lib/content/components/PageContent.jsx b/src/lib/content/components/PageContent.jsx
index 61e5381d..8c467999 100644
--- a/src/lib/content/components/PageContent.jsx
+++ b/src/lib/content/components/PageContent.jsx
@@ -6,13 +6,21 @@ const PageContent = ({ path }) => {
const fetchContent = async () => await pageContentApi({ path })
const content = useQuery(`content-${path}`, fetchContent)
+ if (content.isLoading) {
+ return (
+ <div className='flex justify-center my-6'>
+ <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' />
+ </div>
+ )
+ }
+
if (content.data?.id) {
let parsedContent = content.data.content
parsedContent = parsedContent.replaceAll(
'src="/web/image',
`src="${process.env.NEXT_PUBLIC_ODOO_API_HOST}/web/image`
)
- const contentClassNames = `
+ const contentClassNames = `
prose
prose-gray
prose-a:text-danger-500
@@ -23,19 +31,12 @@ const PageContent = ({ path }) => {
prose-img:mb-1
prose-img:inline-block
prose-hr:my-3
+ max-w-none
`
return <div className={contentClassNames} dangerouslySetInnerHTML={{ __html: parsedContent }} />
}
- if (content.isLoading) {
- return (
- <div className='flex justify-center my-6'>
- <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' />
- </div>
- )
- }
-
return <></>
}
diff --git a/src/lib/flashSale/api/flashSaleApi.js b/src/lib/flashSale/api/flashSaleApi.js
new file mode 100644
index 00000000..115b07dc
--- /dev/null
+++ b/src/lib/flashSale/api/flashSaleApi.js
@@ -0,0 +1,8 @@
+import odooApi from '@/core/api/odooApi'
+
+const flashSaleApi = async () => {
+ const flashSale = await odooApi('GET', '/api/v1/flashsale/header')
+ return flashSale
+}
+
+export default flashSaleApi
diff --git a/src/lib/flashSale/components/FlashSale.jsx b/src/lib/flashSale/components/FlashSale.jsx
new file mode 100644
index 00000000..e4a4a25c
--- /dev/null
+++ b/src/lib/flashSale/components/FlashSale.jsx
@@ -0,0 +1,66 @@
+import { useEffect, useState } from 'react'
+import flashSaleApi from '../api/flashSaleApi'
+import Image from '@/core/components/elements/Image/Image'
+import CountDown from '@/core/components/elements/CountDown/CountDown'
+import productSearchApi from '@/lib/product/api/productSearchApi'
+import ProductSlider from '@/lib/product/components/ProductSlider'
+
+const FlashSale = () => {
+ const [flashSales, setFlashSales] = useState(null)
+
+ useEffect(() => {
+ const loadFlashSales = async () => {
+ const dataFlashSales = await flashSaleApi()
+ setFlashSales(dataFlashSales)
+ }
+ loadFlashSales()
+ }, [])
+
+ return (
+ flashSales?.length > 0 && (
+ <div className='px-4 sm:px-0 grid grid-cols-1 gap-y-8'>
+ {flashSales.map((flashSale, index) => (
+ <div key={index}>
+ <div className='flex gap-x-3 mb-4 justify-between sm:justify-start'>
+ <div className='font-medium sm:text-h-lg mt-1.5'>{flashSale.name}</div>
+ <CountDown initialTime={flashSale.duration} />
+ </div>
+
+ <div className='relative'>
+ <Image
+ src={flashSale.banner}
+ alt={flashSale.name}
+ className='w-full rounded mb-4 hidden sm:block'
+ />
+ <Image
+ src={flashSale.bannerMobile}
+ alt={flashSale.name}
+ className='w-full rounded mb-4 block sm:hidden'
+ />
+ <FlashSaleProduct flashSaleId={flashSale.pricelistId} />
+ </div>
+ </div>
+ ))}
+ </div>
+ )
+ )
+}
+
+const FlashSaleProduct = ({ flashSaleId }) => {
+ const [products, setProducts] = useState(null)
+
+ useEffect(() => {
+ const loadProducts = async () => {
+ const dataProducts = await productSearchApi({
+ query: `fq=flashsale_id_i:${flashSaleId}&fq=flashsale_price_f:[1 TO *]&limit=500`,
+ operation: 'AND'
+ })
+ setProducts(dataProducts.response)
+ }
+ loadProducts()
+ }, [flashSaleId])
+
+ return <ProductSlider products={products} />
+}
+
+export default FlashSale
diff --git a/src/lib/form/components/KunjunganService.jsx b/src/lib/form/components/KunjunganService.jsx
index dfe5873e..076f6814 100644
--- a/src/lib/form/components/KunjunganService.jsx
+++ b/src/lib/form/components/KunjunganService.jsx
@@ -6,7 +6,7 @@ import ReCAPTCHA from 'react-google-recaptcha'
import { Controller, useForm } from 'react-hook-form'
import { toast } from 'react-hot-toast'
import * as Yup from 'yup'
-import createLeadsApi from '../api/createLeadsApi'
+import createLeadApi from '../api/createLeadApi'
const CreateKunjunganService = () => {
const {
@@ -41,18 +41,32 @@ const CreateKunjunganService = () => {
}
const data = {
...values,
- name : 'Pengajuan Kunjungan Service - ' + values.company,
- contact_name : values.cp,
- email_from : values.email,
- phone : values.mobile,
- description : "\r\n Nama Perusahaan : " + values.company + " \r\n Alamat : " + values.address + " \r\n Propinsi : " + values.city + " \r\n Telepon: " + values.phone + " \r\n Handphone : " + values.mobile +" \r\n Email : " + values.email + " \r\n Keterangan : " + values.description ,
+ name: 'Pengajuan Kunjungan Service - ' + values.company,
+ contact_name: values.cp,
+ email_from: values.email,
+ phone: values.mobile,
+ description:
+ '\r\n Nama Perusahaan : ' +
+ values.company +
+ ' \r\n Alamat : ' +
+ values.address +
+ ' \r\n Propinsi : ' +
+ values.city +
+ ' \r\n Telepon: ' +
+ values.phone +
+ ' \r\n Handphone : ' +
+ values.mobile +
+ ' \r\n Email : ' +
+ values.email +
+ ' \r\n Keterangan : ' +
+ values.description
}
- const create_leads = await createLeadsApi({ data })
+ const create_leads = await createLeadApi({ data })
if (create_leads) {
toast.success('Berhasil menambahkan alamat')
reset()
- recaptchaRef.current.reset()
+ recaptchaRef.current.reset()
}
}
return (
@@ -125,9 +139,7 @@ const CreateKunjunganService = () => {
type='text'
className='form-input'
/>
- <div className='text-caption-2 text-danger-500 mt-1'>
- {errors.cp?.message}
- </div>
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.cp?.message}</div>
</div>
</div>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
@@ -156,7 +168,9 @@ const CreateKunjunganService = () => {
</div>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
<div>
- <label className='form-label mb-2'>Sebutkan: Merek, Tipe, Permasalahan, Service, Perawatan</label>
+ <label className='form-label mb-2'>
+ Sebutkan: Merek, Tipe, Permasalahan, Service, Perawatan
+ </label>
<textarea {...register('description')} type='text' className='form-input' />
<div className='text-caption-2 text-danger-500 mt-1'>
{errors.description?.message}
@@ -181,24 +195,24 @@ const CreateKunjunganService = () => {
)
}
const validationSchema = Yup.object().shape({
- company: Yup.string().required('Harus di-isi'),
- email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
- phone: Yup.string().required('Harus di-isi'),
- city: Yup.string().required('Harus di-isi'),
- cp: Yup.string().required('Harus di-isi'),
- mobile: Yup.string().required('Harus di-isi'),
- email: Yup.string().required('Harus di-isi'),
- address: Yup.string().required('Harus di-isi')
+ company: Yup.string().required('Harus di-isi'),
+ email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ phone: Yup.string().required('Harus di-isi'),
+ city: Yup.string().required('Harus di-isi'),
+ cp: Yup.string().required('Harus di-isi'),
+ mobile: Yup.string().required('Harus di-isi'),
+ email: Yup.string().required('Harus di-isi'),
+ address: Yup.string().required('Harus di-isi')
})
const defaultValues = {
- company:'',
- email: '',
- phone: '',
- city: '',
- cp: '',
- mobile: '',
- email: '',
- address: ''
+ company: '',
+ email: '',
+ phone: '',
+ city: '',
+ cp: '',
+ mobile: '',
+ email: '',
+ address: ''
}
export default CreateKunjunganService
diff --git a/src/lib/form/components/MediaRelations.jsx b/src/lib/form/components/MediaRelations.jsx
new file mode 100644
index 00000000..05ae7e03
--- /dev/null
+++ b/src/lib/form/components/MediaRelations.jsx
@@ -0,0 +1,237 @@
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'
+import cityApi from '@/lib/address/api/cityApi'
+import { yupResolver } from '@hookform/resolvers/yup'
+import React, { useEffect, useRef, useState } from 'react'
+import ReCAPTCHA from 'react-google-recaptcha'
+import { Controller, useForm } from 'react-hook-form'
+import { toast } from 'react-hot-toast'
+import * as Yup from 'yup'
+import createLeadApi from '../api/createLeadApi'
+
+const CreateMediaRelations = () => {
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ control,
+ reset
+ } = useForm({
+ resolver: yupResolver(validationSchema),
+ defaultValues
+ })
+ const list_unit = [
+ {
+ value: 'Media Cetak',
+ label: 'Media Cetak'
+ },
+ {
+ value: 'Media',
+ label: 'Hospitality'
+ },
+ {
+ value: 'Automotive',
+ label: 'Automotive'
+ },
+ {
+ value: 'Retail',
+ label: 'Retail'
+ },
+ {
+ value: 'Maining',
+ label: 'Maining'
+ },
+ {
+ value: 'Lain - Lain',
+ label: 'Lain - Lain'
+ }
+ ]
+ const [cities, setCities] = useState([])
+ const [company_unit, setCompany_unit] = useState(list_unit)
+
+ const recaptchaRef = useRef(null)
+
+ useEffect(() => {
+ const loadCities = async () => {
+ let dataCities = await cityApi()
+ dataCities = dataCities.map((city) => ({ value: city.id, label: city.name }))
+ setCities(dataCities)
+ }
+ loadCities()
+ }, [])
+
+ const onSubmitHandler = async (values) => {
+ const attachment = document.getElementById('attachment').files[0]
+
+ const recaptchaValue = recaptchaRef.current.getValue()
+ if (!recaptchaValue) {
+ toast.error('Catcha harus diisi')
+ return
+ }
+ const data = {
+ ...values,
+ name: 'Form Merchant - ' + values.company,
+ contact_name: values.cp,
+ email_from: values.email,
+ phone: values.phone,
+ description:
+ 'Nama Perusahaan : ' +
+ values.company +
+ ' \r\n Alamat : ' +
+ values.address +
+ ' \r\n Kota : ' +
+ values.city +
+ ' \r\n Unit Perusahaan : ' +
+ values.company_unit +
+ ' \r\n Telepon: ' +
+ values.phone +
+ ' \r\n Email : ' +
+ values.email +
+ ' \r\n Website : ' +
+ values.website +
+ ' \r\n No Hp : ' +
+ values.mobile +
+ 'Keterangan : ' +
+ values.description
+ }
+ const create_leads = await createLeadApi({ data })
+ if (create_leads) {
+ toast.success('Berhasil menambahkan data')
+ reset()
+ recaptchaRef.current.reset()
+ }
+ }
+ return (
+ <div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
+ <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Form Media dan Relasi</h1>
+ <div className='w-full p-4 bg-white border border-gray_r-6 rounded'>
+ <form onSubmit={handleSubmit(onSubmitHandler)}>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Nama Lengkap *</label>
+ <input
+ {...register('name')}
+ placeholder='Jhone Doe'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.name?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Nama Perusahan *</label>
+ <input
+ {...register('company')}
+ placeholder='PT.Indoteknik'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.company?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Alamat Email *</label>
+ <input
+ {...register('email')}
+ placeholder='contoh@email.com'
+ type='email'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>No. Telp *</label>
+ <input
+ {...register('phone')}
+ placeholder='021-XXXX'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Jenis Media / Partnetship *</label>
+ <Controller
+ name='company_unit'
+ control={control}
+ render={(props) => <HookFormSelect {...props} options={company_unit} />}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.company_unit?.message}
+ </div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Jika anda memiliki media lain, sebutkan </label>
+ <input
+ {...register('other_media')}
+ placeholder='021-XXXX'
+ type='text'
+ className='form-input'
+ />
+ </div>
+ </div>
+
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>
+ Lampiran (Company Peofile, Proposal Kerjasama, dll)
+ </label>
+ <input
+ {...register('attachment')}
+ type='file'
+ className='form-input'
+ accept='application/pdf'
+ id='attachment'
+ placeholder='Hello'
+ />
+ </div>
+ </div>
+
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <button type='submit' className='btn-yellow w-full md:w-fit mt-6 ml-0 md:ml-auto'>
+ Simpan
+ </button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ )
+}
+const validationSchema = Yup.object().shape({
+ company: Yup.string().required('Harus di-isi'),
+ email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ phone: Yup.string().required('Harus di-isi'),
+ cp: Yup.string().required('Harus di-isi'),
+ city: Yup.string().required('Harus di-isi'),
+ company_unit: Yup.string().required('Harus di-isi'),
+ address: Yup.string().required('Harus di-isi'),
+ website: Yup.string().required('Harus di-isi'),
+ mobile: Yup.string().required('Harus di-isi')
+})
+const defaultValues = {
+ company: '',
+ email: '',
+ phone: '',
+ city: '',
+ company_unit: '',
+ cp: '',
+ address: '',
+ website: '',
+ mobile: ''
+}
+
+export default CreateMediaRelations
diff --git a/src/lib/form/components/Merchant.jsx b/src/lib/form/components/Merchant.jsx
new file mode 100644
index 00000000..75b4e132
--- /dev/null
+++ b/src/lib/form/components/Merchant.jsx
@@ -0,0 +1,264 @@
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'
+import cityApi from '@/lib/address/api/cityApi'
+import { yupResolver } from '@hookform/resolvers/yup'
+import React, { useEffect, useRef, useState } from 'react'
+import ReCAPTCHA from 'react-google-recaptcha'
+import { Controller, useForm } from 'react-hook-form'
+import { toast } from 'react-hot-toast'
+import * as Yup from 'yup'
+import createLeadApi from '../api/createLeadApi'
+
+const CreateMerchant = () => {
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ control,
+ reset
+ } = useForm({
+ resolver: yupResolver(validationSchema),
+ defaultValues
+ })
+ const list_unit = [
+ {
+ value: 'Manufacturing',
+ label: 'Manufacturing'
+ },
+ {
+ value: 'Hospitality',
+ label: 'Hospitality'
+ },
+ {
+ value: 'Automotive',
+ label: 'Automotive'
+ },
+ {
+ value: 'Retail',
+ label: 'Retail'
+ },
+ {
+ value: 'Maining',
+ label: 'Maining'
+ },
+ {
+ value: 'Lain - Lain',
+ label: 'Lain - Lain'
+ }
+ ]
+ const [cities, setCities] = useState([])
+ const [company_unit, setCompany_unit] = useState(list_unit)
+
+ const recaptchaRef = useRef(null)
+
+ useEffect(() => {
+ const loadCities = async () => {
+ let dataCities = await cityApi()
+ dataCities = dataCities.map((city) => ({ value: city.id, label: city.name }))
+ setCities(dataCities)
+ }
+ loadCities()
+ }, [])
+
+ const onSubmitHandler = async (values) => {
+ const recaptchaValue = recaptchaRef.current.getValue()
+ if (!recaptchaValue) {
+ toast.error('Catcha harus diisi')
+ return
+ }
+ const data = {
+ ...values,
+ name: 'Form Merchant - ' + values.company,
+ contact_name: values.cp,
+ email_from: values.email,
+ phone: values.phone,
+ description:
+ 'Nama Perusahaan : ' +
+ values.company +
+ ' \r\n Alamat : ' +
+ values.address +
+ ' \r\n Kota : ' +
+ values.city +
+ ' \r\n Unit Perusahaan : ' +
+ values.company_unit +
+ ' \r\n Telepon: ' +
+ values.phone +
+ ' \r\n Email : ' +
+ values.email +
+ ' \r\n Website : ' +
+ values.website +
+ ' \r\n No Hp : ' +
+ values.mobile +
+ 'Keterangan : ' +
+ values.description
+ }
+ const create_leads = await createLeadApi({ data })
+ if (create_leads) {
+ toast.success('Berhasil menambahkan data')
+ reset()
+ recaptchaRef.current.reset()
+ }
+ }
+ return (
+ <div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
+ <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Form Merchant</h1>
+ <div className='w-full p-4 bg-white border border-gray_r-6 rounded'>
+ <div
+ class='flex items-center bg-blue-100 border border-blue-400 text-blue-500 font-bold px-4 py-3 mb-4'
+ role='alert'
+ >
+ <p>
+ Penjualan online adalah hal yang HARUS dilakukan mulai sekarang. Perubahan dalam banyak
+ industri dan pola pembelian. Gabung dengan platform kami dan mulai penjualan lansung di
+ ribuan perusahaan d seluruh Indonesia.{' '}
+ </p>
+ </div>
+ <form onSubmit={handleSubmit(onSubmitHandler)}>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Nama Perusahan *</label>
+ <input
+ {...register('company')}
+ placeholder='PT.Indoteknik'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.company?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Alamat*</label>
+ <input
+ {...register('address')}
+ placeholder='jl. Bandengan no.31 '
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.address?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>No. Telp *</label>
+ <input
+ {...register('phone')}
+ placeholder='021-XXXX'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Kota*</label>
+ <Controller
+ name='city'
+ control={control}
+ render={(props) => <HookFormSelect {...props} options={cities} />}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.city?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Unit Perusahaan*</label>
+ <Controller
+ name='company_unit'
+ control={control}
+ render={(props) => <HookFormSelect {...props} options={company_unit} />}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.company_unit?.message}
+ </div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Website *</label>
+ <input
+ {...register('website')}
+ placeholder='https://indoteknik.com'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.website?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Contact Person*</label>
+ <input
+ {...register('cp')}
+ placeholder='Jhone doe'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.cp?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>No HP *</label>
+ <input
+ {...register('mobile')}
+ placeholder='628XXXXXXX'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.mobile?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Alamat Email *</label>
+ <input
+ {...register('email')}
+ placeholder='contoh@email.com'
+ type='email'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <button type='submit' className='btn-yellow w-full md:w-fit mt-6 ml-0 md:ml-auto'>
+ Simpan
+ </button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+ )
+}
+const validationSchema = Yup.object().shape({
+ company: Yup.string().required('Harus di-isi'),
+ email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ phone: Yup.string().required('Harus di-isi'),
+ cp: Yup.string().required('Harus di-isi'),
+ city: Yup.string().required('Harus di-isi'),
+ company_unit: Yup.string().required('Harus di-isi'),
+ address: Yup.string().required('Harus di-isi'),
+ website: Yup.string().required('Harus di-isi'),
+ mobile: Yup.string().required('Harus di-isi')
+})
+const defaultValues = {
+ company: '',
+ email: '',
+ phone: '',
+ city: '',
+ company_unit: '',
+ cp: '',
+ address: '',
+ website: '',
+ mobile: ''
+}
+
+export default CreateMerchant
diff --git a/src/lib/form/components/PembayaranTempo.jsx b/src/lib/form/components/PembayaranTempo.jsx
index 5f32753e..ffdb0961 100644
--- a/src/lib/form/components/PembayaranTempo.jsx
+++ b/src/lib/form/components/PembayaranTempo.jsx
@@ -52,7 +52,7 @@ const PembayaranTempo = () => {
return (
<div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
<h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Pembayaran Tempo</h1>
-
+
<div className='w-full grid grid-cols-1 md:grid-cols-2'>
<form onSubmit={handleSubmit(onSubmitHandler)} className='grid grid-cols-1 gap-y-6'>
<div>
diff --git a/src/lib/form/components/SuratDukungan.jsx b/src/lib/form/components/SuratDukungan.jsx
index 22452b3c..0eab84a4 100644
--- a/src/lib/form/components/SuratDukungan.jsx
+++ b/src/lib/form/components/SuratDukungan.jsx
@@ -6,7 +6,7 @@ import ReCAPTCHA from 'react-google-recaptcha'
import { Controller, useForm } from 'react-hook-form'
import { toast } from 'react-hot-toast'
import * as Yup from 'yup'
-import createLeadsApi from '../api/createLeadsApi'
+import createLeadsApi from '../api/createLeadApi'
const CreateSuratDukungan = () => {
const {
@@ -41,18 +41,34 @@ const CreateSuratDukungan = () => {
}
const data = {
...values,
- name : 'Pengajuan Kunjungan Service - ' + values.company,
- contact_name : values.cp,
- email_from : values.email,
- phone : values.mobile,
- description : "\r\n Nama Perusahaan : " + values.company + " \r\n Alamat : " + values.address + " \r\n Propinsi : " + values.city + " \r\n Telepon: " + values.phone + " \r\n Handphone : " + values.mobile +" \r\n Email : " + values.email + " \r\n Keterangan : " + values.description ,
+ name: 'Permintaan Surat Dukungan - ' + values.company,
+ contact_name: values.company,
+ email_from: values.email,
+ phone: values.phone,
+ description:
+ 'Nama Perusahaan : ' +
+ values.company +
+ ' \r\n Alamat : ' +
+ values.address +
+ ' \r\n Npwp : ' +
+ values.npwp +
+ ' \r\n Telepon: ' +
+ values.phone +
+ ' \r\n Email : ' +
+ values.email +
+ ' \r\n Pengadaan : ' +
+ values.pengadaan +
+ ' \r\n Alamat 2 : ' +
+ values.address2 +
+ 'Keterangan : ' +
+ values.description
}
const create_leads = await createLeadsApi({ data })
if (create_leads) {
toast.success('Berhasil menambahkan alamat')
reset()
- recaptchaRef.current.reset()
+ recaptchaRef.current.reset()
}
}
return (
@@ -63,9 +79,10 @@ const CreateSuratDukungan = () => {
class='flex items-center bg-blue-100 border border-blue-400 text-blue-500 font-bold px-4 py-3 mb-4'
role='alert'
>
- <p>
- Lengkapi form berikut untuk melakukan konfirmasi pembayaran.
- </p>
+ <p>Lengkapi form berikut untuk melakukan konfirmasi pembayaran.</p>
+ </div>
+ <div className=' w-full md:w-[50%] p-4 bg-gray-50 border border-gray_r-6 rounded text-center'>
+ <h1>Data Peserta</h1>
</div>
<form onSubmit={handleSubmit(onSubmitHandler)}>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
@@ -82,18 +99,6 @@ const CreateSuratDukungan = () => {
</div>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
<div>
- <label className='form-label mb-2'>No. Telp *</label>
- <input
- {...register('phone')}
- placeholder='021-XXXX'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
- </div>
- </div>
- <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
- <div>
<label className='form-label mb-2'>Alamat*</label>
<input
{...register('address')}
@@ -106,39 +111,26 @@ const CreateSuratDukungan = () => {
</div>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
<div>
- <label className='form-label mb-2'>Kota*</label>
- <Controller
- name='city'
- control={control}
- render={(props) => <HookFormSelect {...props} options={cities} />}
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.city?.message}</div>
- </div>
- </div>
- <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
- <div>
- <label className='form-label mb-2'>Contact Person*</label>
+ <label className='form-label mb-2'>No. Telp *</label>
<input
- {...register('cp')}
- placeholder='Jhone doe'
+ {...register('phone')}
+ placeholder='021-XXXX'
type='text'
className='form-input'
/>
- <div className='text-caption-2 text-danger-500 mt-1'>
- {errors.cp?.message}
- </div>
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
</div>
</div>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
<div>
- <label className='form-label mb-2'>No HP *</label>
+ <label className='form-label mb-2'>NPWP *</label>
<input
- {...register('mobile')}
- placeholder='628XXXXXXX'
+ {...register('npwp')}
+ placeholder='npwp number'
type='text'
className='form-input'
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.mobile?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.npwp?.message}</div>
</div>
</div>
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
@@ -153,10 +145,36 @@ const CreateSuratDukungan = () => {
<div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
</div>
</div>
+ <div className='w-[50%] mt-10 p-4 bg-gray-50 border border-gray_r-6 rounded text-center'>
+ <h1>Data Peserta</h1>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Pengadaan *</label>
+ <input {...register('pengadaan')} placeholder='' type='text' className='form-input' />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.pengadaan?.message}</div>
+ </div>
+ </div>
+ <div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
+ <div>
+ <label className='form-label mb-2'>Alamat *</label>
+ <textarea
+ {...register('address2')}
+ placeholder=''
+ type='text'
+ className='form-input h-[120px]'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>{errors.address2?.message}</div>
+ </div>
+ </div>
+ <div className='w-[50%] mt-10 p-4 bg-gray-50 border border-gray_r-6 rounded text-center'>
+ <h1>Data Produk</h1>
+ </div>
+
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 mt-4'>
<div>
- <label className='form-label mb-2'>Sebutkan: Merek, Tipe, Permasalahan, Service, Perawatan</label>
- <textarea {...register('description')} type='text' className='form-input' />
+ <label className='form-label mb-2'>Produk</label>
+ <textarea {...register('description')} type='text' className='form-input h-[120px]' />
<div className='text-caption-2 text-danger-500 mt-1'>
{errors.description?.message}
</div>
@@ -180,24 +198,24 @@ const CreateSuratDukungan = () => {
)
}
const validationSchema = Yup.object().shape({
- company: Yup.string().required('Harus di-isi'),
- email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
- phone: Yup.string().required('Harus di-isi'),
- city: Yup.string().required('Harus di-isi'),
- cp: Yup.string().required('Harus di-isi'),
- mobile: Yup.string().required('Harus di-isi'),
- email: Yup.string().required('Harus di-isi'),
- address: Yup.string().required('Harus di-isi')
+ company: Yup.string().required('Harus di-isi'),
+ email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ phone: Yup.string().required('Harus di-isi'),
+ npwp: Yup.string().required('Harus di-isi'),
+ pengadaan: Yup.string().required('Harus di-isi'),
+ email: Yup.string().required('Harus di-isi'),
+ address: Yup.string().required('Harus di-isi'),
+ address2: Yup.string().required('Harus di-isi')
})
const defaultValues = {
- company:'',
- email: '',
- phone: '',
- city: '',
- cp: '',
- mobile: '',
- email: '',
- address: ''
+ company: '',
+ email: '',
+ phone: '',
+ pengadaan: '',
+ npwp: '',
+ email: '',
+ address: '',
+ address2: ''
}
export default CreateSuratDukungan
diff --git a/src/lib/home/components/HeroBanner.jsx b/src/lib/home/components/HeroBanner.jsx
index e6136e03..50cfc0ff 100644
--- a/src/lib/home/components/HeroBanner.jsx
+++ b/src/lib/home/components/HeroBanner.jsx
@@ -10,6 +10,7 @@ import 'swiper/css/pagination'
import 'swiper/css/autoplay'
import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
+import Link from '@/core/components/elements/Link/Link'
const HeroBanner = () => {
const { heroBanners } = useHeroBanner()
@@ -41,7 +42,9 @@ const HeroBanner = () => {
<Swiper slidesPerView={1} className='border border-gray_r-6' {...swiperBannerMobile}>
{heroBanners.data?.map((banner, index) => (
<SwiperSlide key={index}>
- <Image src={banner.image} alt={banner.name} className='w-full h-auto' />
+ <Link href={banner.url || ''} className='w-full h-auto'>
+ <Image src={banner.image} alt={banner.name} className='w-full h-auto' />
+ </Link>
</SwiperSlide>
))}
</Swiper>
@@ -50,7 +53,9 @@ const HeroBanner = () => {
<Swiper slidesPerView={1} className='border border-gray_r-6' {...swiperBannerDesktop}>
{heroBanners.data?.map((banner, index) => (
<SwiperSlide key={index}>
- <Image src={banner.image} alt={banner.name} className='w-full h-auto' />
+ <Link href={banner.url || ''} className='w-full h-auto'>
+ <Image src={banner.image} alt={banner.name} className='w-full h-auto' />
+ </Link>
</SwiperSlide>
))}
</Swiper>
diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx
index f97943cb..34c50220 100644
--- a/src/lib/home/components/PreferredBrand.jsx
+++ b/src/lib/home/components/PreferredBrand.jsx
@@ -14,7 +14,7 @@ const PreferredBrand = () => {
<div className='flex justify-between items-center mb-4'>
<div className='font-medium sm:text-h-lg'>Brand Pilihan</div>
{isDesktop && (
- <Link href='/' className='btn-yellow !text-gray_r-12'>
+ <Link href='/shop/brands' className='btn-yellow !text-gray_r-12'>
Lihat Semua
</Link>
)}
diff --git a/src/lib/invoice/components/Invoices.jsx b/src/lib/invoice/components/Invoices.jsx
index 6f7d54a0..96686bbb 100644
--- a/src/lib/invoice/components/Invoices.jsx
+++ b/src/lib/invoice/components/Invoices.jsx
@@ -24,7 +24,7 @@ const Invoices = () => {
const router = useRouter()
const { q = '', page = 1 } = router.query
- const limit = 10
+ const limit = 15
const query = {
name: q,
@@ -36,7 +36,7 @@ const Invoices = () => {
const [inputQuery, setInputQuery] = useState(q)
const [toOthers, setToOthers] = useState(null)
- const pageCount = Math.ceil(invoices?.data?.saleOrderTotal / limit)
+ const pageCount = Math.ceil(invoices?.data?.invoiceTotal / limit)
let pageQuery = _.omit(query, ['limit', 'offset'])
pageQuery = _.pickBy(pageQuery, _.identity)
pageQuery = toQuery(pageQuery)
@@ -78,7 +78,7 @@ const Invoices = () => {
{invoices.data?.invoices?.map((invoice, index) => (
<div className='p-4 shadow border border-gray_r-3 rounded-md' key={index}>
<div className='grid grid-cols-2'>
- <Link href={`/my/invoice/${invoice.id}`}>
+ <Link href={`${router.pathname}/${invoice.id}`}>
<span className='text-caption-2 text-gray_r-11'>No. Invoice</span>
<h2 className='text-danger-500 mt-1'>{invoice.name}</h2>
</Link>
@@ -91,7 +91,7 @@ const Invoices = () => {
<EllipsisVerticalIcon className='w-5 h-5' onClick={() => setToOthers(invoice)} />
</div>
</div>
- <Link href={`/my/invoice/${invoice.id}`}>
+ <Link href={`${router.pathname}/${invoice.id}`}>
<div className='grid grid-cols-2 text-caption-2 text-gray_r-11 mt-2 font-normal'>
<p>{invoice.invoiceDate}</p>
<p className='text-right'>{invoice.paymentTerm}</p>
@@ -214,7 +214,7 @@ const Invoices = () => {
{invoices.data?.invoices?.map((invoice) => (
<tr key={invoice.id}>
<td>
- <Link href={`/my/invoice/${invoice.id}`}>{invoice.name}</Link>
+ <Link href={`${router.pathname}/${invoice.id}`}>{invoice.name}</Link>
</td>
<td>{invoice.purchaseOrderName || '-'}</td>
<td>{invoice.invoiceDate}</td>
@@ -235,7 +235,7 @@ const Invoices = () => {
<Pagination
pageCount={pageCount}
currentPage={parseInt(page)}
- url={`/my/transactions${pageQuery}`}
+ url={`/my/invoices${pageQuery}`}
className='mt-2 mb-2'
/>
</div>
diff --git a/src/lib/product/api/productApi.js b/src/lib/product/api/productApi.js
index 8156d1ec..33f1265c 100644
--- a/src/lib/product/api/productApi.js
+++ b/src/lib/product/api/productApi.js
@@ -1,8 +1,8 @@
import odooApi from '@/core/api/odooApi'
-const productApi = async ({ id }) => {
+const productApi = async ({ id, headers = {} }) => {
if (!id) return
- const dataProduct = await odooApi('GET', `/api/v2/product/${id}`)
+ const dataProduct = await odooApi('GET', `/api/v2/product/${id}`, {}, headers)
return dataProduct
}
diff --git a/src/lib/product/api/productSearchApi.js b/src/lib/product/api/productSearchApi.js
index 71fb72e6..1626b7b7 100644
--- a/src/lib/product/api/productSearchApi.js
+++ b/src/lib/product/api/productSearchApi.js
@@ -1,9 +1,9 @@
import _ from 'lodash-contrib'
import axios from 'axios'
-const productSearchApi = async ({ query }) => {
+const productSearchApi = async ({ query, operation = 'AND' }) => {
const dataProductSearch = await axios(
- `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/search?${query}&operation=OR`
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/search?${query}&operation=${operation}`
)
return dataProductSearch.data
}
diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx
index bb2b2db9..8ce6da00 100644
--- a/src/lib/product/components/Product/ProductDesktop.jsx
+++ b/src/lib/product/components/Product/ProductDesktop.jsx
@@ -11,7 +11,9 @@ import { updateItemCart } from '@/core/utils/cart'
import { useRouter } from 'next/router'
import { createSlug } from '@/core/utils/slug'
import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
-import { Toast } from 'flowbite-react'
+import ProductCard from '../ProductCard'
+import productSimilarApi from '../../api/productSimilarApi'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
const router = useRouter()
@@ -59,7 +61,6 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
selected: true
})
setAddCartAlert(true)
- // toast.success('Berhasil menambahkan ke keranjang')
}
const handleBuy = (variantId) => {
@@ -85,61 +86,117 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
`fq=-manufacture_id_i:${product.manufacture?.id || 0}`
].join('&')
+ const [productSimilarInBrand, setProductSimilarInBrand] = useState(null)
+
+ useEffect(() => {
+ const loadProductSimilarInBrand = async () => {
+ const productSimilarQuery = [product?.name, `fq=-product_id_i:${product.id}`].join('&')
+ const dataProductSimilar = await productSimilarApi({ query: productSimilarQuery })
+ setProductSimilarInBrand(dataProductSimilar.products)
+ }
+ if (!productSimilarInBrand) loadProductSimilarInBrand()
+ }, [product, productSimilarInBrand])
+
return (
<DesktopView>
<div className='container mx-auto pt-10'>
<div className='flex'>
- <div className='w-[30%]'>
- <Image
- src={product.image}
- alt={product.name}
- className='h-96 object-contain object-center w-full border border-gray_r-4'
- />
- </div>
- <div className='w-[50%] px-4'>
- <h1 className='text-title-md leading-10 font-medium'>{product?.name}</h1>
- <div className='mt-10'>
- <div className='flex p-3'>
- <div className='w-1/4 text-gray_r-12/70'>Nomor SKU</div>
- <div className='w-3/4'>SKU-{product.id}</div>
- </div>
- <div className='flex p-3 bg-gray_r-4'>
- <div className='w-1/4 text-gray_r-12/70'>Part Number</div>
- <div className='w-3/4'>{product.code || '-'}</div>
+ <div className='w-full flex flex-wrap'>
+ <div className='w-5/12'>
+ <Image
+ src={product.image}
+ alt={product.name}
+ className='h-96 object-contain object-center w-full border border-gray_r-4'
+ />
+ </div>
+
+ <div className='w-7/12 px-4'>
+ <h1 className='text-title-md leading-10 font-medium'>{product?.name}</h1>
+ <div className='mt-10'>
+ <div className='flex p-3'>
+ <div className='w-1/4 text-gray_r-12/70'>Nomor SKU</div>
+ <div className='w-3/4'>SKU-{product.id}</div>
+ </div>
+ <div className='flex p-3 bg-gray_r-4'>
+ <div className='w-1/4 text-gray_r-12/70'>Part Number</div>
+ <div className='w-3/4'>{product.code || '-'}</div>
+ </div>
+ <div className='flex p-3'>
+ <div className='w-1/4 text-gray_r-12/70'>Manufacture</div>
+ <div className='w-3/4'>
+ {product.manufacture?.name ? (
+ <Link
+ href={createSlug(
+ '/shop/brands/',
+ product.manufacture?.name,
+ product.manufacture?.id
+ )}
+ >
+ {product.manufacture?.name}
+ </Link>
+ ) : (
+ <div>-</div>
+ )}
+ </div>
+ </div>
+ <div className='flex p-3 bg-gray_r-4'>
+ <div className='w-1/4 text-gray_r-12/70'>Berat Barang</div>
+ <div className='w-3/4'>
+ {product?.weight > 0 && <span>{product?.weight} KG</span>}
+ {product?.weight == 0 && (
+ <a
+ href={whatsappUrl('productWeight', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 font-medium'
+ >
+ Tanya Berat
+ </a>
+ )}
+ </div>
+ </div>
</div>
- <div className='flex p-3'>
- <div className='w-1/4 text-gray_r-12/70'>Manufacture</div>
- <div className='w-3/4'>
- {product.manufacture?.name ? (
- <Link
- href={createSlug(
- '/shop/brands/',
- product.manufacture?.name,
- product.manufacture?.id
- )}
+ </div>
+
+ <div className='w-full'>
+ <div className='mt-12'>
+ <div className='text-h-lg font-semibold'>Informasi Produk</div>
+ <div className='flex gap-x-4 mt-6 mb-4'>
+ {informationTabOptions.map((option) => (
+ <TabButton
+ value={option.value}
+ key={option.value}
+ active={informationTab == option.value}
+ onClick={() => setInformationTab(option.value)}
>
- {product.manufacture?.name}
- </Link>
- ) : (
- <div>-</div>
- )}
+ {option.label}
+ </TabButton>
+ ))}
</div>
- </div>
- <div className='flex p-3 bg-gray_r-4'>
- <div className='w-1/4 text-gray_r-12/70'>Berat Barang</div>
- <div className='w-3/4'>
- {product?.weight > 0 && <span>{product?.weight} KG</span>}
- {product?.weight == 0 && (
- <a href='https://wa.me' className='text-danger-500 font-medium'>
- Tanya Berat
- </a>
- )}
+ <div className='flex'>
+ <div className='w-3/4 leading-7 product__description'>
+ <TabContent active={informationTab == 'description'}>
+ <span
+ dangerouslySetInnerHTML={{
+ __html:
+ product.description != ''
+ ? product.description
+ : 'Belum ada deskripsi produk.'
+ }}
+ />
+ </TabContent>
+
+ <TabContent active={informationTab == 'information'}>
+ Belum ada informasi.
+ </TabContent>
+ </div>
</div>
</div>
</div>
</div>
- <div className='w-[20%]'>
+ <div className='w-[25%]'>
{product.variants.length > 1 && product.lowestPrice.priceDiscount > 0 && (
<div className='text-gray_r-12/80'>Harga mulai dari: </div>
)}
@@ -160,7 +217,13 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
) : (
<span className='text-gray_r-12/90 font-normal text-h-sm'>
Hubungi kami untuk dapatkan harga terbaik,&nbsp;
- <a href='https://wa.me/' className='text-danger-500 underline'>
+ <a
+ href={whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 underline'
+ >
klik disini
</a>
</span>
@@ -209,6 +272,20 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
Wishlist
</button>
</div>
+
+ <div className='border border-gray_r-6 overflow-auto mt-4'>
+ <div className='font-medium text-center p-4 bg-gray_r-1 border-b border-gray_r-6 sticky top-0 z-10'>
+ Produk Serupa
+ </div>
+ <div className='h-full divide-y divide-gray_r-6 max-h-96'>
+ {productSimilarInBrand &&
+ productSimilarInBrand?.map((product) => (
+ <div className='py-2' key={product.id}>
+ <ProductCard product={product} variant='horizontal' />
+ </div>
+ ))}
+ </div>
+ </div>
</div>
</div>
@@ -244,7 +321,13 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
{variant.price.priceDiscount > 0 ? (
currencyFormat(variant.price.priceDiscount)
) : (
- <a href='https://wa.me/' className='text-red_r-11'>
+ <a
+ href={whatsappUrl('product', {
+ name: variant.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-red_r-11'
+ >
Call for price
</a>
)}
@@ -283,38 +366,6 @@ const ProductDesktop = ({ product, wishlist, toggleWishlist }) => {
</div>
)}
- <div className='mt-12'>
- <div className='text-h-lg font-semibold'>Informasi Produk</div>
- <div className='flex gap-x-4 mt-6 mb-4'>
- {informationTabOptions.map((option) => (
- <TabButton
- value={option.value}
- key={option.value}
- active={informationTab == option.value}
- onClick={() => setInformationTab(option.value)}
- >
- {option.label}
- </TabButton>
- ))}
- </div>
- <div className='flex'>
- <div className='w-3/4 leading-7 product__description'>
- <TabContent active={informationTab == 'description'}>
- <span
- dangerouslySetInnerHTML={{
- __html:
- product.description != ''
- ? product.description
- : 'Belum ada deskripsi produk.'
- }}
- />
- </TabContent>
-
- <TabContent active={informationTab == 'information'}>Belum ada informasi.</TabContent>
- </div>
- </div>
- </div>
-
<div className='my-12'>
<div className='text-h-lg font-semibold mb-6'>Kamu Mungkin Juga Suka</div>
<LazyLoad>
diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx
index b75a191b..426fe1b8 100644
--- a/src/lib/product/components/Product/ProductMobile.jsx
+++ b/src/lib/product/components/Product/ProductMobile.jsx
@@ -13,6 +13,7 @@ import MobileView from '@/core/components/views/MobileView'
import { toast } from 'react-hot-toast'
import { createSlug } from '@/core/utils/slug'
import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
const router = useRouter()
@@ -152,7 +153,13 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
) : (
<span className='text-gray_r-11 leading-6 font-normal'>
Hubungi kami untuk dapatkan harga terbaik,&nbsp;
- <a href='https://wa.me/' className='text-danger-500 underline'>
+ <a
+ href={whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 underline'
+ >
klik disini
</a>
</span>
@@ -236,7 +243,13 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
</span>
)}
{activeVariant?.stock == 0 && (
- <a href='https://wa.me' className='text-danger-500 font-medium'>
+ <a
+ href={whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 font-medium'
+ >
Tanya Stok
</a>
)}
@@ -244,7 +257,13 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
<SpecificationContent label='Berat Barang'>
{activeVariant?.weight > 0 && <span>{activeVariant?.weight} KG</span>}
{activeVariant?.weight == 0 && (
- <a href='https://wa.me' className='text-danger-500 font-medium'>
+ <a
+ href={whatsappUrl('productWeight', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='text-danger-500 font-medium'
+ >
Tanya Berat
</a>
)}
diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx
index a1c30d00..9300643e 100644
--- a/src/lib/product/components/ProductCard.jsx
+++ b/src/lib/product/components/ProductCard.jsx
@@ -2,8 +2,14 @@ import Image from '@/core/components/elements/Image/Image'
import Link from '@/core/components/elements/Link/Link'
import currencyFormat from '@/core/utils/currencyFormat'
import { createSlug } from '@/core/utils/slug'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
+ const callForPriceWhatsapp = whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })
+
if (variant == 'vertical') {
return (
<div className='rounded shadow-sm border border-gray_r-4 h-full bg-white'>
@@ -58,7 +64,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
{product?.lowestPrice.priceDiscount > 0 ? (
currencyFormat(product?.lowestPrice.priceDiscount)
) : (
- <a href='https://wa.me/'>Call for price</a>
+ <a href={callForPriceWhatsapp}>Call for price</a>
)}
</div>
@@ -130,7 +136,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
{product?.lowestPrice?.priceDiscount > 0 ? (
currencyFormat(product?.lowestPrice?.priceDiscount)
) : (
- <a href='https://wa.me/'>Call for price</a>
+ <a href={callForPriceWhatsapp}>Call for price</a>
)}
</div>
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index 81e7948b..cc85589d 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
import useProductSearch from '../hooks/useProductSearch'
import ProductCard from './ProductCard'
import Pagination from '@/core/components/elements/Pagination/Pagination'
@@ -12,6 +12,9 @@ import DesktopView from '@/core/components/views/DesktopView'
import NextImage from 'next/image'
import ProductFilterDesktop from './ProductFilterDesktop'
import { useRouter } from 'next/router'
+import searchSpellApi from '@/core/api/searchSpellApi'
+import Link from '@/core/components/elements/Link/Link'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
const router = useRouter()
@@ -19,6 +22,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
if (defaultBrand) query.brand = defaultBrand.toLowerCase()
const { productSearch } = useProductSearch({ query })
const [products, setProducts] = useState(null)
+ const [spellings, setSpellings] = useState(null)
const popup = useActive()
const pageCount = Math.ceil(
@@ -28,6 +32,30 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
const productRows = productSearch.data?.responseHeader.params.rows
const productFound = productSearch.data?.response.numFound
+ useEffect(() => {
+ if (productFound == 0 && query.q) {
+ searchSpellApi({ query: query.q }).then((response) => {
+ const oddIndexSuggestions = response.data.spellcheck.suggestions.filter(
+ (_, index) => index % 2 === 1
+ )
+ const oddIndexCollations = response.data.spellcheck.collations.filter(
+ (_, index) => index % 2 === 1
+ )
+ const dataSpellings = oddIndexSuggestions.reduce((acc, curr) => {
+ oddIndexCollations.forEach((collation) => {
+ acc.push(collation.collationQuery)
+ })
+ curr.suggestion.forEach((s) => {
+ if (!acc.includes(s.word)) acc.push(s.word)
+ })
+ return acc
+ }, [])
+
+ setSpellings(dataSpellings)
+ })
+ }
+ }, [productFound, query])
+
const brands = productSearch.data?.facetCounts?.facetFields?.manufactureName?.filter(
(value, index) => {
if (index % 2 === 0) {
@@ -66,6 +94,20 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
}
}, [query, products, productSearch])
+ const SpellingComponent = useMemo(() => {
+ return (
+ <>
+ Mungkin yang anda cari{' '}
+ {spellings?.map((spelling, i) => (
+ <Link href={`/shop/search?q=${spelling}`} key={i} className='inline'>
+ {spelling}
+ {i + 1 < spellings.length ? ', ' : ''}
+ </Link>
+ ))}
+ </>
+ )
+ }, [spellings])
+
return (
<>
<MobileView>
@@ -97,13 +139,15 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
)}
</>
) : (
- 'Mungkin yang anda cari'
+ SpellingComponent
)}
</div>
- <button className='btn-light mb-6 py-2 px-5' onClick={popup.activate}>
- Filter
- </button>
+ {productFound > 0 && (
+ <button className='btn-light mb-6 py-2 px-5' onClick={popup.activate}>
+ Filter
+ </button>
+ )}
<div className='grid grid-cols-2 gap-3'>
{products &&
@@ -127,6 +171,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
/>
</div>
</MobileView>
+
<DesktopView>
<div className='container mx-auto mt-10 flex mb-3'>
<div className='w-3/12'>
@@ -164,7 +209,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
)}
</>
) : (
- 'Mungkin yang anda cari'
+ SpellingComponent
)}
</div>
<div className='justify-end flex '>
@@ -202,7 +247,12 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
<div className='text-gray_r-12/90'>
<span>
Barang yang anda cari tidak ada?{' '}
- <a href='#' className='text-danger-500'>
+ <a
+ href={whatsappUrl('productSearch', {
+ name: query.q
+ })}
+ className='text-danger-500'
+ >
Hubungi Kami
</a>
</span>
diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx
index a68889f5..6ff40327 100644
--- a/src/lib/quotation/components/Quotation.jsx
+++ b/src/lib/quotation/components/Quotation.jsx
@@ -15,7 +15,6 @@ import VariantGroupCard from '@/lib/variant/components/VariantGroupCard'
import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
import Image from '@/core/components/elements/Image/Image'
-import variantPriceApi from '@/lib/variant/api/variantPriceApi'
const Quotation = () => {
const router = useRouter()
@@ -32,15 +31,9 @@ const Quotation = () => {
.map((o) => o.productId)
.join(',')
const dataProducts = await CartApi({ variantIds })
- const productsWithQuantity = dataProducts?.map(async (product) => {
- const productPrice = await variantPriceApi({ id: product.id })
+ const productsWithQuantity = dataProducts?.map((product) => {
return {
...product,
- price: {
- price: productPrice.priceExclude,
- discountPercentage: productPrice.discount,
- priceDiscount: productPrice.priceExcludeAfterDiscount
- },
quantity: getItemCart({ productId: product.id }).quantity
}
})
diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx
index 3e3f2cc7..30bb454a 100644
--- a/src/lib/transaction/components/Transaction.jsx
+++ b/src/lib/transaction/components/Transaction.jsx
@@ -2,7 +2,7 @@ import Spinner from '@/core/components/elements/Spinner/Spinner'
import useTransaction from '../hooks/useTransaction'
import TransactionStatusBadge from './TransactionStatusBadge'
import Divider from '@/core/components/elements/Divider/Divider'
-import { useEffect, useMemo, useRef, useState } from 'react'
+import { useMemo, useRef, useState } from 'react'
import { downloadPurchaseOrder, downloadQuotation } from '../utils/transactions'
import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
import uploadPoApi from '../api/uploadPoApi'
diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx
index 13417707..bfb8c66b 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -19,15 +19,16 @@ import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
import Menu from '@/lib/auth/components/Menu'
-const Transactions = () => {
+const Transactions = ({ context = '' }) => {
const router = useRouter()
const { q = '', page = 1 } = router.query
- const limit = 10
+ const limit = 15
const query = {
name: q,
offset: (page - 1) * limit,
+ context,
limit
}
const { transactions } = useTransactions({ query })
@@ -48,13 +49,13 @@ const Transactions = () => {
}
const pageCount = Math.ceil(transactions?.data?.saleOrderTotal / limit)
- let pageQuery = _.omit(query, ['limit', 'offset'])
+ let pageQuery = _.omit(query, ['limit', 'offset', 'context'])
pageQuery = _.pickBy(pageQuery, _.identity)
pageQuery = toQuery(pageQuery)
const handleSubmit = (e) => {
e.preventDefault()
- router.push(`/my/transactions?q=${inputQuery}`)
+ router.push(`${router.pathname}?q=${inputQuery}`)
}
return (
@@ -89,7 +90,7 @@ const Transactions = () => {
{transactions.data?.saleOrders?.map((saleOrder, index) => (
<div className='p-4 shadow border border-gray_r-3 rounded-md' key={index}>
<div className='grid grid-cols-2'>
- <Link href={`/my/transaction/${saleOrder.id}`}>
+ <Link href={`${router.pathname}/${saleOrder.id}`}>
<span className='text-caption-2 text-gray_r-11'>No. Transaksi</span>
<h2 className='text-danger-500 mt-1'>{saleOrder.name}</h2>
</Link>
@@ -101,7 +102,7 @@ const Transactions = () => {
/>
</div>
</div>
- <Link href={`/my/transaction/${saleOrder.id}`}>
+ <Link href={`${router.pathname}/${saleOrder.id}`}>
<div className='grid grid-cols-2 mt-3'>
<div>
<span className='text-caption-2 text-gray_r-11'>No. Purchase Order</span>
@@ -135,7 +136,7 @@ const Transactions = () => {
<Pagination
pageCount={pageCount}
currentPage={parseInt(page)}
- url={`/my/transactions${pageQuery}`}
+ url={router.pathname + pageQuery}
className='mt-2 mb-2'
/>
@@ -249,7 +250,7 @@ const Transactions = () => {
{transactions.data?.saleOrders?.map((saleOrder) => (
<tr key={saleOrder.id}>
<td>
- <Link href={`/my/transaction/${saleOrder.id}`}>{saleOrder.name}</Link>
+ <Link href={`${router.pathname}/${saleOrder.id}`}>{saleOrder.name}</Link>
</td>
<td>-</td>
<td className='!text-left'>{saleOrder.sales}</td>
@@ -267,7 +268,7 @@ const Transactions = () => {
<Pagination
pageCount={pageCount}
currentPage={parseInt(page)}
- url={`/my/transactions${pageQuery}`}
+ url={router.pathname + pageQuery}
className='mt-2 mb-2'
/>
</div>
diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx
index 28f3e193..0f9f02f6 100644
--- a/src/lib/variant/components/VariantCard.jsx
+++ b/src/lib/variant/components/VariantCard.jsx
@@ -6,6 +6,7 @@ import Link from '@/core/components/elements/Link/Link'
import { createSlug } from '@/core/utils/slug'
import currencyFormat from '@/core/utils/currencyFormat'
import { updateItemCart } from '@/core/utils/cart'
+import whatsappUrl from '@/core/utils/whatsappUrl'
const VariantCard = ({ product, openOnClick = true, buyMore = false }) => {
const router = useRouter()
@@ -60,7 +61,13 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => {
{product.price.priceDiscount > 0 ? (
currencyFormat(product.quantity * product.price.priceDiscount)
) : (
- <a href='https://wa.me/628128080622' className='underline text-danger-500'>
+ <a
+ href={whatsappUrl('product', {
+ name: product.name,
+ url: createSlug('/shop/product/', product.name, product.id, true)
+ })}
+ className='underline text-danger-500'
+ >
Call For Price{' '}
</a>
)}
diff --git a/src/pages/404.jsx b/src/pages/404.jsx
new file mode 100644
index 00000000..f73e6383
--- /dev/null
+++ b/src/pages/404.jsx
@@ -0,0 +1,22 @@
+import Seo from '@/core/components/Seo'
+import Link from '@/core/components/elements/Link/Link'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import Image from 'next/image'
+
+export default function PageNotFound() {
+ return (
+ <BasicLayout>
+ <Seo title='Halaman tidak ditemukan - Indoteknik.com' />
+ <div className='container mx-auto'>
+ <Image
+ src='/images/page-not-found.svg'
+ alt='Page not found - Indoteknik'
+ className='w-full'
+ width={1024}
+ height={512}
+ />
+ <Link href='/' className='btn-yellow text-black mx-auto mt-4'>Kembali ke halaman utama</Link>
+ </div>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index 3c93d27f..2d74d8b7 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -1,7 +1,7 @@
import '../styles/globals.css'
import NextProgress from 'next-progress'
import { useRouter, Router } from 'next/router'
-import { AnimatePresence } from 'framer-motion'
+import { AnimatePresence, motion } from 'framer-motion'
import { Toaster } from 'react-hot-toast'
import { QueryClient, QueryClientProvider } from 'react-query'
import useDevice from '@/core/hooks/useDevice'
@@ -17,12 +17,17 @@ function MyApp({ Component, pageProps }) {
const [animateLoader, setAnimateLoader] = useState(false)
useEffect(() => {
- Router.events.on('routeChangeStart', () => setAnimateLoader(true))
- Router.events.on('routeChangeComplete', () => 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)
return () => {
- Router.events.off('routeChangeStart', () => setAnimateLoader(true))
- Router.events.off('routeChangeComplete', () => setAnimateLoader(false))
+ Router.events.off('routeChangeStart', handleRouteChangeStart)
+ Router.events.off('routeChangeComplete', handleRouteChangeComplete)
+ Router.events.off('routeChangeError', handleRouteChangeComplete)
}
}, [])
@@ -43,11 +48,21 @@ function MyApp({ Component, pageProps }) {
return (
<>
- {animateLoader && (
- <div className='w-screen h-screen z-[500] flex justify-center items-center backdrop-blur'>
- <LogoSpinner />
- </div>
- )}
+ <AnimatePresence>
+ {animateLoader && (
+ <motion.div
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ exit={{ opacity: 0 }}
+ transition={{
+ duration: 0.1
+ }}
+ className='fixed w-screen h-screen z-[500] bg-white flex justify-center items-center'
+ >
+ <LogoSpinner />
+ </motion.div>
+ )}
+ </AnimatePresence>
<Toaster
position='top-center'
containerStyle={toasterStyle}
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index ff205a38..dbe210aa 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -2,9 +2,13 @@ import { Html, Head, Main, NextScript } from 'next/document'
import Script from 'next/script'
export default function MyDocument() {
+ const env = process.env.NODE_ENV
+
return (
<Html>
<Head>
+ <link rel='icon' href='/favicon.ico' />
+
<meta name='facebook-domain-verification' content='328wmjs7hcnz74rwsqzxvq50rmbtm2' />
<Script
async
@@ -57,6 +61,24 @@ export default function MyDocument() {
}}
/>
+ {/* <Script
+ id='tawk-script-tag'
+ strategy='afterInteractive'
+ dangerouslySetInnerHTML={{
+ __html: `
+ var Tawk_API=Tawk_API||{}, Tawk_LoadStart=new Date();
+ (function(){
+ var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
+ s1.async=true;
+ s1.src='https://embed.tawk.to/643e00614247f20fefec36c5/1gu932vhh';
+ s1.charset='UTF-8';
+ s1.setAttribute('crossorigin','*');
+ s0.parentNode.insertBefore(s1,s0);
+ })();
+ `
+ }}
+ /> */}
+
<meta
name='google-site-verification'
content='uHuW_mZhjv_fUg3do-lV8Mo7R2vVjF4MPQhTXFP3jH4'
diff --git a/src/pages/activate.jsx b/src/pages/activate.jsx
index 48d9c4d3..8e9d8fbb 100644
--- a/src/pages/activate.jsx
+++ b/src/pages/activate.jsx
@@ -1,9 +1,11 @@
import Seo from '@/core/components/Seo'
-import SimpleFooter from '@/core/components/elements/Footer/SimpleFooter'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
import DesktopView from '@/core/components/views/DesktopView'
import MobileView from '@/core/components/views/MobileView'
-import ActivateComponent from '@/lib/auth/components/Activate'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const ActivateComponent = dynamic(() => import('@/lib/auth/components/Activate'))
+const SimpleFooter = dynamic(() => import('@/core/components/elements/Footer/SimpleFooter'))
export default function Activate() {
return (
diff --git a/src/pages/api/shop/finish-checkout.js b/src/pages/api/shop/finish-checkout.js
index 04e82118..9eaa36db 100644
--- a/src/pages/api/shop/finish-checkout.js
+++ b/src/pages/api/shop/finish-checkout.js
@@ -46,7 +46,7 @@ export default async function handler(req, res) {
}
}
- const query = `name=${orderName.replaceAll('-', '/')}&limit=1`
+ const query = `name=${orderName.replaceAll('-', '/')}&limit=1&context=quotation`
const searchTransaction = await odooApi(
'GET',
`/api/v1/partner/${auth.partnerId}/sale_order?${query}`,
diff --git a/src/pages/api/shop/midtrans-payment.js b/src/pages/api/shop/midtrans-payment.js
index 1772e9e0..12aaa51f 100644
--- a/src/pages/api/shop/midtrans-payment.js
+++ b/src/pages/api/shop/midtrans-payment.js
@@ -22,6 +22,7 @@ export default async function handler(req, res) {
{},
{ Token: auth.token }
)
+
if (!transaction?.id) {
return res.status(400).json({ error: 'No Data' })
}
@@ -48,7 +49,7 @@ export default async function handler(req, res) {
const parameter = {
transaction_details: {
order_id: transaction.name?.replaceAll('/', '-'),
- gross_amount: transaction.amountTotal
+ gross_amount: Math.floor(transaction.amountTotal)
},
credit_card: {
secure: true
@@ -56,17 +57,7 @@ export default async function handler(req, res) {
customer_details: {
first_name: transaction.address.customer.name,
email: transaction.address.customer.email || '',
- phone: transaction.address.customer.phone || '',
- billing_address: {
- first_name: transaction.address.invoice.name,
- email: transaction.address.invoice.email || '',
- phone: transaction.address.invoice.phone || ''
- },
- shipping_address: {
- first_name: transaction.address.shipping.name,
- email: transaction.address.shipping.email || '',
- phone: transaction.address.shipping.phone || ''
- }
+ phone: transaction.address.customer.phone || ''
}
}
diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js
index 19b9655a..2e6764fd 100644
--- a/src/pages/api/shop/search.js
+++ b/src/pages/api/shop/search.js
@@ -29,6 +29,9 @@ export default async function handler(req, res) {
case 'stock':
paramOrderBy += 'stock_total_f DESC'
break
+ default:
+ paramOrderBy += 'product_rating_f DESC, price_discount_f DESC'
+ break
}
let offset = (page - 1) * limit
@@ -43,10 +46,17 @@ export default async function handler(req, res) {
'qf=name_s',
`start=${offset}`,
`rows=${limit}`,
- `sort=${paramOrderBy}`,
- `fq=price_discount_f:[${priceFrom == '' ? '*' : priceFrom} TO ${priceTo == '' ? '*' : priceTo}]`
+ `sort=${paramOrderBy}`
]
+ if (priceFrom > 0 || priceTo > 0) {
+ parameter.push(
+ `fq=price_discount_f:[${priceFrom == '' ? '*' : priceFrom} TO ${
+ priceTo == '' ? '*' : priceTo
+ }]`
+ )
+ }
+
if (brand) parameter.push(`fq=manufacture_name:${brand}`)
if (category) parameter.push(`fq=category_name:${category}`)
@@ -57,7 +67,12 @@ export default async function handler(req, res) {
let result = await axios(process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&'))
try {
- result.data.response.products = productResponseMap(result.data.response.docs)
+ let { auth } = req.cookies
+ if (auth) auth = JSON.parse(auth)
+ result.data.response.products = productResponseMap(
+ result.data.response.docs,
+ auth?.pricelist || false
+ )
result.data.responseHeader.params.start = parseInt(result.data.responseHeader.params.start)
result.data.responseHeader.params.rows = parseInt(result.data.responseHeader.params.rows)
delete result.data.response.docs
@@ -83,23 +98,42 @@ const escapeSolrQuery = (query) => {
return escapedWords.join(' ')
}
-const productResponseMap = (products) => {
+const productResponseMap = (products, pricelist) => {
return products.map((product) => {
+ let price = product.price_f || 0
+ let priceDiscount = product.price_discount_f || 0
+ let discountPercentage = product.discount_f || 0
+
+ if (pricelist) {
+ const pricelistDiscount = product?.[`price_${pricelist}_f`] || false
+ const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false
+
+ if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount
+ if (pricelistDiscountPerc && pricelistDiscountPerc > 0)
+ discountPercentage = pricelistDiscountPerc
+ }
+
+ if (product?.flashsale_id_i > 0) {
+ price = product?.flashsale_base_price_f || 0
+ priceDiscount = product?.flashsale_price_f || 0
+ discountPercentage = product?.flashsale_discount_f || 0
+ }
+
let productMapped = {
id: product.product_id_i || '',
image: product.image_s || '',
code: product.default_code_s || '',
name: product.name_s || '',
- lowestPrice: {
- price: product.price_f || 0,
- priceDiscount: product.price_discount_f || 0,
- discountPercentage: product.discount_f || 0
- },
+ lowestPrice: { price, priceDiscount, discountPercentage },
variantTotal: product.variant_total_i || 0,
stockTotal: product.stock_total_f || 0,
weight: product.weight_f || 0,
manufacture: {},
- categories: []
+ categories: [],
+ flashSale: {
+ id: product?.flashsale_id_i,
+ name: product?.product?.flashsale_name_s
+ }
}
if (product.manufacture_id_i && product.manufacture_name_s) {
diff --git a/src/pages/api/shop/spell.js b/src/pages/api/shop/spell.js
new file mode 100644
index 00000000..4c01765c
--- /dev/null
+++ b/src/pages/api/shop/spell.js
@@ -0,0 +1,18 @@
+import axios from 'axios'
+
+export default async function handler(req, res) {
+ const { q = '' } = req.query
+
+ let result = await axios(
+ process.env.SOLR_HOST + `/solr/product/spell?indent=true&q.op=AND&q=${q}`
+ )
+
+ try {
+ res.status(200).json(result.data)
+ } catch (error) {
+ res.status(400).json({
+ numFound: 0,
+ suggestions: []
+ })
+ }
+}
diff --git a/src/pages/blog/[slug].jsx b/src/pages/blog/[slug].jsx
index 9305411d..39c0bb50 100644
--- a/src/pages/blog/[slug].jsx
+++ b/src/pages/blog/[slug].jsx
@@ -1,10 +1,11 @@
import Seo from '@/core/components/Seo'
-import Link from '@/core/components/elements/Link/Link'
import Spinner from '@/core/components/elements/Spinner/Spinner'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import { createSlug, getIdFromSlug } from '@/core/utils/slug'
+import { getIdFromSlug } from '@/core/utils/slug'
import useBlog from '@/lib/blog/hooks/useBlog'
import { useRouter } from 'next/router'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
export default function BlogDetail() {
const router = useRouter()
diff --git a/src/pages/blog/index.jsx b/src/pages/blog/index.jsx
index c65fe07d..17446935 100644
--- a/src/pages/blog/index.jsx
+++ b/src/pages/blog/index.jsx
@@ -1,12 +1,14 @@
-import BasicLayout from '@/core/components/layouts/BasicLayout'
import Link from 'next/link'
+import { useRouter } from 'next/router'
import { createSlug } from '@/core/utils/slug'
-import Image from '@/core/components/elements/Image/Image'
import useBlogs from '@/lib/blog/hooks/useBlogs'
-import { useRouter } from 'next/router'
-import Pagination from '@/core/components/elements/Pagination/Pagination'
-import Spinner from '@/core/components/elements/Spinner/Spinner'
import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const Pagination = dynamic(() => import('@/core/components/elements/Pagination/Pagination'))
+const Spinner = dynamic(() => import('@/core/components/elements/Spinner/Spinner'))
+const Image = dynamic(() => import('@/core/components/elements/Image/Image'))
export default function Blogs() {
const router = useRouter()
diff --git a/src/pages/contact-us.jsx b/src/pages/contact-us.jsx
deleted file mode 100644
index adbf9439..00000000
--- a/src/pages/contact-us.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import Seo from '@/core/components/Seo'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import PageContent from '@/lib/content/components/PageContent'
-
-export default function ContactUs() {
- return (
- <BasicLayout>
- <Seo title='Hubungi Indoteknik.com' />
- <PageContent path='/contact-us' />
- </BasicLayout>
- )
-}
diff --git a/src/pages/faqs.jsx b/src/pages/faqs.jsx
deleted file mode 100644
index e8ffb4e3..00000000
--- a/src/pages/faqs.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import Seo from '@/core/components/Seo'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import PageContent from '@/lib/content/components/PageContent'
-
-export default function ContactUs() {
- return (
- <BasicLayout>
- <Seo title='FAQS Indoteknik.com' />
- <PageContent path='/faqs' />
- </BasicLayout>
- )
-}
diff --git a/src/pages/hubungi-kami.jsx b/src/pages/hubungi-kami.jsx
new file mode 100644
index 00000000..a246b515
--- /dev/null
+++ b/src/pages/hubungi-kami.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function HubungiKami() {
+ return (
+ <BasicLayout>
+ <Seo title='Hubungi Kami - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/hubungi-kami' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 2a996b5d..5ca7b939 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -3,33 +3,29 @@ import ImageSkeleton from '@/core/components/elements/Skeleton/ImageSkeleton'
import PopularProductSkeleton from '@/lib/home/components/Skeleton/PopularProductSkeleton'
import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
-import { useEffect, useRef, useState } from 'react'
-import { NextSeo } from 'next-seo'
+import { useRef } from 'react'
import Seo from '@/core/components/Seo'
import { useQuery } from 'react-query'
import odooApi from '@/core/api/odooApi'
-import Image from '@/core/components/elements/Image/Image'
+import Image from 'next/image'
const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
-
+const FlashSale = dynamic(() => import('@/lib/flashSale/components/FlashSale'))
const HeroBanner = dynamic(() => import('@/lib/home/components/HeroBanner'), {
loading: () => <ImageSkeleton />
})
-
const PreferredBrand = dynamic(() => import('@/lib/home/components/PreferredBrand'), {
loading: () => <PopularProductSkeleton />
})
-
const PopularProduct = dynamic(() => import('@/lib/home/components/PopularProduct'), {
loading: () => <PopularProductSkeleton />
})
-
const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId'), {
loading: () => <PopularProductSkeleton />
})
export default function Home() {
- const fetchSecondHeroBanner = async () => await odooApi('GET', '/api/v1/banner?type=index-b-2')
+ const fetchSecondHeroBanner = async () => await odooApi('GET', '/api/v1/banner?type=index-a-2')
const secondHeroBanner = useQuery('secondHeroBanner', fetchSecondHeroBanner)
const bannerRef = useRef(null)
@@ -57,12 +53,18 @@ export default function Home() {
<DesktopView>
<div className='container mx-auto'>
<div className='flex h-[360px]' ref={wrapperRef} onLoad={handleOnLoad}>
- <div className='w-3/12'>
+ <div className='w-2/12'>
{secondHeroBanner.isFetched && (
- <Image src={secondHeroBanner.data[0].image} alt={secondHeroBanner.data[0].name} />
+ <Image
+ src={secondHeroBanner.data[0].image}
+ width={512}
+ height={1024}
+ alt={secondHeroBanner.data[0].name}
+ className='object-cover object-center h-full'
+ />
)}
</div>
- <div className='w-6/12 px-1' ref={bannerRef}>
+ <div className='w-7/12 px-1' ref={bannerRef}>
<HeroBanner />
</div>
<div className='w-3/12'>
@@ -72,6 +74,7 @@ export default function Home() {
<div className='my-16 flex flex-col gap-y-10'>
<PreferredBrand />
+ <FlashSale />
<CategoryHomeId />
</div>
</div>
@@ -81,6 +84,7 @@ export default function Home() {
<HeroBanner />
<div className='flex flex-col gap-y-6 my-6'>
<PreferredBrand />
+ <FlashSale />
<PopularProduct />
<CategoryHomeId />
</div>
diff --git a/src/pages/informasi-garansi.jsx b/src/pages/informasi-garansi.jsx
new file mode 100644
index 00000000..c4511d30
--- /dev/null
+++ b/src/pages/informasi-garansi.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function InformasiGaransi() {
+ return (
+ <BasicLayout>
+ <Seo title='Informasi Garansi - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/informasi-garansi' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/karir.jsx b/src/pages/karir.jsx
new file mode 100644
index 00000000..406397d9
--- /dev/null
+++ b/src/pages/karir.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function KebijakanPrivasi() {
+ return (
+ <BasicLayout>
+ <Seo title='Karir - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/karir' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/kebijakan-privasi.jsx b/src/pages/kebijakan-privasi.jsx
new file mode 100644
index 00000000..8662d56d
--- /dev/null
+++ b/src/pages/kebijakan-privasi.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function KebijakanPrivasi() {
+ return (
+ <BasicLayout>
+ <Seo title='Kebijakan Privasi - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/kebijakan-privasi' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/metode-pembayaran.jsx b/src/pages/metode-pembayaran.jsx
new file mode 100644
index 00000000..8e5d6467
--- /dev/null
+++ b/src/pages/metode-pembayaran.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function MetodePembayaran() {
+ return (
+ <BasicLayout>
+ <Seo title='Metode Pembayaran - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/metode-pembayaran' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/metode-pengiriman.jsx b/src/pages/metode-pengiriman.jsx
new file mode 100644
index 00000000..2b0b65fa
--- /dev/null
+++ b/src/pages/metode-pengiriman.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function MetodePengiriman() {
+ return (
+ <BasicLayout>
+ <Seo title='Metode Pengiriman - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/metode-pengiriman' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/my/daftar-merchant.jsx b/src/pages/my/daftar-merchant.jsx
new file mode 100644
index 00000000..e1fa9bcb
--- /dev/null
+++ b/src/pages/my/daftar-merchant.jsx
@@ -0,0 +1,15 @@
+import Seo from '@/core/components/Seo'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import CreateMerchant from '@/lib/form/components/Merchant'
+
+export default function DaftarMerchant() {
+ return (
+ <>
+ <Seo title='Daftar Merchant - Indoteknik.com' />
+
+ <BasicLayout>
+ <CreateMerchant></CreateMerchant>
+ </BasicLayout>
+ </>
+ )
+}
diff --git a/src/pages/my/invoice/[id].jsx b/src/pages/my/invoices/[id].jsx
index 740819cc..5972b382 100644
--- a/src/pages/my/invoice/[id].jsx
+++ b/src/pages/my/invoices/[id].jsx
@@ -6,7 +6,7 @@ import IsAuth from '@/lib/auth/components/IsAuth'
import InvoiceComponent from '@/lib/invoice/components/Invoice'
import { useRouter } from 'next/router'
-export default function Invoice() {
+export default function MyInvoice() {
const router = useRouter()
return (
diff --git a/src/pages/my/invoices.jsx b/src/pages/my/invoices/index.jsx
index 59059b2e..73c7b9fe 100644
--- a/src/pages/my/invoices.jsx
+++ b/src/pages/my/invoices/index.jsx
@@ -5,7 +5,7 @@ import MobileView from '@/core/components/views/MobileView'
import IsAuth from '@/lib/auth/components/IsAuth'
import InvoicesComponent from '@/lib/invoice/components/Invoices'
-export default function Invoices() {
+export default function MyInvoices() {
return (
<IsAuth>
<MobileView>
diff --git a/src/pages/my/kunjungan-sales.jsx b/src/pages/my/kunjungan-sales.jsx
index 63e95837..052991d9 100644
--- a/src/pages/my/kunjungan-sales.jsx
+++ b/src/pages/my/kunjungan-sales.jsx
@@ -2,7 +2,7 @@ import Seo from '@/core/components/Seo'
import BasicLayout from '@/core/components/layouts/BasicLayout'
import KunjunganSales from '@/lib/form/components/KunjunganSales'
-export default function pembayaran_tempo() {
+export default function kunjungan_sales() {
return (
<>
<Seo title='Kunjungan Sales - Indoteknik.com' />
diff --git a/src/pages/my/kunjungan-service.jsx b/src/pages/my/kunjungan-service.jsx
index 80d1ecbc..37de5a0b 100644
--- a/src/pages/my/kunjungan-service.jsx
+++ b/src/pages/my/kunjungan-service.jsx
@@ -2,8 +2,7 @@ import Seo from '@/core/components/Seo'
import BasicLayout from '@/core/components/layouts/BasicLayout'
import CreateKunjunganService from '@/lib/form/components/KunjunganService'
-export default function pembayaran_tempo() {
-
+export default function kunjungan_service() {
return (
<>
<Seo title='Kunjungan Service - Indoteknik.com' />
diff --git a/src/pages/my/media-relations.jsx b/src/pages/my/media-relations.jsx
new file mode 100644
index 00000000..a965f39a
--- /dev/null
+++ b/src/pages/my/media-relations.jsx
@@ -0,0 +1,15 @@
+import Seo from '@/core/components/Seo'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import CreateMediaRelations from '@/lib/form/components/MediaRelations'
+
+export default function media_relations() {
+ return (
+ <>
+ <Seo title='Media Relations - Indoteknik.com' />
+
+ <BasicLayout>
+ <CreateMediaRelations></CreateMediaRelations>
+ </BasicLayout>
+ </>
+ )
+}
diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx
index e7ae27fd..c8e1e7e9 100644
--- a/src/pages/my/menu.jsx
+++ b/src/pages/my/menu.jsx
@@ -40,6 +40,7 @@ export default function Menu() {
<MenuHeader>Aktivitas Pembelian</MenuHeader>
<div className='divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4'>
+ <LinkItem href='/my/quotations'>Daftar Quotation</LinkItem>
<LinkItem href='/my/transactions'>Daftar Transaksi</LinkItem>
<LinkItem href='/my/invoices'>Invoice & Faktur Pajak</LinkItem>
<LinkItem href='/my/wishlist'>Wishlist</LinkItem>
diff --git a/src/pages/my/pembayaran-tempo.jsx b/src/pages/my/pembayaran-tempo.jsx
index 1e4fc80d..8947bdd9 100644
--- a/src/pages/my/pembayaran-tempo.jsx
+++ b/src/pages/my/pembayaran-tempo.jsx
@@ -2,7 +2,7 @@ import Seo from '@/core/components/Seo'
import BasicLayout from '@/core/components/layouts/BasicLayout'
import PembayaranTempo from '@/lib/form/components/PembayaranTempo'
-export default function pembayaran_tempo() {
+export default function pembayaranTempo() {
return (
<>
<Seo title='Pembayaran Tempo - Indoteknik.com' />
diff --git a/src/pages/my/transaction/[id].jsx b/src/pages/my/quotations/[id].jsx
index c3283783..1fbbf34a 100644
--- a/src/pages/my/transaction/[id].jsx
+++ b/src/pages/my/quotations/[id].jsx
@@ -6,7 +6,7 @@ import IsAuth from '@/lib/auth/components/IsAuth'
import TransactionComponent from '@/lib/transaction/components/Transaction'
import { useRouter } from 'next/router'
-export default function Transaction() {
+export default function MyQuotation() {
const router = useRouter()
return (
diff --git a/src/pages/my/quotations/index.jsx b/src/pages/my/quotations/index.jsx
new file mode 100644
index 00000000..bd91d9d0
--- /dev/null
+++ b/src/pages/my/quotations/index.jsx
@@ -0,0 +1,26 @@
+import AppLayout from '@/core/components/layouts/AppLayout'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import DesktopView from '@/core/components/views/DesktopView'
+import MobileView from '@/core/components/views/MobileView'
+import IsAuth from '@/lib/auth/components/IsAuth'
+import dynamic from 'next/dynamic'
+
+const TransactionsComponent = dynamic(() => import('@/lib/transaction/components/Transactions'))
+
+export default function MyQuotations() {
+ return (
+ <IsAuth>
+ <MobileView>
+ <AppLayout title='Quotation'>
+ <TransactionsComponent context='quotation' />
+ </AppLayout>
+ </MobileView>
+
+ <DesktopView>
+ <BasicLayout>
+ <TransactionsComponent context='quotation' />
+ </BasicLayout>
+ </DesktopView>
+ </IsAuth>
+ )
+}
diff --git a/src/pages/my/surat-dukungan.jsx b/src/pages/my/surat-dukungan.jsx
index 8c469d02..8058f34d 100644
--- a/src/pages/my/surat-dukungan.jsx
+++ b/src/pages/my/surat-dukungan.jsx
@@ -3,8 +3,7 @@ import BasicLayout from '@/core/components/layouts/BasicLayout'
import CreateKunjunganService from '@/lib/form/components/KunjunganService'
import CreateSuratDukungan from '@/lib/form/components/SuratDukungan'
-export default function pembayaran_tempo() {
-
+export default function surat_dukungan() {
return (
<>
<Seo title='Surat Dukungan - Indoteknik.com' />
diff --git a/src/pages/my/transactions/[id].jsx b/src/pages/my/transactions/[id].jsx
new file mode 100644
index 00000000..e36c1ca4
--- /dev/null
+++ b/src/pages/my/transactions/[id].jsx
@@ -0,0 +1,27 @@
+import AppLayout from '@/core/components/layouts/AppLayout'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import DesktopView from '@/core/components/views/DesktopView'
+import MobileView from '@/core/components/views/MobileView'
+import IsAuth from '@/lib/auth/components/IsAuth'
+import TransactionComponent from '@/lib/transaction/components/Transaction'
+import { useRouter } from 'next/router'
+
+export default function MyTransaction() {
+ const router = useRouter()
+
+ return (
+ <IsAuth>
+ <MobileView>
+ <AppLayout title='Transaksi'>
+ <TransactionComponent id={router.query.id} />
+ </AppLayout>
+ </MobileView>
+
+ <DesktopView>
+ <BasicLayout>
+ <TransactionComponent id={router.query.id} />
+ </BasicLayout>
+ </DesktopView>
+ </IsAuth>
+ )
+}
diff --git a/src/pages/my/transactions.jsx b/src/pages/my/transactions/index.jsx
index a8ca78b8..91482a39 100644
--- a/src/pages/my/transactions.jsx
+++ b/src/pages/my/transactions/index.jsx
@@ -7,7 +7,7 @@ import dynamic from 'next/dynamic'
const TransactionsComponent = dynamic(() => import('@/lib/transaction/components/Transactions'))
-export default function Transactions() {
+export default function MyTransactions() {
return (
<IsAuth>
<MobileView>
diff --git a/src/pages/panduan-belanja.jsx b/src/pages/panduan-belanja.jsx
new file mode 100644
index 00000000..27be13da
--- /dev/null
+++ b/src/pages/panduan-belanja.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function PanduanBelanja() {
+ return (
+ <BasicLayout>
+ <Seo title='Panduan Belanja - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/panduan-belanja' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/panduan-pick-up-service.jsx b/src/pages/panduan-pick-up-service.jsx
new file mode 100644
index 00000000..57f78a4c
--- /dev/null
+++ b/src/pages/panduan-pick-up-service.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function PanduanPickUpService() {
+ return (
+ <BasicLayout>
+ <Seo title='Panduan Pick Up Service - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/panduan-pick-up-service' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/panduan-quotation.jsx b/src/pages/panduan-quotation.jsx
new file mode 100644
index 00000000..e4ecdd95
--- /dev/null
+++ b/src/pages/panduan-quotation.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function PanduanQuotation() {
+ return (
+ <BasicLayout>
+ <Seo title='Panduan Quotation - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/panduan-quotation' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/pelanggan-kami.jsx b/src/pages/pelanggan-kami.jsx
new file mode 100644
index 00000000..48b92339
--- /dev/null
+++ b/src/pages/pelanggan-kami.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function PelangganKami() {
+ return (
+ <BasicLayout>
+ <Seo title='Pelanggan Kami - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/pelanggan-kami' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/pengembalian-barang-dana.jsx b/src/pages/pengembalian-barang-dana.jsx
new file mode 100644
index 00000000..57b5c9c5
--- /dev/null
+++ b/src/pages/pengembalian-barang-dana.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function PengembalianBarangDana() {
+ return (
+ <BasicLayout>
+ <Seo title='Pengembalian Barang & Dana - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/pengembalian-barang-dana' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/shop/category/[slug].jsx b/src/pages/shop/category/[slug].jsx
new file mode 100644
index 00000000..dbc17c06
--- /dev/null
+++ b/src/pages/shop/category/[slug].jsx
@@ -0,0 +1,37 @@
+import dynamic from 'next/dynamic'
+import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'
+import { useRouter } from 'next/router'
+import _ from 'lodash'
+import Seo from '@/core/components/Seo'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch'))
+
+export default function CategoryDetail() {
+ const router = useRouter()
+ const { slug = '' } = router.query
+
+ const categoryName = getNameFromSlug(slug)
+ const categoryId = getIdFromSlug(slug)
+ const query = {
+ fq: `manufacture_id_i:${categoryId}`
+ }
+ return (
+ <BasicLayout>
+ <Seo
+ title={`Beli ${categoryName} di Indoteknik`}
+ description={`Jual ${categoryName} Kirim Jakarta Surabaya Semarang Makassar Manado Denpasar Balikpapan Medan Palembang Lampung Bali Bandung Makassar Manado.`}
+ additionalMetaTags={[
+ {
+ property: 'keywords',
+ content: `Jual ${categoryName}, harga ${categoryName}, ${categoryName} murah, toko ${categoryName}, ${categoryName} jakarta, ${categoryName} surabaya`
+ }
+ ]}
+ />
+
+ {!_.isEmpty(router.query) && (
+ <ProductSearch query={query} prefixUrl={`/shop/category/${slug}`} />
+ )}
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx
index 84b848f0..5d706dec 100644
--- a/src/pages/shop/product/[slug].jsx
+++ b/src/pages/shop/product/[slug].jsx
@@ -1,48 +1,75 @@
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'
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
- let product = await productApi({ id: getIdFromSlug(slug) })
+ const cookies = context.req.headers.cookie
+ const cookieObj = cookies ? cookie.parse(cookies) : {}
+ const auth = cookieObj.auth ? JSON.parse(cookieObj.auth) : {}
+ const authToken = auth?.token || ''
+
+ let product = await productApi({ id: getIdFromSlug(slug), headers: { Token: authToken } })
if (product?.length == 1) {
product = product[0]
const regexHtmlTags = /(<([^>]+)>)/gi
const regexHtmlTagsExceptP = /<\/?(?!p\b)[^>]*>/g
- if (product.description.replace(regexHtmlTags, ' ').trim() == '') {
- product.description = ''
- }
- product.description = product.description.replace(regexHtmlTagsExceptP, ' ')
- product.description = product.description.trim()
+ product.description = product.description
+ .replace(regexHtmlTagsExceptP, ' ')
+ .replace(regexHtmlTags, ' ')
+ .trim()
+ } else {
+ product = null
+ }
+
+ return {
+ props: { product }
}
- return { props: { product } }
}
export default function ProductDetail({ product }) {
const router = useRouter()
+
+ if (!product) return <PageNotFound />
+
return (
<BasicLayout>
<Seo
- title={product?.name + ' - Indoteknik.com' || ''}
+ 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,
- image: product.image,
+ 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}`
+ content: `${product?.name}, Harga ${product?.name}, Beli ${product?.name}, Spesifikasi ${product?.name}`
}
]}
/>
- <Product product={product} />
+ {!product && (
+ <div className='container mx-auto flex justify-center pt-10'>
+ <LogoSpinner width={36} height={36} />
+ </div>
+ )}
+ {product && <Product product={product} />}
</BasicLayout>
)
}
diff --git a/src/pages/shop/quotation/finish.jsx b/src/pages/shop/quotation/finish.jsx
index 0e9c5672..3850fef8 100644
--- a/src/pages/shop/quotation/finish.jsx
+++ b/src/pages/shop/quotation/finish.jsx
@@ -30,7 +30,7 @@ export default function FinishQuotation() {
</p>
{id && (
<Link
- href={`/my/transaction/${id}`}
+ href={`/my/quotations/${id}`}
className='btn-yellow !text-gray_r-12 mt-6 w-full md:w-1/3 md:mx-auto'
>
Lihat Penawaran
diff --git a/src/pages/sitemap/blogs.xml.js b/src/pages/sitemap/blogs.xml.js
new file mode 100644
index 00000000..7f41ad0f
--- /dev/null
+++ b/src/pages/sitemap/blogs.xml.js
@@ -0,0 +1,31 @@
+import { createSlug } from '@/core/utils/slug'
+import blogsApi from '@/lib/blog/api/blogsApi'
+import { create } from 'xmlbuilder'
+
+export async function getServerSideProps({ res }) {
+ const baseUrl = process.env.SELF_HOST + '/blog/'
+ const blogs = await blogsApi({ limit: 0, offset: 0 })
+ const sitemap = create('urlset', { encoding: 'utf-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ )
+
+ const date = new Date()
+ blogs.blogs.forEach((blog) => {
+ const url = sitemap.ele('url')
+ url.ele('loc', createSlug(baseUrl, blog.title, blog.id))
+ url.ele('lastmod', date.toISOString().slice(0, 10))
+ url.ele('changefreq', 'weekly')
+ url.ele('priority', '0.6')
+ })
+
+ res.setHeader('Content-Type', 'text/xml')
+ res.write(sitemap.end())
+ res.end()
+
+ return { props: {} }
+}
+
+export default function SitemapProducts() {
+ return null
+}
diff --git a/src/pages/sitemap/brands.xml.js b/src/pages/sitemap/brands.xml.js
new file mode 100644
index 00000000..c85c40e9
--- /dev/null
+++ b/src/pages/sitemap/brands.xml.js
@@ -0,0 +1,31 @@
+import { create } from 'xmlbuilder'
+import { createSlug } from '@/core/utils/slug'
+import odooApi from '@/core/api/odooApi'
+
+export async function getServerSideProps({ res }) {
+ const baseUrl = process.env.SELF_HOST + '/shop/brands/'
+ const brands = await odooApi('GET', `/api/v1/manufacture?limit=0`)
+ const sitemap = create('urlset', { encoding: 'utf-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ )
+
+ const date = new Date()
+ brands.manufactures.forEach((brand) => {
+ const url = sitemap.ele('url')
+ url.ele('loc', createSlug(baseUrl, brand.name, brand.id))
+ url.ele('lastmod', date.toISOString().slice(0, 10))
+ url.ele('changefreq', 'weekly')
+ url.ele('priority', '0.6')
+ })
+
+ res.setHeader('Content-Type', 'text/xml')
+ res.write(sitemap.end())
+ res.end()
+
+ return { props: {} }
+}
+
+export default function SitemapProducts() {
+ return null
+}
diff --git a/src/pages/sitemap/categories.xml.js b/src/pages/sitemap/categories.xml.js
new file mode 100644
index 00000000..1c684576
--- /dev/null
+++ b/src/pages/sitemap/categories.xml.js
@@ -0,0 +1,41 @@
+import { create } from 'xmlbuilder'
+import { createSlug } from '@/core/utils/slug'
+import odooApi from '@/core/api/odooApi'
+
+export async function getServerSideProps({ res }) {
+ const categories = await odooApi('GET', '/api/v1/category/tree')
+ const sitemap = create('urlset', { encoding: 'utf-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ )
+
+ categories.forEach((category) => {
+ addUrlToSitemap(sitemap, category.name, category.id)
+ category.childs.forEach((child1Category) => {
+ addUrlToSitemap(sitemap, child1Category.name, child1Category.id)
+ child1Category.childs.forEach((child2Category) => {
+ addUrlToSitemap(sitemap, child2Category.name, child2Category.id)
+ })
+ })
+ })
+
+ res.setHeader('Content-Type', 'text/xml')
+ res.write(sitemap.end())
+ res.end()
+
+ return { props: {} }
+}
+
+function addUrlToSitemap(sitemap, name, id) {
+ const baseUrl = process.env.SELF_HOST + '/shop/category/'
+ const date = new Date()
+ const url = sitemap.ele('url')
+ url.ele('loc', createSlug(baseUrl, name, id))
+ url.ele('lastmod', date.toISOString().slice(0, 10))
+ url.ele('changefreq', 'weekly')
+ url.ele('priority', '0.6')
+}
+
+export default function SitemapProducts() {
+ return null
+}
diff --git a/src/pages/sitemap/products.xml.js b/src/pages/sitemap/products.xml.js
index e5fc8029..a2067308 100644
--- a/src/pages/sitemap/products.xml.js
+++ b/src/pages/sitemap/products.xml.js
@@ -9,7 +9,10 @@ export async function getServerSideProps({ res }) {
const products = await productSearchApi({ query: _.toQuery(query) })
const pageCount = Math.ceil(products.response.numFound / limit)
const pages = Array.from({ length: pageCount }, (_, i) => i + 1)
- const sitemapIndex = create('sitemapindex', { encoding: 'UTF-8' })
+ const sitemapIndex = create('sitemapindex', { encoding: 'UTF-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ )
const date = new Date()
pages.forEach((page) => {
diff --git a/src/pages/sitemap/products/[id].xml.js b/src/pages/sitemap/products/[id].xml.js
deleted file mode 100644
index 98c2bf40..00000000
--- a/src/pages/sitemap/products/[id].xml.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import productSearchApi from '@/lib/product/api/productSearchApi'
-import { create } from 'xmlbuilder'
-import _ from 'lodash-contrib'
-import { createSlug } from '@/core/utils/slug'
-
-export async function getServerSideProps({ res }) {
- const baseUrl = process.env.SELF_HOST + '/shop/product'
- const limit = 2500
- const query = { limit }
- const products = await productSearchApi({ query: _.toQuery(query) })
- console.log(products)
- // const sitemap = create('urlset', { encoding: 'UTF-8' })
-
- // const date = new Date()
- // pages.forEach((page) => {
- // const url = sitemap.ele('url')
- // url.ele('loc', createSlug(baseUrl, '', ''))
- // url.ele('lastmod', date.toISOString().slice(0, 10))
- // url.ele('changefreq', 'weekly')
- // url.ele('priority', '0.8')
- // })
-
- // res.setHeader('Content-Type', 'text/xml')
- // res.write(sitemap.end())
- // res.end()
-
- return { props: {} }
-}
-
-export default function SitemapProducts() {
- return <></>
-}
diff --git a/src/pages/sitemap/products/[page].js b/src/pages/sitemap/products/[page].js
new file mode 100644
index 00000000..2f9c3198
--- /dev/null
+++ b/src/pages/sitemap/products/[page].js
@@ -0,0 +1,35 @@
+import productSearchApi from '@/lib/product/api/productSearchApi'
+import { create } from 'xmlbuilder'
+import _ from 'lodash-contrib'
+import { createSlug } from '@/core/utils/slug'
+
+export async function getServerSideProps({ query, res }) {
+ const baseUrl = process.env.SELF_HOST + '/shop/product/'
+ const { page } = query
+ const limit = 2500
+ const queries = { limit, page: page.replace('.xml', '') }
+ const products = await productSearchApi({ query: _.toQuery(queries) })
+ const sitemap = create('urlset', { encoding: 'utf-8' }).att(
+ 'xmlns',
+ 'http://www.sitemaps.org/schemas/sitemap/0.9'
+ )
+
+ const date = new Date()
+ products.response.products.forEach((product) => {
+ const url = sitemap.ele('url')
+ url.ele('loc', createSlug(baseUrl, product.name, product.id))
+ url.ele('lastmod', date.toISOString().slice(0, 10))
+ url.ele('changefreq', 'weekly')
+ url.ele('priority', '0.8')
+ })
+
+ res.setHeader('Content-Type', 'text/xml')
+ res.write(sitemap.end())
+ res.end()
+
+ return { props: {} }
+}
+
+export default function SitemapProducts() {
+ return null
+}
diff --git a/src/pages/syarat-ketentuan.jsx b/src/pages/syarat-ketentuan.jsx
new file mode 100644
index 00000000..20a3aa63
--- /dev/null
+++ b/src/pages/syarat-ketentuan.jsx
@@ -0,0 +1,17 @@
+import Seo from '@/core/components/Seo'
+import dynamic from 'next/dynamic'
+
+const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
+const PageContent = dynamic(() => import('@/lib/content/components/PageContent'))
+
+export default function SyaratKetentuan() {
+ return (
+ <BasicLayout>
+ <Seo title='Syarat & Ketentuan - Indoteknik.com' />
+
+ <article className='container mx-auto py-6 px-4 sm:px-0'>
+ <PageContent path='/syarat-ketentuan' />
+ </article>
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/about-us.jsx b/src/pages/tentang-kami.jsx
index c7e546df..d7029a50 100644
--- a/src/pages/about-us.jsx
+++ b/src/pages/tentang-kami.jsx
@@ -2,7 +2,7 @@ import Seo from '@/core/components/Seo'
import BasicLayout from '@/core/components/layouts/BasicLayout'
import IframeContent from '@/lib/iframe/components/IframeContent'
-export default function AboutUs() {
+export default function TentangKami() {
return (
<BasicLayout>
<Seo title='Tentang Indoteknik.com' />