summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.env45
-rw-r--r--src-migrate/modules/page-content/index.tsx61
-rw-r--r--src-migrate/modules/product-promo/components/Item.tsx37
-rw-r--r--src-migrate/modules/promo/components/Hero.tsx103
-rw-r--r--src-migrate/modules/promo/components/PromotinProgram.jsx223
-rw-r--r--src-migrate/modules/promo/components/Voucher.tsx65
-rw-r--r--src-migrate/modules/register/components/FormBisnis.tsx2
-rw-r--r--src-migrate/pages/shop/cart/index.tsx146
-rw-r--r--src/core/components/elements/Footer/BasicFooter.jsx8
-rw-r--r--src/core/components/elements/Navbar/NavbarDesktop.jsx95
-rw-r--r--src/lib/home/components/BannerSection.jsx20
-rw-r--r--src/lib/home/components/CategoryDynamic.jsx15
-rw-r--r--src/lib/home/components/CategoryDynamicMobile.jsx14
-rw-r--r--src/lib/home/components/CategoryHomeId.jsx18
-rw-r--r--src/lib/home/components/CategoryPilihan.jsx265
-rw-r--r--src/lib/home/components/PromotionProgram.jsx118
-rw-r--r--src/lib/home/components/ServiceList.jsx34
-rw-r--r--src/lib/quotation/components/Quotationheader.jsx131
-rw-r--r--src/lib/review/components/CustomerReviews.jsx37
-rw-r--r--src/lib/tracking-order/component/TrackingOrder.jsx272
-rw-r--r--src/pages/my/profile.jsx69
21 files changed, 1043 insertions, 735 deletions
diff --git a/.env b/.env
new file mode 100644
index 00000000..1aca1dbc
--- /dev/null
+++ b/.env
@@ -0,0 +1,45 @@
+SELF_HOST=http://localhost:2100
+# SELF_HOST=http://192.168.23.178:2100
+# ODOO_API_HOST=http://192.168.23.191:8069
+# ODOO_API_HOST=http://192.168.23.251:8069
+# ODOO_API_HOST=http://192.168.23.73:8069
+# ODOO_API_HOST=https://erp.indoteknik.com
+ODOO_API_HOST=http://localhost:8069
+SOLR_HOST=http://34.101.189.218:8983
+# SOLR_HOST=http://192.168.23.5:8983
+# SOLR_HOST=http://localhost:8983
+
+RAJA_ONGKIR_HOST='https://pro.rajaongkir.com'
+RAJA_ONGKIR_KEY='7ac9883688da043b50cc32f0e3070bb6'
+
+MAIL_PORT=465
+MAIL_HOST=smtp.gmail.com
+MAIL_USER=sales@indoteknik.com
+MAIL_PASS=#&Win*%a3C%^FF
+
+MIDTRANS_HOST=https://api.sandbox.midtrans.com
+MIDTRANS_ENV=development
+MIDTRANS_SERVER_KEY=SB-Mid-server-n-V7d2c2ZB0SVED29OyCWVYp
+MIDTRANS_CLIENT_KEY=SB-Mid-client-IsVHHv5mzPqNV7bs
+
+RECAPTCHA_GOOGLE=6LdajH0lAAAAAI6kCVHjR9rHuD22Pf-X7XakSQ_P
+
+NEXTAUTH_URL=http://localhost:2100
+
+PPN=1.11
+
+# GOOGLE_CLIENT_ID="396438712998-308hckshgeekr34phr5jskj1f6qltfvk.apps.googleusercontent.com"
+# GOOGLE_CLIENT_SECRET=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
+GOOGLE_CLIENT_ID="140590317805-5k5v3pjb7gcv4rcefgt8udgmn3hllv0q.apps.googleusercontent.com"
+GOOGLE_CLIENT_SECRET=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
+
+JWT_SECRET=NTNv7j0TuYARvmNMmWXo6fKvM4o6nvaUi9ryX38ZHL1bkrnD1ObOQ8JAUmHCBq7Iy7otZcyAagBLHVKvvYaIpmMuxmARQ97jUVG16Jkpkp1wXOPsrF9zwew6TpczyHkHgX5EuLg2MeBuiTqJACs1J0apruOOJCggOtkjB4c
+
+NEXT_PUBLIC_SELF_HOST=$SELF_HOST
+NEXT_PUBLIC_ODOO_API_HOST=$ODOO_API_HOST
+NEXT_PUBLIC_MIDTRANS_CLIENT_KEY=$MIDTRANS_CLIENT_KEY
+NEXT_PUBLIC_RECAPTCHA_GOOGLE=$RECAPTCHA_GOOGLE
+NEXT_PUBLIC_RAJA_ONGKIR_HOST=$RAJA_ONGKIR_HOST
+NEXT_PUBLIC_RAJA_ONGKIR_KEY=$RAJA_ONGKIR_KEY
+NEXT_PUBLIC_ODOO_HOST=$ODOO_API_HOST
+NEXT_PUBLIC_PPN=$PPN \ No newline at end of file
diff --git a/src-migrate/modules/page-content/index.tsx b/src-migrate/modules/page-content/index.tsx
index 547b1957..af597641 100644
--- a/src-migrate/modules/page-content/index.tsx
+++ b/src-migrate/modules/page-content/index.tsx
@@ -1,44 +1,45 @@
-import { useMemo } from "react"
-import { useQuery } from "react-query"
-import { PageContentProps } from "~/types/pageContent"
-import { getPageContent } from "~/services/pageContent"
+import { useMemo } from 'react';
+import { useQuery } from 'react-query';
+import { PageContentProps } from '~/types/pageContent';
+import { getPageContent } from '~/services/pageContent';
type Props = {
- path: string
-}
+ path: string;
+};
const PageContent = ({ path }: Props) => {
- const { data, isLoading } = useQuery<PageContentProps>(`page-content:${path}`, async () => await getPageContent({ path }))
+ const { data, isLoading } = useQuery<PageContentProps>(
+ `page-content:${path}`,
+ async () => await getPageContent({ path })
+ );
const parsedContent = useMemo<string>(() => {
- if (!data) return ''
+ if (!data) return '';
return data.content.replaceAll(
'src="/web/image',
`src="${process.env.NEXT_PUBLIC_ODOO_API_HOST}/web/image`
- )
- }, [data])
+ );
+ }, [data]);
+ console.log('parsedContent', parsedContent);
+ if (isLoading) return <PageContentSkeleton />;
- if (isLoading) return <PageContentSkeleton />
-
- return (
- <div dangerouslySetInnerHTML={{ __html: parsedContent || '' }}></div>
- )
-}
+ return <div dangerouslySetInnerHTML={{ __html: parsedContent || '' }}></div>;
+};
const PageContentSkeleton = () => (
- <div className="animate-pulse grid gap-y-4">
- <div className="w-full h-10 bg-gray-300 rounded" />
- <div className="h-2" />
- <div className="w-full h-4 bg-gray-300 rounded" />
- <div className="w-full h-4 bg-gray-300 rounded" />
- <div className="w-full h-4 bg-gray-300 rounded" />
- <div className="w-8/12 h-4 bg-gray-300 rounded" />
- <div className="h-2" />
- <div className="w-full h-4 bg-gray-300 rounded" />
- <div className="w-full h-4 bg-gray-300 rounded" />
- <div className="w-full h-4 bg-gray-300 rounded" />
- <div className="w-1/2 h-4 bg-gray-300 rounded" />
+ <div className='animate-pulse grid gap-y-4'>
+ <div className='w-full h-10 bg-gray-300 rounded' />
+ <div className='h-2' />
+ <div className='w-full h-4 bg-gray-300 rounded' />
+ <div className='w-full h-4 bg-gray-300 rounded' />
+ <div className='w-full h-4 bg-gray-300 rounded' />
+ <div className='w-8/12 h-4 bg-gray-300 rounded' />
+ <div className='h-2' />
+ <div className='w-full h-4 bg-gray-300 rounded' />
+ <div className='w-full h-4 bg-gray-300 rounded' />
+ <div className='w-full h-4 bg-gray-300 rounded' />
+ <div className='w-1/2 h-4 bg-gray-300 rounded' />
</div>
-)
+);
-export default PageContent \ No newline at end of file
+export default PageContent;
diff --git a/src-migrate/modules/product-promo/components/Item.tsx b/src-migrate/modules/product-promo/components/Item.tsx
index b396160f..4b345654 100644
--- a/src-migrate/modules/product-promo/components/Item.tsx
+++ b/src-migrate/modules/product-promo/components/Item.tsx
@@ -1,34 +1,35 @@
-import style from '../styles/item.module.css'
+import style from '../styles/item.module.css';
-import { Tooltip } from '@chakra-ui/react'
+import { Tooltip } from '@chakra-ui/react';
-import Image from '~/components/ui/image'
-import { IProductVariantPromo } from '~/types/promotion'
+import Image from '~/components/ui/image';
+import { IProductVariantPromo } from '~/types/promotion';
type Props = {
- variant: IProductVariantPromo,
- isFree?: boolean
-}
+ variant: IProductVariantPromo;
+ isFree?: boolean;
+};
-const ProductPromoItem = ({
- variant,
- isFree = false
-}: Props) => {
+const ProductPromoItem = ({ variant, isFree = false }: Props) => {
return (
<div className={style.item}>
<div className={style.image}>
- <Image src={variant.image || '/images/noimage.jpeg'} alt={variant.display_name} width={120} height={120} quality={100} />
+ <Image
+ src={variant.image || '/images/noimage.jpeg'}
+ alt={variant.display_name}
+ width={120}
+ height={120}
+ quality={85}
+ />
<div className={style.quantity}>
{variant.qty} pcs {isFree ? '(free)' : ''}
</div>
</div>
<Tooltip label={variant.display_name} placement='top' fontSize='sm'>
- <div className={style.name}>
- {variant.name}
- </div>
+ <div className={style.name}>{variant.name}</div>
</Tooltip>
</div>
- )
-}
+ );
+};
-export default ProductPromoItem \ No newline at end of file
+export default ProductPromoItem;
diff --git a/src-migrate/modules/promo/components/Hero.tsx b/src-migrate/modules/promo/components/Hero.tsx
index 97cbe0b7..7d0aad11 100644
--- a/src-migrate/modules/promo/components/Hero.tsx
+++ b/src-migrate/modules/promo/components/Hero.tsx
@@ -3,34 +3,34 @@ import 'swiper/css';
import Image from 'next/image';
import { useEffect, useMemo } from 'react';
import { useQuery } from 'react-query';
-import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react';
+import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react';
import style from '../styles/hero.module.css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
-import { Navigation, Pagination, Autoplay } from 'swiper';
+import { Navigation, Pagination, Autoplay } from 'swiper';
import MobileView from '../../../../src/core/components/views/MobileView';
import DesktopView from '@/core/components/views/DesktopView';
-import {bannerApi} from '../../../../src/api/bannerApi'
+import { bannerApi } from '../../../../src/api/bannerApi';
interface IPromotionProgram {
headlineBanner: string;
descriptionBanner: string;
- image: string ;
+ image: string;
name: string;
}
const swiperBanner: SwiperProps = {
- modules:[Navigation, Pagination, Autoplay],
+ modules: [Navigation, Pagination, Autoplay],
autoplay: {
delay: 6000,
- disableOnInteraction: false
+ disableOnInteraction: false,
},
loop: true,
className: 'h-[400px] w-full',
slidesPerView: 1,
spaceBetween: 10,
- pagination:true,
-}
+ pagination: true,
+};
const swiperBannerMob = {
autoplay: {
delay: 6000,
@@ -43,7 +43,10 @@ const swiperBannerMob = {
};
const Hero = () => {
- const heroBanner = useQuery('allPromo', bannerApi({ type: 'banner-semua-promo' }));
+ const heroBanner = useQuery(
+ 'allPromo',
+ bannerApi({ type: 'banner-semua-promo' })
+ );
const banners: IPromotionProgram[] = useMemo(
() => heroBanner?.data || [],
@@ -54,52 +57,60 @@ const Hero = () => {
...swiperBannerMob,
pagination: { dynamicBullets: false, clickable: true },
};
-
+
return (
<>
<DesktopView>
<div className={style['wrapper']}>
- <Swiper {...swiperBanner}>
- {banners?.map((banner, index) => (
- <SwiperSlide key={index} className='flex flex-row'>
- <div className={style['desc-section']}>
- <div className={style['title']}>{banner?.headlineBanner? banner?.headlineBanner : "Pasti Hemat & Untung Selama Belanja di Indoteknik.com!"}</div>
- <div className='h-4' />
- <div className={style['subtitle']}>{banner?.descriptionBanner? banner?.descriptionBanner : "Cari paket yang kami sediakan dengan penawaran harga & Nikmati kemudahan dalam setiap transaksi dengan fitur lengkap Pembayaran hingga barang sampai!"}</div>
+ <Swiper {...swiperBanner}>
+ {banners?.map((banner, index) => (
+ <SwiperSlide key={index} className='flex flex-row'>
+ <div className={style['desc-section']}>
+ <div className={style['title']}>
+ {banner?.headlineBanner
+ ? banner?.headlineBanner
+ : 'Pasti Hemat & Untung Selama Belanja di Indoteknik.com!'}
</div>
- <div className={style['banner-section']}>
- <Image
- src={banner.image}
- alt={banner.name}
- width={666}
- height={450}
- quality={90}
- className='w-full h-full object-fit object-center rounded-2xl' />
+ <div className='h-4' />
+ <div className={style['subtitle']}>
+ {banner?.descriptionBanner
+ ? banner?.descriptionBanner
+ : 'Cari paket yang kami sediakan dengan penawaran harga & Nikmati kemudahan dalam setiap transaksi dengan fitur lengkap Pembayaran hingga barang sampai!'}
</div>
- </SwiperSlide>
- ))}
- </Swiper>
- </div>
- </DesktopView>
- <MobileView>
- <Swiper {...swiperBannerMobile}>
- {banners?.map((banner, index) => (
- <SwiperSlide key={index}>
- <Image
- width={439}
- height={150}
- quality={100}
- src={banner?.image}
- alt={banner?.name}
- className='w-full h-full object-cover object-center rounded-2xl'
- />
+ </div>
+ <div className={style['banner-section']}>
+ <Image
+ src={banner.image}
+ alt={banner.name}
+ width={666}
+ height={450}
+ quality={85}
+ className='w-full h-full object-fit object-center rounded-2xl'
+ />
+ </div>
</SwiperSlide>
))}
</Swiper>
-
+ </div>
+ </DesktopView>
+ <MobileView>
+ <Swiper {...swiperBannerMobile}>
+ {banners?.map((banner, index) => (
+ <SwiperSlide key={index}>
+ <Image
+ width={439}
+ height={150}
+ quality={85}
+ src={banner?.image}
+ alt={banner?.name}
+ className='w-full h-full object-cover object-center rounded-2xl'
+ />
+ </SwiperSlide>
+ ))}
+ </Swiper>
</MobileView>
</>
- )
-}
+ );
+};
-export default Hero \ No newline at end of file
+export default Hero;
diff --git a/src-migrate/modules/promo/components/PromotinProgram.jsx b/src-migrate/modules/promo/components/PromotinProgram.jsx
index 33839944..43e4eedf 100644
--- a/src-migrate/modules/promo/components/PromotinProgram.jsx
+++ b/src-migrate/modules/promo/components/PromotinProgram.jsx
@@ -1,9 +1,7 @@
import React from 'react';
import Image from 'next/image';
-import { InfoIcon } from "lucide-react";
-import MobileView from '../../../../src/core/components/views/MobileView';
-import DesktopView from '@/core/components/views/DesktopView';
-import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react';
+import { InfoIcon } from 'lucide-react';
+import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import useDevice from '@/core/hooks/useDevice';
@@ -11,9 +9,12 @@ const PromotionProgram = ({ selectedPromo, onSelectPromo }) => {
const { isMobile } = useDevice();
return (
<>
- <div className="text-h-sm md:text-h-lg font-semibold py-4">Serba Serbi Promo</div>
+ <h1 className='text-h-sm md:text-h-lg font-semibold py-4'>
+ {' '}
+ Serba Serbi Promo
+ </h1>
<div className='px-4 sm:px-0'>
- {/* <div className='w-full h-full '>
+ {/* <div className='w-full h-full '>
<div
onClick={() => onSelectPromo('Diskon')}
className={`border p-2 flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Diskon' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`}
@@ -39,93 +40,147 @@ const PromotionProgram = ({ selectedPromo, onSelectPromo }) => {
</div>
</div>
</div> */}
-
- <Swiper slidesPerView={isMobile ? 1.3 : 3} spaceBetween={10}>
- <SwiperSlide>
- <div className='w-full h-full '>
- <div
- onClick={() => onSelectPromo('Bundling')}
- className={`border h-full p-1 flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Bundling' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`}
- >
- <div>
- <Image
- width={24}
- height={24}
- quality={100}
- src='/images/icon_promo/silat.svg'
- alt=''
- className='h-12 w-12 rounded'
- />
- </div>
- <div >
- <div className='flex w-full flex-row items-center justify-start'>
- <h1 className={`mr-1 font-semibold text-base ${selectedPromo === 'Bundling' ? 'text-red-500' : 'text-gray-900'}`}>Paket Silat</h1>
- <InfoIcon className='mt-[1px] text-red-500' size={14} />
- </div>
- <p className={`text-xs md:text-sm ${selectedPromo === 'Bundling' ? 'text-red-500' : 'text-gray-500'}`}>
- Pilihan bundling barang kombinasi Silat.
- </p>
+
+ <Swiper slidesPerView={isMobile ? 1.3 : 3} spaceBetween={10}>
+ <SwiperSlide>
+ <div className='w-full h-full '>
+ <div
+ onClick={() => onSelectPromo('Bundling')}
+ className={`border h-full p-1 flex items-center gap-x-2 rounded-lg cursor-pointer ${
+ selectedPromo === 'Bundling'
+ ? 'bg-red-50 border-red-500 text-red-500'
+ : 'border-gray-200 text-gray-900'
+ }`}
+ >
+ <div>
+ <Image
+ width={24}
+ height={24}
+ quality={85}
+ src='/images/icon_promo/silat.svg'
+ alt=''
+ className='h-12 w-12 rounded'
+ />
+ </div>
+ <div>
+ <div className='flex w-full flex-row items-center justify-start'>
+ <h1
+ className={`mr-1 font-semibold text-base ${
+ selectedPromo === 'Bundling'
+ ? 'text-red-500'
+ : 'text-gray-900'
+ }`}
+ >
+ Paket Silat
+ </h1>
+ <InfoIcon className='mt-[1px] text-red-500' size={14} />
</div>
+ <p
+ className={`text-xs md:text-sm ${
+ selectedPromo === 'Bundling'
+ ? 'text-red-500'
+ : 'text-gray-500'
+ }`}
+ >
+ Pilihan bundling barang kombinasi Silat.
+ </p>
</div>
</div>
- </SwiperSlide>
- <SwiperSlide>
- <div className='w-full h-full '>
- <div
- onClick={() => onSelectPromo('Loading')}
- className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Loading' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`}
- >
- <div>
- <Image
- width={24}
- height={24}
- quality={100}
- src='/images/icon_promo/barong.svg'
- alt=''
- className='h-12 w-12 rounded'
- />
- </div>
- <div>
- <div className='flex w-full flex-row items-center justify-start'>
- <h1 className={`mr-1 font-semibold text-base ${selectedPromo === 'Loading' ? 'text-red-500' : 'text-gray-900'}`}>Paket Barong</h1>
- <InfoIcon className='mt-[1px] text-red-500' size={14} />
- </div>
- <p className={`text-xs md:text-sm ${selectedPromo === 'Loading' ? 'text-red-500' : 'text-gray-500'}`}>
- Beli banyak barang/partai barang borong.
- </p>
+ </div>
+ </SwiperSlide>
+ <SwiperSlide>
+ <div className='w-full h-full '>
+ <div
+ onClick={() => onSelectPromo('Loading')}
+ className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${
+ selectedPromo === 'Loading'
+ ? 'bg-red-50 border-red-500 text-red-500'
+ : 'border-gray-200 text-gray-900'
+ }`}
+ >
+ <div>
+ <Image
+ width={24}
+ height={24}
+ quality={85}
+ src='/images/icon_promo/barong.svg'
+ alt=''
+ className='h-12 w-12 rounded'
+ />
+ </div>
+ <div>
+ <div className='flex w-full flex-row items-center justify-start'>
+ <h1
+ className={`mr-1 font-semibold text-base ${
+ selectedPromo === 'Loading'
+ ? 'text-red-500'
+ : 'text-gray-900'
+ }`}
+ >
+ Paket Barong
+ </h1>
+ <InfoIcon className='mt-[1px] text-red-500' size={14} />
</div>
+ <p
+ className={`text-xs md:text-sm ${
+ selectedPromo === 'Loading'
+ ? 'text-red-500'
+ : 'text-gray-500'
+ }`}
+ >
+ Beli banyak barang/partai barang borong.
+ </p>
</div>
</div>
- </SwiperSlide>
- <SwiperSlide>
- <div className='w-full h-full '>
- <div
- onClick={() => onSelectPromo('Merchandise')}
- className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${selectedPromo === 'Merchandise' ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`}
- >
- <div>
- <Image
- width={24}
- height={24}
- quality={100}
- src='/images/icon_promo/angklung.svg'
- alt=''
- className='h-12 w-12 rounded'
- />
- </div>
- <div >
- <div className='flex w-full flex-row items-center justify-start '>
- <h1 className={`mr-1 font-semibold text-base ${selectedPromo === 'Merchandise' ? 'text-red-500' : 'text-gray-900'}`}>Paket Angklung</h1>
- <InfoIcon className='mt-[1px] text-red-500' size={14} />
- </div>
- <p className={` m1 text-xs md:text-sm ${selectedPromo === 'Merchandise' ? 'text-red-500' : 'text-gray-500'}`}>
- Gratis barang promosi/merchandise menang langsung.
- </p>
+ </div>
+ </SwiperSlide>
+ <SwiperSlide>
+ <div className='w-full h-full '>
+ <div
+ onClick={() => onSelectPromo('Merchandise')}
+ className={`border p-2 h-full flex items-center gap-x-2 rounded-lg cursor-pointer ${
+ selectedPromo === 'Merchandise'
+ ? 'bg-red-50 border-red-500 text-red-500'
+ : 'border-gray-200 text-gray-900'
+ }`}
+ >
+ <div>
+ <Image
+ width={24}
+ height={24}
+ quality={85}
+ src='/images/icon_promo/angklung.svg'
+ alt=''
+ className='h-12 w-12 rounded'
+ />
+ </div>
+ <div>
+ <div className='flex w-full flex-row items-center justify-start '>
+ <h1
+ className={`mr-1 font-semibold text-base ${
+ selectedPromo === 'Merchandise'
+ ? 'text-red-500'
+ : 'text-gray-900'
+ }`}
+ >
+ Paket Angklung
+ </h1>
+ <InfoIcon className='mt-[1px] text-red-500' size={14} />
</div>
+ <p
+ className={` m1 text-xs md:text-sm ${
+ selectedPromo === 'Merchandise'
+ ? 'text-red-500'
+ : 'text-gray-500'
+ }`}
+ >
+ Gratis barang promosi/merchandise menang langsung.
+ </p>
</div>
</div>
- </SwiperSlide>
- </Swiper>
+ </div>
+ </SwiperSlide>
+ </Swiper>
</div>
</>
);
diff --git a/src-migrate/modules/promo/components/Voucher.tsx b/src-migrate/modules/promo/components/Voucher.tsx
index 510fe746..034d13e9 100644
--- a/src-migrate/modules/promo/components/Voucher.tsx
+++ b/src-migrate/modules/promo/components/Voucher.tsx
@@ -55,15 +55,18 @@ const VoucherComponent = () => {
slidesPerView: isMobile ? 1.2 : 3.2,
spaceBetween: 2,
};
-
- const dataVouchers = useMemo(() => voucherQuery?.data || [], [voucherQuery?.data]);
- const vouchers = auth?.id? listVouchers : dataVouchers;
+ const dataVouchers = useMemo(
+ () => voucherQuery?.data || [],
+ [voucherQuery?.data]
+ );
+ const vouchers = auth?.id ? listVouchers : dataVouchers;
const copyText = (text: string) => {
if (navigator.clipboard && navigator.clipboard.writeText) {
- navigator.clipboard.writeText(text)
+ navigator.clipboard
+ .writeText(text)
.then(() => {
toast({
title: 'Salin ke papan klip',
@@ -72,7 +75,7 @@ const VoucherComponent = () => {
duration: 3000,
isClosable: true,
position: 'top',
- })
+ });
})
.catch(() => {
fallbackCopyTextToClipboard(text);
@@ -80,10 +83,10 @@ const VoucherComponent = () => {
} else {
fallbackCopyTextToClipboard(text);
}
- }
+ };
const fallbackCopyTextToClipboard = (text: string) => {
- const textArea = document.createElement("textarea");
+ const textArea = document.createElement('textarea');
textArea.value = text;
// Tambahkan style untuk menyembunyikan textArea secara visual
textArea.style.position = 'fixed';
@@ -108,23 +111,26 @@ const VoucherComponent = () => {
duration: 3000,
isClosable: true,
position: 'top',
- })
+ });
} catch (err) {
console.error('Fallback: Oops, unable to copy', err);
}
document.body.removeChild(textArea);
- }
+ };
return (
<>
- <div className={style['title']}>Pakai Voucher Belanja</div>
+ <h1 className={style['title']}>Pakai Voucher Belanja</h1>
<div className='h-6' />
{voucherQuery?.isLoading && (
<div className='grid grid-cols-3 gap-x-4 animate-pulse'>
{Array.from({ length: 3 }).map((_, index) => (
- <div key={index} className='w-full h-[160px] bg-gray-200 rounded-xl' />
+ <div
+ key={index}
+ className='w-full h-[160px] bg-gray-200 rounded-xl'
+ />
))}
</div>
)}
@@ -134,17 +140,36 @@ const VoucherComponent = () => {
{vouchers?.map((voucher) => (
<SwiperSlide key={voucher.id} className='pb-2'>
<div className={style['voucher-card']}>
- <Image src={voucher?.image} alt={voucher?.name} width={128} height={128} className={style['voucher-image']} />
+ <Image
+ src={voucher?.image}
+ alt={voucher?.name}
+ width={128}
+ height={128}
+ className={style['voucher-image']}
+ />
<div className={style['voucher-content']}>
- <div className={style['voucher-title']}>{voucher?.name}</div>
- <div className={style['voucher-desc']}>{voucher?.description}</div>
+ <div className={style['voucher-title']}>
+ {voucher?.name}
+ </div>
+ <div className={style['voucher-desc']}>
+ {voucher?.description}
+ </div>
<div className={style['voucher-bottom']}>
<div>
- <div className={style['voucher-code-desc']}>Kode Promo</div>
- <div className={style['voucher-code']}>{voucher?.code}</div>
+ <div className={style['voucher-code-desc']}>
+ Kode Promo
+ </div>
+ <div className={style['voucher-code']}>
+ {voucher?.code}
+ </div>
</div>
- <button className={style['voucher-copy']} onClick={() => copyText(voucher?.code)}>Salin</button>
+ <button
+ className={style['voucher-copy']}
+ onClick={() => copyText(voucher?.code)}
+ >
+ Salin
+ </button>
</div>
</div>
</div>
@@ -154,7 +179,7 @@ const VoucherComponent = () => {
</div>
)}
</>
- )
-}
+ );
+};
-export default VoucherComponent
+export default VoucherComponent;
diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx
index 5ee19e58..e4cf3442 100644
--- a/src-migrate/modules/register/components/FormBisnis.tsx
+++ b/src-migrate/modules/register/components/FormBisnis.tsx
@@ -325,7 +325,7 @@ const form: React.FC<FormProps> = ({
className='w-full h-full '
width={800}
height={800}
- quality={100}
+ quality={85}
/>
</div>
</BottomPopup>
diff --git a/src-migrate/pages/shop/cart/index.tsx b/src-migrate/pages/shop/cart/index.tsx
index 4768f62d..c5386c91 100644
--- a/src-migrate/pages/shop/cart/index.tsx
+++ b/src-migrate/pages/shop/cart/index.tsx
@@ -14,10 +14,10 @@ import clsxm from '~/libs/clsxm';
import useDevice from '@/core/hooks/useDevice';
import CartSummaryMobile from '~/modules/cart/components/CartSummaryMobile';
import Image from '~/components/ui/image';
-import { CartItem } from '~/types/cart'
-import { deleteUserCart ,upsertUserCart } from '~/services/cart'
+import { CartItem } from '~/types/cart';
+import { deleteUserCart, upsertUserCart } from '~/services/cart';
import { Trash2Icon } from 'lucide-react';
-import { useProductCartContext } from '@/contexts/ProductCartContext'
+import { useProductCartContext } from '@/contexts/ProductCartContext';
const CartPage = () => {
const router = useRouter();
@@ -26,11 +26,11 @@ const CartPage = () => {
const [isSelectedAll, setIsSelectedAll] = useState(false);
const [isButtonChek, setIsButtonChek] = useState(false);
const [buttonSelectNow, setButtonSelectNow] = useState(true);
- const [isLoad, setIsLoad] = useState<boolean>(false)
- const [isLoadDelete, setIsLoadDelete] = useState<boolean>(false)
+ const [isLoad, setIsLoad] = useState<boolean>(false);
+ const [isLoadDelete, setIsLoadDelete] = useState<boolean>(false);
const { loadCart, cart, summary, updateCartItem } = useCartStore();
const useDivvice = useDevice();
- const { setRefreshCart } = useProductCartContext()
+ const { setRefreshCart } = useProductCartContext();
const [isTop, setIsTop] = useState(true);
const [hasChanged, setHasChanged] = useState(false);
const prevCartRef = useRef<CartItem[] | null>(null);
@@ -64,18 +64,19 @@ const CartPage = () => {
const hasSelectedChanged = () => {
if (prevCartRef.current && cart) {
const prevCart = prevCartRef.current;
- return cart.products.some((item, index) =>
- prevCart[index] && prevCart[index].selected !== item.selected
+ return cart.products.some(
+ (item, index) =>
+ prevCart[index] && prevCart[index].selected !== item.selected
);
}
return false;
};
if (hasSelectedChanged()) {
- setHasChanged(true)
+ setHasChanged(true);
// Perform necessary actions here if selection has changed
- }else{
- setHasChanged(false)
+ } else {
+ setHasChanged(false);
}
prevCartRef.current = cart ? [...cart.products] : null;
@@ -83,35 +84,38 @@ const CartPage = () => {
const hasSelectedPromo = useMemo(() => {
if (!cart) return false;
- return cart.products.some(item => item.cart_type === 'promotion' && item.selected);
+ return cart.products.some(
+ (item) => item.cart_type === 'promotion' && item.selected
+ );
}, [cart]);
const hasSelected = useMemo(() => {
if (!cart) return false;
- return cart.products.some(item => item.selected);
+ return cart.products.some((item) => item.selected);
}, [cart]);
const hasSelectNoPrice = useMemo(() => {
if (!cart) return false;
- return cart.products.some(item => item.selected && item.price.price_discount === 0);
+ return cart.products.some(
+ (item) => item.selected && item.price.price_discount === 0
+ );
}, [cart]);
const hasSelectedAll = useMemo(() => {
if (!cart || !Array.isArray(cart.products)) return false;
- return cart.products.every(item => item.selected);
+ return cart.products.every((item) => item.selected);
}, [cart]);
-
useEffect(() => {
const updateCartItems = async () => {
if (typeof auth === 'object' && cart) {
- const upsertPromises = cart.products.map(item =>
+ const upsertPromises = cart.products.map((item) =>
upsertUserCart({
userId: auth.id,
type: item.cart_type,
id: item.id,
qty: item.quantity,
- selected: item.selected
+ selected: item.selected,
})
);
try {
@@ -128,7 +132,7 @@ const CartPage = () => {
const handleCheckout = () => {
router.push('/shop/checkout');
- }
+ };
const handleQuotation = () => {
if (hasSelectedPromo || !hasSelected) {
@@ -136,54 +140,53 @@ const CartPage = () => {
} else {
router.push('/shop/quotation');
}
- }
+ };
const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
-
-
if (cart) {
const updatedCart = {
...cart,
- products: cart.products.map(item => ({
+ products: cart.products.map((item) => ({
...item,
- selected: !hasSelectedAll
- }))
+ selected: !hasSelectedAll,
+ })),
};
-
- updateCartItem(updatedCart);
- if(hasSelectedAll){
+
+ updateCartItem(updatedCart);
+ if (hasSelectedAll) {
setIsSelectedAll(false);
- }else{
+ } else {
setIsSelectedAll(true);
}
}
};
-
const handleDelete = async () => {
if (typeof auth !== 'object' || !cart) return;
- setIsLoadDelete(true)
+ setIsLoadDelete(true);
for (const item of cart.products) {
- if(item.selected === true){
- await deleteUserCart(auth.id, [item.cart_id])
- await loadCart(auth.id)
+ if (item.selected === true) {
+ await deleteUserCart(auth.id, [item.cart_id]);
+ await loadCart(auth.id);
}
}
- setIsLoadDelete(false)
- setRefreshCart(true)
- }
+ setIsLoadDelete(false);
+ setRefreshCart(true);
+ };
return (
<>
- <div className={`${isTop ? 'border-b-[0px]' : 'border-b-[1px]'} sticky md:top-[157px] flex-col bg-white py-4 border-gray-300 z-50 sm:w-full md:w-3/4`}>
- <div className={`${style['title']}`}>Keranjang Belanja</div>
+ <div
+ className={`${
+ isTop ? 'border-b-[0px]' : 'border-b-[1px]'
+ } sticky md:top-[157px] flex-col bg-white py-4 border-gray-300 z-50 sm:w-full md:w-3/4`}
+ >
+ <h1 className={`${style['title']}`}>Keranjang Belanja</h1>
<div className='h-2' />
<div className={`flex items-center object-center justify-between `}>
<div className='flex items-center object-center'>
- {isLoad && (
- <Spinner className='my-auto' size='sm' />
- )}
+ {isLoad && <Spinner className='my-auto' size='sm' />}
{!isLoad && (
<Checkbox
borderColor='gray.600'
@@ -193,34 +196,31 @@ const CartPage = () => {
onChange={handleChange}
/>
)}
- <p className='p-2 text-caption-2'>
- {hasSelectedAll ? "Uncheck all" : "Select all"}
- </p>
+ <p className='p-2 text-caption-2'>
+ {hasSelectedAll ? 'Uncheck all' : 'Select all'}
+ </p>
+ </div>
+ <div className='delate all flex items-center object-center'>
+ <Tooltip
+ label={clsxm({
+ 'Tidak ada item yang dipilih': !hasSelected,
+ })}
+ >
+ <Button
+ bg='#fadede'
+ variant='outline'
+ colorScheme='red'
+ w='full'
+ isDisabled={!hasSelected}
+ onClick={handleDelete}
+ >
+ {isLoadDelete && <Spinner size='xs' />}
+ {!isLoadDelete && <Trash2Icon size={16} />}
+ <p className='text-sm ml-2'>Hapus Barang</p>
+ </Button>
+ </Tooltip>
</div>
- <div className='delate all flex items-center object-center'>
- <Tooltip
- label={clsxm({
- 'Tidak ada item yang dipilih': !hasSelected,
- })}
- >
- <Button
- bg='#fadede'
- variant='outline'
- colorScheme='red'
- w='full'
- isDisabled={!hasSelected}
- onClick={handleDelete}
- >
- {isLoadDelete && <Spinner size='xs' />}
- {!isLoadDelete && <Trash2Icon size={16} />}
- <p className='text-sm ml-2'>
- Hapus Barang
- </p>
- </Button>
- </Tooltip>
- </div>
</div>
-
</div>
<div className={style['content']}>
@@ -274,7 +274,13 @@ const CartPage = () => {
<CartSummary {...summary} isLoaded={!!cart} />
)}
- <div className={isStepApproval ? style['summary-buttons-step-approval'] : style['summary-buttons']}>
+ <div
+ className={
+ isStepApproval
+ ? style['summary-buttons-step-approval']
+ : style['summary-buttons']
+ }
+ >
<Tooltip
label={
hasSelectedPromo &&
@@ -315,4 +321,4 @@ const CartPage = () => {
);
};
-export default CartPage; \ No newline at end of file
+export default CartPage;
diff --git a/src/core/components/elements/Footer/BasicFooter.jsx b/src/core/components/elements/Footer/BasicFooter.jsx
index 8f024d86..4688b15b 100644
--- a/src/core/components/elements/Footer/BasicFooter.jsx
+++ b/src/core/components/elements/Footer/BasicFooter.jsx
@@ -175,7 +175,7 @@ const CustomerGuide = () => (
<div>
<div className={headerClassName}>Bantuan & Panduan</div>
<ul className='flex flex-col gap-y-3'>
- <li >
+ <li>
<InternalItemLink href='/metode-pembayaran'>
Metode Pembayaran
</InternalItemLink>
@@ -395,7 +395,7 @@ const Payments = () => (
alt='Metode Pembayaran - Indoteknik'
width={512}
height={512}
- quality={100}
+ quality={85}
className='w-full'
/>
</div>
@@ -409,7 +409,7 @@ const Shippings = () => (
alt='Jasa Pengiriman - Indoteknik'
width={512}
height={512}
- quality={100}
+ quality={85}
className='w-full'
/>
</div>
@@ -423,7 +423,7 @@ const Secures = () => (
alt='Keamanan Belanja - Indoteknik'
width={512}
height={512}
- quality={100}
+ quality={85}
className='w-full'
/>
</div>
diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx
index 2a51c41f..d480aa8d 100644
--- a/src/core/components/elements/Navbar/NavbarDesktop.jsx
+++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx
@@ -5,7 +5,7 @@ import { createSlug } from '@/core/utils/slug';
import whatsappUrl from '@/core/utils/whatsappUrl';
import IndoteknikLogo from '@/images/logo.png';
import Cardheader from '@/lib/cart/components/Cartheader';
-import Quotationheader from "../../../../../src/lib/quotation/components/Quotationheader.jsx"
+import Quotationheader from '../../../../../src/lib/quotation/components/Quotationheader.jsx';
import Category from '@/lib/category/components/Category';
import { useProductCartContext } from '@/contexts/ProductCartContext';
import {
@@ -30,7 +30,7 @@ import {
MenuList,
useDisclosure,
} from '@chakra-ui/react';
-import style from "./style/NavbarDesktop.module.css";
+import style from './style/NavbarDesktop.module.css';
import useTransactions from '@/lib/transaction/hooks/useTransactions';
import { useCartStore } from '~/modules/cart/stores/useCartStore';
@@ -43,7 +43,7 @@ const NavbarDesktop = () => {
const [cartCount, setCartCount] = useState(0);
const [quotationCount, setQuotationCount] = useState(0);
- const [pendingTransactions, setPendingTransactions] = useState([])
+ const [pendingTransactions, setPendingTransactions] = useState([]);
const [templateWA, setTemplateWA] = useState(null);
const [payloadWA, setPayloadWa] = useState(null);
const [urlPath, setUrlPath] = useState(null);
@@ -52,14 +52,17 @@ const NavbarDesktop = () => {
const { product } = useProductContext();
const { isOpen, onOpen, onClose } = useDisclosure();
-
+
const query = {
context: 'quotation',
- site:
- (auth?.webRole === null && auth?.site ? auth.site : null),
+ site: auth?.webRole === null && auth?.site ? auth.site : null,
};
-
- const { transactions } = useTransactions({ query });
+ let transactions = null;
+
+ if (auth) {
+ transactions = useTransactions({ query });
+ }
+
const data = transactions?.data?.saleOrders.filter(
(transaction) => transaction.status === 'draft'
);
@@ -106,9 +109,8 @@ const NavbarDesktop = () => {
useEffect(() => {
setPendingTransactions(data);
- }, [transactions.data]);
-
-
+ }, [transactions?.data]);
+
useEffect(() => {
if (router.pathname === '/shop/product/[slug]') {
setPayloadWa({
@@ -117,11 +119,11 @@ const NavbarDesktop = () => {
url: createSlug('/shop/product/', product?.name, product?.id, true),
});
setTemplateWA('product');
-
+
setUrlPath(router.asPath);
}
}, [product, router]);
-
+
useEffect(() => {
const handleCartChange = () => {
const cart = async () => {
@@ -130,14 +132,14 @@ const NavbarDesktop = () => {
};
cart();
};
- handleCartChange();
-
+ handleCartChange();
+
window.addEventListener('localStorageChange', handleCartChange);
-
+
return () => {
window.removeEventListener('localStorageChange', handleCartChange);
};
- }, [transactions.data, cart]);
+ }, [transactions?.data, cart]);
useEffect(() => {
const handleQuotationChange = () => {
@@ -154,7 +156,7 @@ const NavbarDesktop = () => {
window.removeEventListener('localStorageChange', handleQuotationChange);
};
}, [pendingTransactions]);
-
+
return (
<DesktopView>
<TopBanner onLoad={handleTopBannerLoad} />
@@ -174,7 +176,7 @@ const NavbarDesktop = () => {
>
<div className='flex gap-x-1'>
<div>Fitur Layanan </div>
- <ChevronDownIcon className='w-5'/>
+ <ChevronDownIcon className='w-5' />
</div>
</MenuButton>
<MenuList
@@ -217,7 +219,10 @@ const NavbarDesktop = () => {
<Search />
</div>
<div className='flex gap-x-4 items-center'>
- <Quotationheader quotationCount={quotationCount} data={pendingTransactions} />
+ <Quotationheader
+ quotationCount={quotationCount}
+ data={pendingTransactions}
+ />
<Cardheader cartCount={cartCount} />
@@ -271,29 +276,30 @@ const NavbarDesktop = () => {
</div>
</div>
<div className='w-6/12 flex px-1 divide-x divide-gray_r-6'>
-
- <Link
- href="/shop/promo"
+ <Link
+ href='/shop/promo'
className={`${
router.asPath === '/shop/promo' && 'bg-gray_r-3'
} flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition group relative`} // Added relative position
- target="_blank"
- rel="noreferrer"
+ target='_blank'
+ rel='noreferrer'
>
- {showPopup && (
- <div className='w-full h-full relative justify-end items-start'>
+ {showPopup && (
+ <div className='w-full h-full relative justify-end items-start'>
<Image
- src='/images/penawaran-terbatas.jpg'
- alt='penawaran terbatas'
- width={1440}
- height={160}
- quality={100}
- // className={`fixed ${isTop ? 'md:top-[145px] lg:top-[160px] ' : 'lg:top-[85px] top-[80px]'} rounded-3xl md:left-1/4 lg:left-1/4 xl:left-1/4 left-2/3 w-40 h-12 p-2 z-50 transition-all duration-300 animate-pulse`}
- className={`inline-block relative -top-8 transition-all duration-300 z-20 animate-pulse`}
- />
+ src='/images/penawaran-terbatas.jpg'
+ alt='penawaran terbatas'
+ width={1440}
+ height={160}
+ quality={85}
+ // className={`fixed ${isTop ? 'md:top-[145px] lg:top-[160px] ' : 'lg:top-[85px] top-[80px]'} rounded-3xl md:left-1/4 lg:left-1/4 xl:left-1/4 left-2/3 w-40 h-12 p-2 z-50 transition-all duration-300 animate-pulse`}
+ className={`inline-block relative -top-8 transition-all duration-300 z-20 animate-pulse`}
+ />
</div>
- )}
- <span className="absolute inset-0 flex justify-center items-center group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200 z-10">Semua Promo</span>
+ )}
+ <span className='absolute inset-0 flex justify-center items-center group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200 z-10'>
+ Semua Promo
+ </span>
</Link>
{/* {showPopup && router.pathname === '/' && (
<div className={`fixed ${isTop ? 'top-[170px]' : 'top-[90px]'} rounded-3xl left-[700px] w-fit object-center bg-green-50 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20 text-center p-2 z-50 transition-all duration-300`}>
@@ -302,17 +308,18 @@ const NavbarDesktop = () => {
</p>
</div>
)} */}
-
<Link
href='/shop/brands'
- className={`${
+ className={`${
router.asPath === '/shop/brands' && 'bg-gray_r-3'
} p-4 flex-1 flex justify-center items-center !text-gray_r-12/80 hover:bg-gray_r-3 idt-transition group`}
target='_blank'
rel='noreferrer'
>
- <span className="group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200">Semua Brand</span>
+ <span className='group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200'>
+ Semua Brand
+ </span>
</Link>
<Link
href='/shop/search?orderBy=stock'
@@ -323,7 +330,9 @@ const NavbarDesktop = () => {
target='_blank'
rel='noreferrer'
>
- <span className="group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200">Ready Stock</span>
+ <span className='group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200'>
+ Ready Stock
+ </span>
</Link>
<Link
href='https://blog.indoteknik.com/'
@@ -331,7 +340,9 @@ const NavbarDesktop = () => {
target='_blank'
rel='noreferrer noopener'
>
- <span className="group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200">Blog Indoteknik</span>
+ <span className='group-hover:scale-105 group-hover:text-red-500 transition-transform duration-200'>
+ Blog Indoteknik
+ </span>
</Link>
{/* <Link
href='/video'
diff --git a/src/lib/home/components/BannerSection.jsx b/src/lib/home/components/BannerSection.jsx
index 2010503d..f83c36fc 100644
--- a/src/lib/home/components/BannerSection.jsx
+++ b/src/lib/home/components/BannerSection.jsx
@@ -1,12 +1,12 @@
-import Link from '@/core/components/elements/Link/Link'
-import Image from 'next/image'
+import Link from '@/core/components/elements/Link/Link';
+import Image from 'next/image';
-const { useQuery } = require('react-query')
-const { default: bannerSectionApi } = require('../api/bannerSectionApi')
+const { useQuery } = require('react-query');
+const { default: bannerSectionApi } = require('../api/bannerSectionApi');
const BannerSection = () => {
- const fetchBannerSection = async () => await bannerSectionApi()
- const bannerSection = useQuery('bannerSection', fetchBannerSection)
+ const fetchBannerSection = async () => await bannerSectionApi();
+ const bannerSection = useQuery('bannerSection', fetchBannerSection);
return (
bannerSection.data &&
@@ -17,7 +17,7 @@ const BannerSection = () => {
<Image
width={1024}
height={512}
- quality={100}
+ quality={85}
src={banner.image}
alt={banner.name}
className='h-auto w-full rounded'
@@ -26,7 +26,7 @@ const BannerSection = () => {
))}
</div>
)
- )
-}
+ );
+};
-export default BannerSection
+export default BannerSection;
diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx
index 79092c9d..49a9a93f 100644
--- a/src/lib/home/components/CategoryDynamic.jsx
+++ b/src/lib/home/components/CategoryDynamic.jsx
@@ -3,13 +3,12 @@ import { fetchCategoryManagementSolr } from '../api/categoryManagementApi';
import NextImage from 'next/image';
import Link from 'next/link';
import { createSlug } from '@/core/utils/slug';
-import odooApi from '@/core/api/odooApi';
import { Skeleton } from '@chakra-ui/react';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
-import { Navigation, Pagination, Autoplay } from 'swiper';
+import { Pagination } from 'swiper';
const CategoryDynamic = () => {
const [categoryManagement, setCategoryManagement] = useState([]);
@@ -73,9 +72,9 @@ const CategoryDynamic = () => {
<Skeleton key={category.id} isLoaded={!isLoading}>
<div key={category.id}>
<div className='bagian-judul flex flex-row justify-start items-center gap-3 mb-4 mt-4'>
- <div className='font-semibold sm:text-h-lg mr-2'>
+ <h1 className='font-semibold text-[14px] sm:text-h-lg mr-2'>
{category.name}
- </div>
+ </h1>
{/* <Skeleton isLoaded={countLevel1 != 0}>
<p className={`text-gray_r-10 text-sm`}>{countLevel1} Produk tersedia</p>
</Skeleton> */}
@@ -113,9 +112,9 @@ const CategoryDynamic = () => {
className='object-fit p-4'
/>
<div className='bagian-judul flex flex-col justify-center items-start gap-2 ml-2'>
- <div className='font-semibold text-lg mr-2'>
+ <h2 className='font-semibold text-lg mr-2'>
{subCategory?.name}
- </div>
+ </h2>
{/* <Skeleton isLoaded={countLevel2 != 0}>
<p className={`text-gray_r-10 text-sm`}>
{countLevel2} Produk tersedia
@@ -157,9 +156,9 @@ const CategoryDynamic = () => {
height={40}
/>
<div className='bagian-judul flex flex-col justify-center items-center gap-2 break-words line-clamp-2 group-hover:text-red-500'>
- <div className='font-semibold line-clamp-2 group-hover:text-red-500 text-sm mr-2'>
+ <h3 className='font-semibold line-clamp-2 group-hover:text-red-500 text-sm mr-2'>
{childCategory.name}
- </div>
+ </h3>
</div>
</Link>
</div>
diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx
index af151df2..4a8f13cf 100644
--- a/src/lib/home/components/CategoryDynamicMobile.jsx
+++ b/src/lib/home/components/CategoryDynamicMobile.jsx
@@ -59,9 +59,9 @@ const CategoryDynamicMobile = () => {
categoryManagement?.map((category) => (
<div key={category.id}>
<div className='bagian-judul flex flex-row justify-between items-center gap-3 mb-4 mt-4'>
- <div className='font-semibold sm:text-h-sm mr-2'>
- {category?.name}
- </div>
+ <h1 className='font-semibold text-[14px] sm:text-h-lg mr-2'>
+ {category.name}
+ </h1>
<Link
href={createSlug(
'/shop/category/',
@@ -98,9 +98,9 @@ const CategoryDynamicMobile = () => {
className=''
/>
<div className='bagian-judul flex flex-col justify-center items-start gap-1 ml-2'>
- <div className='font-semibold text-[10px] line-clamp-1'>
+ <h2 className='font-semibold text-[10px] line-clamp-1'>
{index?.name}
- </div>
+ </h2>
</div>
</div>
</div>
@@ -131,9 +131,9 @@ const CategoryDynamicMobile = () => {
className='p-2'
/>
<div className='bagian-judul flex flex-col justify-center items-start gap-1 break-words line-clamp-2 group-hover:text-red-500'>
- <div className='font-semibold line-clamp-2 group-hover:text-red-500 text-[10px]'>
+ <h3 className='font-semibold line-clamp-2 group-hover:text-red-500 text-[10px]'>
{x?.name}
- </div>
+ </h3>
</div>
</Link>
</div>
diff --git a/src/lib/home/components/CategoryHomeId.jsx b/src/lib/home/components/CategoryHomeId.jsx
index 71428e27..9f436dac 100644
--- a/src/lib/home/components/CategoryHomeId.jsx
+++ b/src/lib/home/components/CategoryHomeId.jsx
@@ -1,13 +1,15 @@
-import { LazyLoadComponent } from 'react-lazy-load-image-component'
-import useCategoryHomeId from '../hooks/useCategoryHomeId'
-import CategoryHome from './CategoryHome'
+import { LazyLoadComponent } from 'react-lazy-load-image-component';
+import useCategoryHomeId from '../hooks/useCategoryHomeId';
+import CategoryHome from './CategoryHome';
const CategoryHomeId = () => {
- const { categoryHomeIds } = useCategoryHomeId()
+ const { categoryHomeIds } = useCategoryHomeId();
return (
<div>
- <div className='font-semibold sm:text-h-lg mb-6 px-4 sm:px-0'>Kategori Pilihan</div>
+ <h1 className='font-semibold text-[14px] sm:text-h-lg mb-6 px-4 sm:px-0'>
+ Kategori Pilihan
+ </h1>
<div className='flex flex-col gap-y-10'>
{categoryHomeIds.data?.map((id) => (
<LazyLoadComponent key={id}>
@@ -16,7 +18,7 @@ const CategoryHomeId = () => {
))}
</div>
</div>
- )
-}
+ );
+};
-export default CategoryHomeId
+export default CategoryHomeId;
diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx
index 6dbf771e..2e5ca721 100644
--- a/src/lib/home/components/CategoryPilihan.jsx
+++ b/src/lib/home/components/CategoryPilihan.jsx
@@ -1,123 +1,168 @@
-import Image from 'next/image'
-import useCategoryHome from '../hooks/useCategoryHome'
-import Link from '@/core/components/elements/Link/Link'
-import { createSlug } from '@/core/utils/slug'
+import Image from 'next/image';
+import useCategoryHome from '../hooks/useCategoryHome';
+import Link from '@/core/components/elements/Link/Link';
+import { createSlug } from '@/core/utils/slug';
import { useEffect, useState } from 'react';
import { bannerApi } from '../../../api/bannerApi';
-const { useQuery } = require('react-query')
+const { useQuery } = require('react-query');
import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton';
import useCategoryPilihan from '../hooks/useCategoryPilihan';
-import useDevice from '@/core/hooks/useDevice'
+import useDevice from '@/core/hooks/useDevice';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
const CategoryPilihan = ({ id, categories }) => {
- const { isDesktop, isMobile } = useDevice()
- const { categoryPilihan } = useCategoryPilihan();
- const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' }));
- return (
- categoryPilihan.length > 0 && (
- <section>
- {isDesktop && (
- <div>
- <div className='flex flex-row items-center mb-4'>
- <div className='font-semibold sm:text-h-lg mr-2'>LOB Kategori Pilihan</div>
- <p className='text-gray_r-10 text-sm'>200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!</p>
- </div>
- {heroBanner.data &&
- heroBanner.data?.length > 0 && (
- <div className='flex w-full h-full justify-center mb-4 bg-cover bg-center'>
- <Link key={heroBanner.data[0].id} href={heroBanner.data[0].url}>
- <Image
- width={1260}
- height={170}
- quality={100}
- src={heroBanner.data[0].image}
- alt={heroBanner.data[0].name}
- className='h-full object-cover w-full'
- />
- </Link>
- </div>
- )}
- <div className="group/item grid grid-cols-6 gap-y-2 w-full h-full col-span-2 ">
- {categoryPilihan?.data?.map((category) => (
- <div key={category.id} className="KartuInti h-48 w-60 max-w-sm lg:max-w-full flex flex-col border-[1px] border-gray-200 relative group">
- <div className='KartuB absolute h-48 w-60 inset-0 flex items-center justify-center '>
- <div className="group/edit flex items-center justify-end h-48 w-60 flex-col group-hover/item:visible">
- <div className=' h-36 flex justify-end items-end'>
- <Image className='group-hover:scale-105 transition-transform duration-300 ' src={category?.image? category?.image : '/images/noimage.jpeg'} width={120} height={120} alt={category?.name} />
- </div>
- <h2 className="text-gray-700 content-center h-12 border-t-[1px] px-1 w-60 border-gray-200 font-normal text-sm text-center">{category?.industries}</h2>
- </div>
- </div>
- <div className='KartuA relative inset-0 flex h-36 w-60 items-center justify-center opacity-0 group-hover:opacity-75 group-hover:bg-[#E20613] transition-opacity '>
- <Link
- href={createSlug('/shop/lob/', category?.industries, category?.id)}
- className='category-mega-box__parent text-white rounded-lg'
- >
- Lihat semua
- </Link>
- </div>
- </div>
- ))}
+ const { isDesktop, isMobile } = useDevice();
+ const { categoryPilihan } = useCategoryPilihan();
+ const heroBanner = useQuery(
+ 'categoryPilihan',
+ bannerApi({ type: 'banner-category-list' })
+ );
+ return (
+ categoryPilihan.length > 0 && (
+ <section>
+ {isDesktop && (
+ <div>
+ <div className='flex flex-row items-center mb-4'>
+ <div className='font-semibold sm:text-h-lg mr-2'>
+ LOB Kategori Pilihan
+ </div>
+ <p className='text-gray_r-10 text-sm'>
+ 200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!
+ </p>
+ </div>
+ {heroBanner.data && heroBanner.data?.length > 0 && (
+ <div className='flex w-full h-full justify-center mb-4 bg-cover bg-center'>
+ <Link key={heroBanner.data[0].id} href={heroBanner.data[0].url}>
+ <Image
+ width={1260}
+ height={170}
+ quality={85}
+ src={heroBanner.data[0].image}
+ alt={heroBanner.data[0].name}
+ className='h-full object-cover w-full'
+ />
+ </Link>
+ </div>
+ )}
+ <div className='group/item grid grid-cols-6 gap-y-2 w-full h-full col-span-2 '>
+ {categoryPilihan?.data?.map((category) => (
+ <div
+ key={category.id}
+ className='KartuInti h-48 w-60 max-w-sm lg:max-w-full flex flex-col border-[1px] border-gray-200 relative group'
+ >
+ <div className='KartuB absolute h-48 w-60 inset-0 flex items-center justify-center '>
+ <div className='group/edit flex items-center justify-end h-48 w-60 flex-col group-hover/item:visible'>
+ <div className=' h-36 flex justify-end items-end'>
+ <Image
+ className='group-hover:scale-105 transition-transform duration-300 '
+ src={
+ category?.image
+ ? category?.image
+ : '/images/noimage.jpeg'
+ }
+ width={120}
+ height={120}
+ alt={category?.name}
+ />
+ </div>
+ <h2 className='text-gray-700 content-center h-12 border-t-[1px] px-1 w-60 border-gray-200 font-normal text-sm text-center'>
+ {category?.industries}
+ </h2>
</div>
+ </div>
+ <div className='KartuA relative inset-0 flex h-36 w-60 items-center justify-center opacity-0 group-hover:opacity-75 group-hover:bg-[#E20613] transition-opacity '>
+ <Link
+ href={createSlug(
+ '/shop/lob/',
+ category?.industries,
+ category?.id
+ )}
+ className='category-mega-box__parent text-white rounded-lg'
+ >
+ Lihat semua
+ </Link>
+ </div>
</div>
- )}
- {isMobile && (
- <div className='p-4'>
- <div className='flex flex-row items-center mb-4'>
- <div className='font-semibold sm:text-h-md mr-2'>LOB Kategori Pilihan</div>
- {/* <p className='text-gray_r-10 text-sm'>200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!</p> */}
+ ))}
+ </div>
+ </div>
+ )}
+ {isMobile && (
+ <div className='p-4'>
+ <div className='flex flex-row items-center mb-4'>
+ <div className='font-semibold sm:text-h-md mr-2'>
+ LOB Kategori Pilihan
+ </div>
+ {/* <p className='text-gray_r-10 text-sm'>200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!</p> */}
+ </div>
+ <div className='flex'>
+ {heroBanner.data && heroBanner.data?.length > 0 && (
+ <div className=' object-fill '>
+ <Link
+ key={heroBanner.data[0].id}
+ href={heroBanner.data[0].url}
+ >
+ <Image
+ width={439}
+ height={150}
+ quality={85}
+ src={heroBanner.data[0].image}
+ alt={heroBanner.data[0].name}
+ className='object-cover'
+ />
+ </Link>
+ </div>
+ )}
+ </div>
+ <Swiper slidesPerView={2.1} spaceBetween={10}>
+ {categoryPilihan?.data?.map((category) => (
+ <SwiperSlide key={category.id}>
+ <div
+ key={category.id}
+ className='KartuInti mt-2 h-48 w-48 max-w-sm lg:max-w-full flex flex-col border-[1px] border-gray-200 relative group'
+ >
+ <div className='KartuB absolute h-48 w-48 inset-0 flex items-center justify-center '>
+ <div className='group/edit flex items-center justify-end h-48 w-48 flex-col group-hover/item:visible'>
+ <div className=' h-36 flex justify-end items-end'>
+ <Image
+ className='group-hover:scale-105 transition-transform duration-300 '
+ src={
+ category?.image
+ ? category?.image
+ : '/images/noimage.jpeg'
+ }
+ width={120}
+ height={120}
+ alt={category?.name}
+ />
+ </div>
+ <h2 className='text-gray-700 content-center h-12 border-t-[1px] px-1 w-48 border-gray-200 font-normal text-sm text-center'>
+ {category?.industries}
+ </h2>
+ </div>
</div>
- <div className='flex'>
- {heroBanner.data &&
- heroBanner.data?.length > 0 && (
- <div className=' object-fill '>
- <Link key={heroBanner.data[0].id} href={heroBanner.data[0].url}>
- <Image
- width={439}
- height={150}
- quality={100}
- src={heroBanner.data[0].image}
- alt={heroBanner.data[0].name}
- className='object-cover'
- />
- </Link>
- </div>
- )}
+ <div className='KartuA relative inset-0 flex h-36 w-48 items-center justify-center opacity-0 group-hover:opacity-75 group-hover:bg-[#E20613] transition-opacity '>
+ <Link
+ href={createSlug(
+ '/shop/lob/',
+ category?.industries,
+ category?.id
+ )}
+ className='category-mega-box__parent text-white rounded-lg'
+ >
+ Lihat semua
+ </Link>
</div>
- <Swiper slidesPerView={2.1} spaceBetween={10}>
- {categoryPilihan?.data?.map((category) => (
- <SwiperSlide key={category.id}>
- <div key={category.id} className="KartuInti mt-2 h-48 w-48 max-w-sm lg:max-w-full flex flex-col border-[1px] border-gray-200 relative group">
- <div className='KartuB absolute h-48 w-48 inset-0 flex items-center justify-center '>
- <div className="group/edit flex items-center justify-end h-48 w-48 flex-col group-hover/item:visible">
- <div className=' h-36 flex justify-end items-end'>
- <Image className='group-hover:scale-105 transition-transform duration-300 ' src={category?.image? category?.image : '/images/noimage.jpeg'} width={120} height={120} alt={category?.name} />
- </div>
- <h2 className="text-gray-700 content-center h-12 border-t-[1px] px-1 w-48 border-gray-200 font-normal text-sm text-center">{category?.industries}</h2>
- </div>
- </div>
- <div className='KartuA relative inset-0 flex h-36 w-48 items-center justify-center opacity-0 group-hover:opacity-75 group-hover:bg-[#E20613] transition-opacity '>
- <Link
- href={createSlug('/shop/lob/', category?.industries, category?.id)}
- className='category-mega-box__parent text-white rounded-lg'
- >
- Lihat semua
- </Link>
- </div>
- </div>
- </SwiperSlide>
- ))}
-
- </Swiper>
-
- </div>
- )}
- </section>
-
- )
- )
-}
+ </div>
+ </SwiperSlide>
+ ))}
+ </Swiper>
+ </div>
+ )}
+ </section>
+ )
+ );
+};
-export default CategoryPilihan
+export default CategoryPilihan;
diff --git a/src/lib/home/components/PromotionProgram.jsx b/src/lib/home/components/PromotionProgram.jsx
index ae8d5d6f..ae06bd4d 100644
--- a/src/lib/home/components/PromotionProgram.jsx
+++ b/src/lib/home/components/PromotionProgram.jsx
@@ -1,13 +1,16 @@
-import Link from '@/core/components/elements/Link/Link'
-import Image from 'next/image'
+import Link from '@/core/components/elements/Link/Link';
+import Image from 'next/image';
import { bannerApi } from '@/api/bannerApi';
-import useDevice from '@/core/hooks/useDevice'
+import useDevice from '@/core/hooks/useDevice';
import { Swiper, SwiperSlide } from 'swiper/react';
-import BannerPromoSkeleton from '../components/Skeleton/BannerPromoSkeleton';
-const { useQuery } = require('react-query')
+import BannerPromoSkeleton from '../components/Skeleton/BannerPromoSkeleton';
+const { useQuery } = require('react-query');
const BannerSection = () => {
- const promotionProgram = useQuery('promotionProgram', bannerApi({ type: 'banner-promotion' }));
- const { isMobile, isDesktop } = useDevice()
+ const promotionProgram = useQuery(
+ 'promotionProgram',
+ bannerApi({ type: 'banner-promotion' })
+ );
+ const { isMobile, isDesktop } = useDevice();
if (promotionProgram.isLoading) {
return <BannerPromoSkeleton />;
@@ -16,60 +19,65 @@ const BannerSection = () => {
return (
<div className='px-4 sm:px-0'>
<div className='flex justify-between items-center mb-4 '>
- <h1 className='font-semibold text-[14px] sm:text-h-lg'> <Link href='/shop/promo' className='!text-black font-semibold' >Promo Tersedia</Link></h1>
+ <h1 className='font-semibold text-[14px] sm:text-h-lg'>
+ {' '}
+ <Link href='/shop/promo' className='!text-black font-semibold'>
+ Promo Tersedia
+ </Link>
+ </h1>
{isDesktop && (
<Link href='/shop/promo' className='!text-red-500 font-semibold'>
- Lihat Semua
- </Link>
+ Lihat Semua
+ </Link>
)}
{isMobile && (
- <Link href='/shop/promo' className='!text-red-500 font-semibold sm:text-h-sm'>
- Lihat Semua
- </Link>
- )}
- </div>
- {isDesktop && (promotionProgram.data &&
- promotionProgram.data?.length > 0 && (
- <div className='grid grid-cols-3 sm:grid-cols-3 gap-4 rounded-md'>
- {promotionProgram.data?.map((banner) => (
- <Link key={banner.id} href={banner.url}>
- <Image
- width={439}
- height={150}
- quality={100}
- src={banner.image}
- alt={banner.name}
- className='h-auto w-full rounded hover:scale-105 transition duration-500 ease-in-out'
- />
+ <Link
+ href='/shop/promo'
+ className='!text-red-500 font-semibold sm:text-h-sm'
+ >
+ Lihat Semua
</Link>
- ))}
+ )}
</div>
-
- ))}
+ {isDesktop &&
+ promotionProgram.data &&
+ promotionProgram.data?.length > 0 && (
+ <div className='grid grid-cols-3 sm:grid-cols-3 gap-4 rounded-md'>
+ {promotionProgram.data?.map((banner) => (
+ <Link key={banner.id} href={banner.url}>
+ <Image
+ width={439}
+ height={150}
+ quality={85}
+ src={banner.image}
+ alt={banner.name}
+ className='h-auto w-full rounded hover:scale-105 transition duration-500 ease-in-out'
+ />
+ </Link>
+ ))}
+ </div>
+ )}
-{isMobile && (
-
- <Swiper slidesPerView={1.1} spaceBetween={8} freeMode>
- {promotionProgram.data?.map((banner) => (
- <SwiperSlide key={banner.id}>
- <Link key={banner.id} href={banner.url}>
- <Image
- width={439}
- height={150}
- quality={100}
- src={banner.image}
- alt={banner.name}
- className='h-auto w-full rounded '
- />
- </Link>
- </SwiperSlide>
- ))}
- </Swiper>
-
- )}
+ {isMobile && (
+ <Swiper slidesPerView={1.1} spaceBetween={8} freeMode>
+ {promotionProgram.data?.map((banner) => (
+ <SwiperSlide key={banner.id}>
+ <Link key={banner.id} href={banner.url}>
+ <Image
+ width={439}
+ height={150}
+ quality={85}
+ src={banner.image}
+ alt={banner.name}
+ className='h-auto w-full rounded '
+ />
+ </Link>
+ </SwiperSlide>
+ ))}
+ </Swiper>
+ )}
</div>
-
- )
-}
+ );
+};
-export default BannerSection
+export default BannerSection;
diff --git a/src/lib/home/components/ServiceList.jsx b/src/lib/home/components/ServiceList.jsx
index b8799d7d..5b16915d 100644
--- a/src/lib/home/components/ServiceList.jsx
+++ b/src/lib/home/components/ServiceList.jsx
@@ -1,5 +1,5 @@
-import Image from 'next/image'
-import Link from '@/core/components/elements/Link/Link'
+import Image from 'next/image';
+import Link from '@/core/components/elements/Link/Link';
const ServiceList = () => {
return (
@@ -14,14 +14,16 @@ const ServiceList = () => {
<Image
width={24}
height={24}
- quality={100}
+ quality={85}
src='/images/icon_service/ONE-STOP-SOLUTIONS.svg'
alt=''
className='h-20 w-20 rounded'
/>
</div>
<div className=''>
- <h1 className='text-gray-900 font-semibold text-base'>One Stop Solution</h1>
+ <h1 className='text-gray-900 font-semibold text-base'>
+ One Stop Solution
+ </h1>
<p className='text-xs md:text-sm text-gray-500'>
Temukan Solusi Lengkap Anda dalam Satu Tempat.
</p>
@@ -37,14 +39,16 @@ const ServiceList = () => {
<Image
width={24}
height={24}
- quality={100}
+ quality={85}
src='/images/icon_service/WARRANTY.svg'
alt=''
className='h-20 w-20 rounded'
/>
</div>
<div>
- <h1 className='text-gray-900 font-semibold text-base'>Garansi Resmi</h1>
+ <h1 className='text-gray-900 font-semibold text-base'>
+ Garansi Resmi
+ </h1>
<p className='text-xs md:text-sm text-gray-500'>
Garansi Keaslian Barang dan Jaminan Purna Jual.
</p>
@@ -60,14 +64,16 @@ const ServiceList = () => {
<Image
width={24}
height={24}
- quality={100}
+ quality={85}
src='/images/icon_service/DUE-PAYMENT.svg'
alt=''
className='h-20 w-20 rounded'
/>
</div>
<div>
- <h1 className='text-gray-900 font-semibold text-base'>Pembayaran Tempo</h1>
+ <h1 className='text-gray-900 font-semibold text-base'>
+ Pembayaran Tempo
+ </h1>
<p className='text-xs md:text-sm text-gray-500'>
Lebih mudah mengatur pembelian dengan pembayaran tempo.
</p>
@@ -83,14 +89,16 @@ const ServiceList = () => {
<Image
width={24}
height={24}
- quality={100}
+ quality={85}
src='/images/icon_service/TAX.svg'
alt=''
className='h-20 w-20 rounded'
/>
</div>
<div>
- <h1 className='text-gray-900 font-semibold text-base'>Faktur Pajak</h1>
+ <h1 className='text-gray-900 font-semibold text-base'>
+ Faktur Pajak
+ </h1>
<p className='text-xs md:text-sm text-gray-500'>
Dapat Faktur pajak untuk setiap transaksi dengan indoteknik.com
</p>
@@ -99,7 +107,7 @@ const ServiceList = () => {
</div>
</div>
</div>
- )
-}
+ );
+};
-export default ServiceList
+export default ServiceList;
diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx
index 4529c977..cb7684ed 100644
--- a/src/lib/quotation/components/Quotationheader.jsx
+++ b/src/lib/quotation/components/Quotationheader.jsx
@@ -19,14 +19,22 @@ const Quotationheader = (quotationCount) => {
context: 'quotation',
site: auth?.webRole === null && auth?.site ? auth.site : null,
};
-
+
const router = useRouter();
const [subTotal, setSubTotal] = useState(null);
const [buttonLoading, SetButtonTerapkan] = useState(false);
const itemLoading = [1, 2, 3];
const [countQuotation, setCountQuotation] = useState(null);
- const { productCart, setProductCart, refreshCart, setRefreshCart, isLoading, setIsloading, productQuotation, setProductQuotation } =
- useProductCartContext();
+ const {
+ productCart,
+ setProductCart,
+ refreshCart,
+ setRefreshCart,
+ isLoading,
+ setIsloading,
+ productQuotation,
+ setProductQuotation,
+ } = useProductCartContext();
const [isHovered, setIsHovered] = useState(false);
const [isTop, setIsTop] = useState(true);
@@ -49,34 +57,44 @@ const Quotationheader = (quotationCount) => {
refreshCartf();
}
};
- let { transactions } = useTransactions({ query });
+ let transactions = null;
+
+ if (auth) {
+ transactions = useTransactions({ query });
+ }
const refreshCartf = useCallback(async () => {
setIsloading(true);
- let pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft');
+ let pendingTransactions = transactions?.data?.saleOrders.filter(
+ (transaction) => transaction.status === 'draft'
+ );
setProductQuotation(pendingTransactions);
- setCountQuotation(pendingTransactions?.length ? pendingTransactions?.length : pendingTransactions?.length);
+ setCountQuotation(
+ pendingTransactions?.length
+ ? pendingTransactions?.length
+ : pendingTransactions?.length
+ );
setIsloading(false);
}, [setProductQuotation, setIsloading]);
useEffect(() => {
- if (!qotation) return
+ if (!qotation) return;
- let calculateTotalDiscountAmount = 0
+ let calculateTotalDiscountAmount = 0;
for (const product of qotation) {
- // if (qotation.quantity == '') continue
- calculateTotalDiscountAmount += product.amountUntaxed
+ // if (qotation.quantity == '') continue
+ calculateTotalDiscountAmount += product.amountUntaxed;
}
- let subTotal = calculateTotalDiscountAmount
- setSubTotal(subTotal)
- }, [qotation])
+ let subTotal = calculateTotalDiscountAmount;
+ setSubTotal(subTotal);
+ }, [qotation]);
useEffect(() => {
if (refreshCart) {
refreshCartf();
}
setRefreshCart(false);
- }, [ refreshCartf, setRefreshCart]);
+ }, [refreshCartf, setRefreshCart]);
useEffect(() => {
setCountQuotation(quotationCount.quotationCount);
@@ -95,7 +113,10 @@ const Quotationheader = (quotationCount) => {
const handleCheckout = async () => {
SetButtonTerapkan(true);
- let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`);
+ let checkoutAll = await odooApi(
+ 'POST',
+ `/api/v1/user/${auth.id}/cart/select-all`
+ );
router.push('/my/quotations');
};
@@ -150,7 +171,9 @@ const Quotationheader = (quotationCount) => {
className='w-full max-w-md p-2 bg-white border border-gray-200 rounded-lg shadow overflow-hidden'
>
<div className='p-2 flex justify-between items-center'>
- <h5 className='text-base font-semibold leading-none'>Daftar Quotation</h5>
+ <h5 className='text-base font-semibold leading-none'>
+ Daftar Quotation
+ </h5>
</div>
<hr className='mt-3 mb-3 border border-gray-100' />
<div className='flow-root max-h-[250px] overflow-y-auto'>
@@ -158,7 +181,10 @@ const Quotationheader = (quotationCount) => {
<div className='justify-center p-4'>
<p className='text-gray-500 text-center '>
Silahkan{' '}
- <Link href='/login' className='text-red-600 underline leading-6'>
+ <Link
+ href='/login'
+ className='text-red-600 underline leading-6'
+ >
Login
</Link>{' '}
Untuk Melihat Daftar Quotation Anda
@@ -167,7 +193,11 @@ const Quotationheader = (quotationCount) => {
)}
{isLoading &&
itemLoading.map((item) => (
- <div key={item} role='status' className='max-w-sm animate-pulse'>
+ <div
+ key={item}
+ role='status'
+ className='max-w-sm animate-pulse'
+ >
<div className='flex items-center space-x-4 mb- 2'>
<div className='flex-shrink-0'>
<PhotoIcon className='h-16 w-16 text-gray-500' />
@@ -189,43 +219,70 @@ const Quotationheader = (quotationCount) => {
)}
{auth && qotation.length > 0 && !isLoading && (
<>
- <ul role='list' className='divide-y divide-gray-200 dark:divide-gray-700'>
+ <ul
+ role='list'
+ className='divide-y divide-gray-200 dark:divide-gray-700'
+ >
{qotation &&
qotation?.map((product, index) => (
<>
<li className='py-1 sm:py-2'>
<div className='flex justify-between border p-2 flex-col gap-y-2 hover:border-red-500'>
- <Link
+ <Link
href={`/my/quotations/${product?.id}`}
- className='hover:border-red-500'
- >
+ className='hover:border-red-500'
+ >
<div className='flex justify-between mb-2'>
<div className='flex flex-row items-center'>
- <p className='tanggal text-xs opacity-80 mr-[2px]'>Sales : </p>
- <p className='tanggal text-xs text-red-500 font-semibold'>{product.sales}</p>
+ <p className='tanggal text-xs opacity-80 mr-[2px]'>
+ Sales :{' '}
+ </p>
+ <p className='tanggal text-xs text-red-500 font-semibold'>
+ {product.sales}
+ </p>
</div>
<div className='flex flex-row items-center'>
- <p className='text-xs opacity-80 mr-[2px]'>Status :</p>
- <p className='badge-red h-fit text-xs whitespace-nowrap'>Pending Quotation</p>
+ <p className='text-xs opacity-80 mr-[2px]'>
+ Status :
+ </p>
+ <p className='badge-red h-fit text-xs whitespace-nowrap'>
+ Pending Quotation
+ </p>
</div>
</div>
<div className='flex justify-between mb-2'>
<div className='flex flex-col items-start'>
- <p className=' text-xs opacity-80 mr-[2px]'>No. Transaksi</p>
- <p className=' text-sm text-red-500 font-semibold'> {product.name}</p>
+ <p className=' text-xs opacity-80 mr-[2px]'>
+ No. Transaksi
+ </p>
+ <p className=' text-sm text-red-500 font-semibold'>
+ {' '}
+ {product.name}
+ </p>
</div>
<div className='flex flex-col items-end'>
- <p className='text-xs opacity-80 mr-[2px]'>No. Purchase Order</p>
- <p className='font-semibold text-sm text-red-500'> {product.purchaseOrderName ? product.purchaseOrderName : '-'}</p>
+ <p className='text-xs opacity-80 mr-[2px]'>
+ No. Purchase Order
+ </p>
+ <p className='font-semibold text-sm text-red-500'>
+ {' '}
+ {product.purchaseOrderName
+ ? product.purchaseOrderName
+ : '-'}
+ </p>
</div>
</div>
{/* <div className='my-0.5 h-0.5 bg-gray-200'></div> */}
<hr className='mt-3 mb-3 border border-gray-100' />
<div className='bagian bawah flex justify-between mt-2'>
- <p className='font-semibold text-sm'>Total</p>
- <p className='font-semibold text-sm'>{currencyFormat(product.amountUntaxed)}</p>
+ <p className='font-semibold text-sm'>
+ Total
+ </p>
+ <p className='font-semibold text-sm'>
+ {currencyFormat(product.amountUntaxed)}
+ </p>
</div>
- </Link>
+ </Link>
</div>
</li>
</>
@@ -238,8 +295,12 @@ const Quotationheader = (quotationCount) => {
{auth && qotation.length > 0 && !isLoading && (
<>
<div className='mt-3 ml-1'>
- <span className='text-gray-400 text-caption-2'>Subtotal Sebelum PPN : </span>
- <span className='font-semibold text-red-600'>{currencyFormat(subTotal)}</span>
+ <span className='text-gray-400 text-caption-2'>
+ Subtotal Sebelum PPN :{' '}
+ </span>
+ <span className='font-semibold text-red-600'>
+ {currencyFormat(subTotal)}
+ </span>
</div>
<div className='mt-5 mb-2'>
<button
diff --git a/src/lib/review/components/CustomerReviews.jsx b/src/lib/review/components/CustomerReviews.jsx
index 7cad52fb..a6e697f0 100644
--- a/src/lib/review/components/CustomerReviews.jsx
+++ b/src/lib/review/components/CustomerReviews.jsx
@@ -1,18 +1,23 @@
-import DesktopView from '@/core/components/views/DesktopView'
-import MobileView from '@/core/components/views/MobileView'
-import Image from 'next/image'
-import { Swiper, SwiperSlide } from 'swiper/react'
-import { Autoplay } from 'swiper'
+import DesktopView from '@/core/components/views/DesktopView';
+import MobileView from '@/core/components/views/MobileView';
+import Image from 'next/image';
+import { Swiper, SwiperSlide } from 'swiper/react';
+import { Autoplay } from 'swiper';
-const { useQuery } = require('react-query')
-const { getCustomerReviews } = require('../api/customerReviewsApi')
+const { useQuery } = require('react-query');
+const { getCustomerReviews } = require('../api/customerReviewsApi');
const CustomerReviews = () => {
- const { data: customerReviews } = useQuery('customerReviews', getCustomerReviews)
+ const { data: customerReviews } = useQuery(
+ 'customerReviews',
+ getCustomerReviews
+ );
return (
<div className='px-4 sm:px-0'>
- <div className='font-semibold sm:text-h-lg mb-4'>Ulasan Konsumen Kami</div>
+ <h1 className='font-semibold text-[14px] sm:text-h-lg mb-4'>
+ Ulasan Konsumen Kami
+ </h1>
<DesktopView>
<Swiper slidesPerView={3.2} spaceBetween={16} {...swiperProps}>
@@ -36,17 +41,17 @@ const CustomerReviews = () => {
</Swiper>
</MobileView>
</div>
- )
-}
+ );
+};
const swiperProps = {
autoplay: {
delay: 6000,
- disableOnInteraction: false
+ disableOnInteraction: false,
},
loop: true,
- modules: [Autoplay]
-}
+ modules: [Autoplay],
+};
const Card = ({ customerReview }) => (
<div className='bg-gray-200 rounded-md px-5 py-6 shadow-md shadow-gray-500/20 h-full'>
@@ -67,6 +72,6 @@ const Card = ({ customerReview }) => (
dangerouslySetInnerHTML={{ __html: customerReview.ulasan }}
/>
</div>
-)
+);
-export default CustomerReviews
+export default CustomerReviews;
diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx
index 394979c1..8a7b2579 100644
--- a/src/lib/tracking-order/component/TrackingOrder.jsx
+++ b/src/lib/tracking-order/component/TrackingOrder.jsx
@@ -1,139 +1,161 @@
-import { yupResolver } from '@hookform/resolvers/yup'
-import React, { useEffect, useState } from 'react'
-import { useForm } from 'react-hook-form'
-import * as Yup from 'yup'
-import Manifest from '@/lib/treckingAwb/component/Manifest'
-import { trackingOrder } from '../api/trackingOrder'
-import { useQuery } from 'react-query'
+import { yupResolver } from '@hookform/resolvers/yup';
+import React, { useEffect, useState } from 'react';
+import { useForm } from 'react-hook-form';
+import * as Yup from 'yup';
+import Manifest from '@/lib/treckingAwb/component/Manifest';
+import { trackingOrder } from '../api/trackingOrder';
+import { useQuery } from 'react-query';
import { Spinner } from '@chakra-ui/react';
import { Search } from 'lucide-react';
-import whatsappUrl from '@/core/utils/whatsappUrl';
-import Link from 'next/link'
+import Link from 'next/link';
const TrackingOrder = () => {
- const [idAWB, setIdAWB] = useState(null)
- const [inputQuery, setInputQuery] = useState(null)
- const [buttonClick, setButtonClick] = useState(false)
- const [apiError, setApiError] = useState(null) // State to store API error message
-
- const closePopup = () => {
- setIdAWB(null)
- setButtonClick(false)
- setInputQuery(null)
- setApiError(null) // Reset error message on close
- }
-
- const {
- register,
- handleSubmit,
- formState: { errors },
- control,
- reset
- } = useForm({
- resolver: yupResolver(validationSchema),
- defaultValues
- })
-
- const query = {
- email: inputQuery?.email,
- so: inputQuery?.id
- }
-
- const { data: tracking, isLoading, isError, error } = useQuery(
- ['tracking', query],
- () => trackingOrder({ query: query }),
- {
- enabled: !!query.email && !!query.so,
- onSuccess: (data) => {
- if (buttonClick) {
- if (data?.code === 403 || data?.code === 400 || data?.code === 404) {
- setApiError(data?.description);
- } else if (data?.pickings?.length > 0) {
- setIdAWB(data.pickings[0]?.id);
- } else {
- setApiError('No pickings data available');
- }
- setButtonClick(false);
- setInputQuery(null);
- }
- },
+ const [idAWB, setIdAWB] = useState(null);
+ const [inputQuery, setInputQuery] = useState(null);
+ const [buttonClick, setButtonClick] = useState(false);
+ const [apiError, setApiError] = useState(null); // State to store API error message
+
+ const closePopup = () => {
+ setIdAWB(null);
+ setButtonClick(false);
+ setInputQuery(null);
+ setApiError(null); // Reset error message on close
+ };
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ control,
+ reset,
+ } = useForm({
+ resolver: yupResolver(validationSchema),
+ defaultValues,
+ });
+
+ const query = {
+ email: inputQuery?.email,
+ so: inputQuery?.id,
+ };
+
+ const {
+ data: tracking,
+ isLoading,
+ isError,
+ error,
+ } = useQuery(['tracking', query], () => trackingOrder({ query: query }), {
+ enabled: !!query.email && !!query.so,
+ onSuccess: (data) => {
+ if (buttonClick) {
+ if (data?.code === 403 || data?.code === 400 || data?.code === 404) {
+ setApiError(data?.description);
+ } else if (data?.pickings?.length > 0) {
+ setIdAWB(data.pickings[0]?.id);
+ } else {
+ setApiError('No pickings data available');
}
- );
+ setButtonClick(false);
+ setInputQuery(null);
+ }
+ },
+ });
- const onSubmitHandler = async (values) => {
- setInputQuery(values)
- setButtonClick(true)
- }
+ const onSubmitHandler = async (values) => {
+ setInputQuery(values);
+ setButtonClick(true);
+ };
- return (
- <div className='container mx-auto flex py-10 flex-col'>
- <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Tracking Order</h1>
- <div className='flex justify-start items-start'>
- <span className='text-base w-full'>
- {`Untuk melacak pesanan Anda, masukkan Nomor Transaksi di kotak bawah ini dan masukkan Email login anda lalu tekan tombol "Lacak". Nomor Transaksi ini dapat Anda lihat dalam menu `}
- <Link href='/my/transactions' className='text-red-500'>
- Daftar Transaksi
- </Link>
- {`. Jika mengalami kesulitan `}
- <Link href='https://wa.me/6281717181922' target='_blank' rel='noreferrer' className='text-red-500'>
- hubungi kami
- </Link>
- {`.`}
- </span>
+ return (
+ <div className='container mx-auto flex py-10 flex-col'>
+ <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>
+ Tracking Order
+ </h1>
+ <div className='flex justify-start items-start'>
+ <p className='text-base w-full'>
+ {`Untuk melacak pesanan Anda, masukkan Nomor Transaksi di kotak bawah ini dan masukkan Email login anda lalu tekan tombol "Lacak". Nomor Transaksi ini dapat Anda lihat dalam menu `}
+ <Link href='/my/transactions' className='text-red-500'>
+ Daftar Transaksi
+ </Link>
+ {`. Jika mengalami kesulitan `}
+ <Link
+ href='https://wa.me/6281717181922'
+ target='_blank'
+ rel='noreferrer'
+ className='text-red-500'
+ >
+ hubungi kami
+ </Link>
+ {`.`}
+ </p>
+ </div>
+ <div>
+ <form
+ onSubmit={handleSubmit(onSubmitHandler)}
+ className='flex mt-4 flex-row w-full '
+ >
+ <div className='w-[90%] grid grid-cols-2 gap-4'>
+ <div className='flex flex-col '>
+ <label className='form-label mb-2'>ID Pesanan*</label>
+ <input
+ {...register('id')}
+ placeholder='dapat dilihat pada email konfirmasi anda'
+ type='text'
+ className='form-input mb-2'
+ aria-invalid={errors.id?.message}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.id?.message}
+ </div>
</div>
- <div>
- <form onSubmit={handleSubmit(onSubmitHandler)} className='flex mt-4 flex-row w-full '>
- <div className='w-[90%] grid grid-cols-2 gap-4'>
- <div className='flex flex-col '>
- <label className='form-label mb-2'>ID Pesanan*</label>
- <input
- {...register('id')}
- placeholder='dapat dilihat pada email konfirmasi anda'
- type='text'
- className='form-input mb-2'
- aria-invalid={errors.id?.message}
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.id?.message}</div>
- </div>
- <div className='flex flex-col '>
- <label className='form-label mb-2'>Email Penagihan*</label>
- <input
- {...register('email')}
- placeholder='Email yang anda gunakan saat pembayaran'
- type='text'
- className='form-input'
- aria-invalid={errors.email?.message}
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
- </div>
- </div>
- <div className={` ${errors.id?.message ? 'mt-2' : 'mt-5'} flex items-center ml-4`}>
- <button
- type='submit'
- className='bg-red-600 border border-red-600 rounded-md text-sm text-white w-24 h-11 mb-1 content-center flex flex-row justify-center items-center'
- >
- {isLoading && <Spinner size='xs' className='mr-2'/>}
- {!isLoading && <Search size={16} strokeWidth={1} className='mr-2'/>}
- <p>Lacak</p>
- </button>
- </div>
- </form>
- {/* Display the API error message */}
- {apiError && <div className='text-danger-500 mt-4'>{apiError}</div>}
- <Manifest idAWB={idAWB} closePopup={closePopup} />
+ <div className='flex flex-col '>
+ <label className='form-label mb-2'>Email Penagihan*</label>
+ <input
+ {...register('email')}
+ placeholder='Email yang anda gunakan saat pembayaran'
+ type='text'
+ className='form-input'
+ aria-invalid={errors.email?.message}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.email?.message}
+ </div>
</div>
- </div>
- )
-}
+ </div>
+ <div
+ className={` ${
+ errors.id?.message ? 'mt-2' : 'mt-5'
+ } flex items-center ml-4`}
+ >
+ <button
+ type='submit'
+ className='bg-red-600 border border-red-600 rounded-md text-sm text-white w-24 h-11 mb-1 content-center flex flex-row justify-center items-center'
+ >
+ {isLoading && <Spinner size='xs' className='mr-2' />}
+ {!isLoading && (
+ <Search size={16} strokeWidth={1} className='mr-2' />
+ )}
+ <p>Lacak</p>
+ </button>
+ </div>
+ </form>
+ {/* Display the API error message */}
+ {apiError && <div className='text-danger-500 mt-4'>{apiError}</div>}
+ <Manifest idAWB={idAWB} closePopup={closePopup} />
+ </div>
+ </div>
+ );
+};
const validationSchema = Yup.object().shape({
- email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
- id: Yup.string().required('Harus di-isi'),
-})
+ email: Yup.string()
+ .email('Format harus seperti contoh@email.com')
+ .required('Harus di-isi'),
+ id: Yup.string().required('Harus di-isi'),
+});
const defaultValues = {
- email: '',
- id: ''
-}
+ email: '',
+ id: '',
+};
-export default TrackingOrder
+export default TrackingOrder;
diff --git a/src/pages/my/profile.jsx b/src/pages/my/profile.jsx
index 25c3a608..7cf1bcbb 100644
--- a/src/pages/my/profile.jsx
+++ b/src/pages/my/profile.jsx
@@ -1,41 +1,44 @@
-import Divider from '@/core/components/elements/Divider/Divider'
-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 useAuth from '@/core/hooks/useAuth'
-import CompanyProfile from '@/lib/auth/components/CompanyProfile'
-import IsAuth from '@/lib/auth/components/IsAuth'
-import Menu from '@/lib/auth/components/Menu'
-import PersonalProfile from '@/lib/auth/components/PersonalProfile'
+import Divider from '@/core/components/elements/Divider/Divider';
+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 useAuth from '@/core/hooks/useAuth';
+import CompanyProfile from '@/lib/auth/components/CompanyProfile';
+import IsAuth from '@/lib/auth/components/IsAuth';
+import Menu from '@/lib/auth/components/Menu';
+import PersonalProfile from '@/lib/auth/components/PersonalProfile';
+import Seo from '@/core/components/Seo';
export default function Profile() {
- const auth = useAuth()
+ const auth = useAuth();
return (
- <IsAuth>
- <MobileView>
- <AppLayout title='Akun Saya'>
- <PersonalProfile />
- <Divider />
- {auth?.parentId && <CompanyProfile />}
- </AppLayout>
- </MobileView>
-
- <DesktopView>
- <BasicLayout>
- <div className='container mx-auto flex py-10'>
- <div className='w-3/12 pr-4'>
- <Menu />
- </div>
- <div className='w-9/12 bg-white border border-gray_r-6 rounded'>
+ <>
+ <Seo title='Profile - Indoteknik.com' />
+ <IsAuth>
+ <MobileView>
+ <AppLayout title='Akun Saya'>
<PersonalProfile />
<Divider />
{auth?.parentId && <CompanyProfile />}
+ </AppLayout>
+ </MobileView>
- </div>
- </div>
- </BasicLayout>
- </DesktopView>
- </IsAuth>
- )
+ <DesktopView>
+ <BasicLayout>
+ <div className='container mx-auto flex py-10'>
+ <div className='w-3/12 pr-4'>
+ <Menu />
+ </div>
+ <div className='w-9/12 bg-white border border-gray_r-6 rounded'>
+ <PersonalProfile />
+ <Divider />
+ {auth?.parentId && <CompanyProfile />}
+ </div>
+ </div>
+ </BasicLayout>
+ </DesktopView>
+ </IsAuth>
+ </>
+ );
}