summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/brand/components/BrandCard.jsx8
-rw-r--r--src/lib/cart/components/Cartheader.jsx262
-rw-r--r--src/lib/category/api/popularProduct.js31
-rw-r--r--src/lib/category/components/Category.jsx60
-rw-r--r--src/lib/category/components/PopularBrand.jsx83
-rw-r--r--src/lib/checkout/components/Checkout.jsx4
-rw-r--r--src/lib/flashSale/components/FlashSale.jsx63
-rw-r--r--src/lib/flashSale/components/FlashSaleNonDisplay.jsx4
-rw-r--r--src/lib/home/api/CategoryPilihanApi.js8
-rw-r--r--src/lib/home/api/categoryManagementApi.js8
-rw-r--r--src/lib/home/components/CategoryDynamic.jsx108
-rw-r--r--src/lib/home/components/CategoryDynamicMobile.jsx101
-rw-r--r--src/lib/home/components/CategoryPilihan.jsx120
-rw-r--r--src/lib/home/components/PreferredBrand.jsx46
-rw-r--r--src/lib/home/components/PromotionProgram.jsx5
-rw-r--r--src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx16
-rw-r--r--src/lib/home/hooks/useCategoryManagement.js13
-rw-r--r--src/lib/home/hooks/useCategoryPilihan.js13
-rw-r--r--src/lib/lob/components/Breadcrumb.jsx55
-rw-r--r--src/lib/product/components/CategorySection.jsx104
-rw-r--r--src/lib/product/components/LobSectionCategory.jsx81
-rw-r--r--src/lib/product/components/Product/ProductDesktopVariant.jsx86
-rw-r--r--src/lib/product/components/Product/ProductMobileVariant.jsx71
-rw-r--r--src/lib/product/components/ProductCard.jsx32
-rw-r--r--src/lib/product/components/ProductFilter.jsx1
-rw-r--r--src/lib/product/components/ProductFilterDesktop.jsx7
-rw-r--r--src/lib/product/components/ProductSearch.jsx19
-rw-r--r--src/lib/quotation/components/Quotation.jsx7
-rw-r--r--src/lib/quotation/components/Quotationheader.jsx265
-rw-r--r--src/lib/tracking-order/api/trackingOrder.js8
-rw-r--r--src/lib/tracking-order/component/TrackingOrder.jsx139
-rw-r--r--src/lib/transaction/api/checkoutPoApi.js4
-rw-r--r--src/lib/transaction/components/Transaction.jsx429
33 files changed, 330 insertions, 1931 deletions
diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx
index 2d78d956..731214ff 100644
--- a/src/lib/brand/components/BrandCard.jsx
+++ b/src/lib/brand/components/BrandCard.jsx
@@ -8,7 +8,7 @@ const BrandCard = ({ brand }) => {
return (
<Link
href={createSlug('/shop/brands/', brand.name, brand.id)}
- className={`py-1 px-2 border-gray_r-6 flex justify-center items-center hover:scale-110 transition duration-500 ease-in-out ${
+ className={`py-1 px-2 rounded border border-gray_r-6 flex justify-center items-center ${
isMobile ? 'h-16' : 'h-24'
}`}
>
@@ -16,9 +16,9 @@ const BrandCard = ({ brand }) => {
<Image
src={brand.logo}
alt={brand.name}
- width={50}
- height={50}
- className='h-full w-[122px] object-contain object-center'
+ width={128}
+ height={128}
+ className='h-full w-full object-contain object-center'
/>
)}
{!brand.logo && (
diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx
index 6967d180..19f79bc9 100644
--- a/src/lib/cart/components/Cartheader.jsx
+++ b/src/lib/cart/components/Cartheader.jsx
@@ -1,20 +1,14 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
import { getCartApi } from '../api/CartApi'
-import currencyFormat from '@/core/utils/currencyFormat'
-import { createSlug } from '@/core/utils/slug'
import useAuth from '@/core/hooks/useAuth'
import { useRouter } from 'next/router'
import odooApi from '@/core/api/odooApi'
import { useProductCartContext } from '@/contexts/ProductCartContext'
-import Image from '@/core/components/elements/Image/Image'
-import whatsappUrl from '@/core/utils/whatsappUrl'
-import { AnimatePresence, motion } from 'framer-motion'
-import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css'
+
const { ShoppingCartIcon, PhotoIcon } = require('@heroicons/react/24/outline')
const { default: Link } = require('next/link')
const Cardheader = (cartCount) => {
-
const router = useRouter()
const [subTotal, setSubTotal] = useState(null)
const [buttonLoading, SetButtonTerapkan] = useState(false)
@@ -25,7 +19,7 @@ const Cardheader = (cartCount) => {
useProductCartContext()
const [isHovered, setIsHovered] = useState(false)
- const [isTop, setIsTop] = useState(true)
+
const products = useMemo(() => {
return productCart?.products || []
}, [productCart])
@@ -81,26 +75,14 @@ const Cardheader = (cartCount) => {
useEffect(() => {
setCountCart(cartCount.cartCount)
- setRefreshCart(false)
}, [cartCount])
- useEffect(() => {
- const handleScroll = () => {
- setIsTop(window.scrollY === 0)
- }
- window.addEventListener('scroll', handleScroll)
- return () => {
- window.removeEventListener('scroll', handleScroll)
- }
- }, [])
-
const handleCheckout = async () => {
SetButtonTerapkan(true)
let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`)
router.push('/shop/checkout')
}
-
return (
<div className='relative group'>
<div>
@@ -127,246 +109,6 @@ const Cardheader = (cartCount) => {
</span>
</Link>
</div>
- <AnimatePresence>
- {isHovered && (
- <>
- <motion.div
- initial={{ opacity: 0 }}
- animate={{ opacity: 1, top: isTop ? 230 : 155 }}
- exit={{ opacity: 0 }}
- transition={{ duration: 0.15, top: { duration: 0.3 } }}
- className={`fixed left-0 w-full h-full bg-black/50 z-10`}
- />
- <motion.div
- initial={{ opacity: 0 }}
- animate={{ opacity: 1, transition: { duration: 0.2 } }}
- exit={{ opacity: 0, transition: { duration: 0.3 } }}
- className='absolute z-10 left-0 w-96'
- onMouseEnter={handleMouseEnter}
- onMouseLeave={handleMouseLeave}
- >
- <motion.div
- initial={{ height: 0 }}
- animate={{ height: 'auto' }}
- exit={{ height: 0 }}
- 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'>Keranjang Belanja</h5>
- <Link href='/shop/cart' class='text-sm font-medium text-red-600 underline'>
- Lihat Semua
- </Link>
- </div>
- <hr className='mt-3 mb-3 border border-gray-100' />
- <div className='flow-root max-h-[250px] overflow-y-auto'>
- {!auth && (
- <div className='justify-center p-4'>
- <p className='text-gray-500 text-center '>
- Silahkan{' '}
- <Link href='/login' className='text-red-600 underline leading-6'>
- Login
- </Link>{' '}
- Untuk Melihat Daftar Keranjang Belanja Anda
- </p>
- </div>
- )}
- {isLoading &&
- itemLoading.map((item) => (
- <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' />
- </div>
- <div className='flex-1 min-w-0'>
- <div className='h-2.5 bg-gray-200 rounded-full dark:bg-gray-700 w-48 mb-4'></div>
- <div className='h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px] mb-2.5'></div>
- <div className='h-2 bg-gray-200 rounded-full dark:bg-gray-700 mb-2.5'></div>
- </div>
- </div>
- </div>
- ))}
- {auth && products.length === 0 && !isLoading && (
- <div className='justify-center p-4'>
- <p className='text-gray-500 text-center '>
- Tidak Ada Produk di Keranjang Belanja Anda
- </p>
- </div>
- )}
- {auth && products.length > 0 && !isLoading && (
- <>
- <ul role='list' className='divide-y divide-gray-200 dark:divide-gray-700'>
- {products &&
- products?.map((product, index) => (
- <>
- <li className='py-1 sm:py-2'>
- <div className='flex items-center space-x-4'>
- <div className='bagian gambar flex-shrink-0'>
- {product.cartType === 'promotion' && (
- <Image
- src={product.imageProgram[0]}
- alt={product.name}
- className='object-contain object-center border border-gray_r-6 h-16 w-16 rounded-md'
- />
- )}
- {product.cartType === 'product' && (
- <Link
- href={createSlug(
- '/shop/product/',
- product?.parent.name,
- product?.parent.id
- )}
- className='line-clamp-2 leading-6 !text-gray_r-12 font-normal'
- >
- <Image
- src={product?.parent?.image}
- alt={product?.name}
- className='object-contain object-center border border-gray_r-6 h-16 w-16 rounded-md'
- />
- </Link>
- )}
- </div>
- <div className='bagian tulisan dan harga flex-1 min-w-0'>
- {product.cartType === 'promotion' && (
- <p className='text-caption-2 font-medium text-gray-900 truncate dark:text-white'>
- {product.name}
- </p>
- )}
- {product.cartType === 'product' && (
- <Link
- href={createSlug(
- '/shop/product/',
- product?.parent.name,
- product?.parent.id
- )}
- className='line-clamp-2 leading-6 !text-gray_r-12 font-normal'
- >
- {' '}
- <p className='text-caption-2 font-medium text-gray-900 truncate dark:text-white'>
- {product.parent.name}
- </p>
- </Link>
- )}
- {product?.hasFlashsale && (
- <div className='flex gap-x-1 items-center mb-2 mt-1'>
- <div className='badge-solid-red'>
- {product?.price?.discountPercentage}%
- </div>
- <div className='text-gray_r-11 line-through text-caption-2'>
- {currencyFormat(product?.price?.price)}
- </div>
- </div>
- )}
-
- <div className='flex justify-between items-center'>
- <div className='font-semibold text-sm text-red-600'>
- {product?.price?.priceDiscount > 0 ? (
- currencyFormat(product?.price?.priceDiscount)
- ) : (
- <span className='text-gray_r-12/90 font-normal text-caption-1'>
- <a
- href={whatsappUrl('product', {
- name: product.name,
- manufacture: product.manufacture?.name,
- url: createSlug(
- '/shop/product/',
- product.name,
- product.id,
- true
- )
- })}
- className='text-danger-500 underline'
- rel='noopener noreferrer'
- target='_blank'
- >
- Call For Price
- </a>
- </span>
- )}
- </div>
- </div>
- </div>
- </div>
- <div className="flex flex-col w-3/4">
- {product.products?.map((product) =>
- <div key={product.id} className='md:ml-8 ml-4 mt-2 flex'>
- <Link href={createSlug('/shop/product/', product.parent.name, product.parent.id.toString())} className='md:h-12 md:w-12 md:min-w-[48px] h-10 w-10 min-w-[40px] border border-gray-300 rounded '>
- {product?.image && <Image src={product.image} alt={product.name} width={40} height={40} className='w-full h-full object-fill' />}
- </Link>
-
- <div className="ml-4 w-full flex flex-col gap-y-1">
- <Link href={createSlug('/shop/product/', product.parent.name, product.parent.id.toString())} className="text-caption-2 font-medium text-gray-900 truncate dark:text-white">
- {product.displayName}
- </Link>
-
- <div className='flex w-full'>
- <div className="flex flex-col">
- {/* <div className="text-gray-500 text-caption-1">{product.code}</div> */}
- <div>
- <span className="text-gray-500 text-caption-1">Berat Barang: </span>
- <span className="text-gray-500 text-caption-1">{product.packageWeight} Kg</span>
- </div>
- </div>
- </div>
- </div>
-
- </div>
- )}
- {product.freeProducts?.map((product) =>
- <div key={product.id} className='md:ml-8 ml-4 mt-2 flex'>
- <Link href={createSlug('/shop/product/', product.parent.name, product.parent.id.toString())} className='md:h-12 md:w-12 md:min-w-[48px] h-10 w-10 min-w-[40px] border border-gray-300 rounded '>
- {product?.image && <Image src={product.image} alt={product.name} width={40} height={40} className='w-full h-full object-fill' />}
- </Link>
-
- <div className="ml-4 w-full flex flex-col gap-y-1">
- <Link href={createSlug('/shop/product/', product.parent.name, product.parent.id.toString())} className="text-caption-2 font-medium text-gray-900 truncate dark:text-white">
- {product.displayName}
- </Link>
-
- <div className='flex w-full'>
- <div className="flex flex-col">
- {/* <div className="text-gray-500 text-caption-1">{product.code}</div> */}
- <div>
- <span className="text-gray-500 text-caption-1">Berat Barang: </span>
- <span className="text-gray-500 text-caption-1">{product.packageWeight} Kg</span>
- </div>
- </div>
- </div>
- </div>
-
- </div>
- )}
- </div>
- </li>
- </>
- ))}
- </ul>
- <hr />
- </>
- )}
- </div>
- {auth && products.length > 0 && !isLoading && (
- <>
- <div className='mt-3'>
- <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
- type='button'
- className='btn-solid-red rounded-lg w-full'
- onClick={handleCheckout}
- disabled={buttonLoading}
- >
- {buttonLoading ? 'Loading...' : 'Lanjutkan Ke Pembayaran'}
- </button>
- </div>
- </>
- )}
- </motion.div>
- </motion.div>
- </>
- )}
- </AnimatePresence>
</div>
)
}
diff --git a/src/lib/category/api/popularProduct.js b/src/lib/category/api/popularProduct.js
deleted file mode 100644
index e17e0ae5..00000000
--- a/src/lib/category/api/popularProduct.js
+++ /dev/null
@@ -1,31 +0,0 @@
-
-export const fetchPromoItemsSolr = async (category_id_ids) => {
- let sort ='sort=qty_sold_f desc';
- try {
- const queryParams = new URLSearchParams({ q: category_id_ids });
- const response = await fetch(`/solr/product/select?${queryParams.toString()}&rows=2000&fl=manufacture_name_s,manufacture_id_i,id,display_name_s&${sort}`);
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- const data = await response.json();
- const promotions = await map(data.response.docs);
- return promotions;
- } catch (error) {
- console.error("Error fetching promotion data:", error);
- return [];
- }
- };
-
- const map = async (promotions) => {
- const result = [];
- for (const promotion of promotions) {
- const data = {
- id: promotion.id,
- name: promotion.display_name_s,
- manufacture_name: promotion.manufacture_name_s,
- manufacture_id: promotion.manufacture_id_i,
- };
- result.push(data);
- }
- return result;
- }; \ No newline at end of file
diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx
index ff958378..e6ea5acf 100644
--- a/src/lib/category/components/Category.jsx
+++ b/src/lib/category/components/Category.jsx
@@ -2,15 +2,10 @@ 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 { ChevronRightIcon } from '@heroicons/react/24/outline'
-import Image from 'next/image'
import { useEffect, useState } from 'react'
-import PopularBrand from './PopularBrand'
const Category = () => {
const [categories, setCategories] = useState([])
- const [openCategories, setOpenCategory] = useState([]);
-
useEffect(() => {
const loadCategories = async () => {
@@ -31,65 +26,46 @@ const Category = () => {
}
loadCategories()
}, [])
- // console.log("categories",categories)
return (
<DesktopView>
<div className='category-mega-box'>
{categories?.map((category) => (
- <div key={category.id} className='flex'>
+ <div key={category.id}>
<Link
href={createSlug('/shop/category/', category.name, category.id)}
- className='category-mega-box__parent flex items-center'
+ className='category-mega-box__parent'
>
- <div className='w-6 h-6 border mr-2 rounded-full flex justify-center items-center'>
- <Image src={category.image} alt='' width={16} height={16} />
- </div>
{category.name}
</Link>
<div className='category-mega-box__child-wrapper'>
- <div className='grid grid-cols-3 gap-x-4 gap-y-6 max-h-full !w-[590px] overflow-auto'>
+ <div className='grid grid-cols-3 gap-x-4 gap-y-6 max-h-full overflow-auto'>
{category.childs.map((child1Category) => (
- <div key={child1Category.id} className='w-full'>
+ <div key={child1Category.id}>
<Link
href={createSlug('/shop/category/', child1Category.name, child1Category.id)}
- className='category-mega-box__child-one mb-4 w-full h-8 flex justify-center line-clamp-2'
+ className='category-mega-box__child-one mb-4'
>
{child1Category.name}
</Link>
- <div className='flex flex-col gap-y-3 w-full'>
- {child1Category.childs.map((child2Category, index) => (
- (index < 4) && (
- <Link
- href={createSlug('/shop/category/', child2Category.name, child2Category.id)}
- className='category-mega-box__child-two truncate'
- key={child2Category.id}
- >
- {child2Category.name}
- </Link>
- )
+ <div className='flex flex-col gap-y-3'>
+ {child1Category.childs.map((child2Category) => (
+ <Link
+ href={createSlug(
+ '/shop/category/',
+ child2Category.name,
+ child2Category.id
+ )}
+ className='category-mega-box__child-two'
+ key={child2Category.id}
+ >
+ {child2Category.name}
+ </Link>
))}
- {child1Category.childs.length > 5 && (
- <div className='flex hover:bg-gray_r-8/35 rounded-10'>
- <Link
- href={createSlug('/shop/category/', child1Category.name, child1Category.id)}
- className='category-mega-box__child-one flex items-center gap-4 font-bold hover:ml-4'
- >
- <p className='mt-2 mb-0 text-danger-500 font-semibold'>Lihat Semua</p>
- <ChevronRightIcon className='w-4 text-danger-500 font-bold' />
- </Link>
- </div>
- )}
</div>
</div>
))}
</div>
- <div className='category-mega-box__child-wrapper !w-[260px] !flex !flex-col !gap-4'>
- <PopularBrand category={category} />
- <div className='flex w-60 h-20 object-cover'>
- <Image src='https://erp.indoteknik.com/api/image/x_banner.banner/x_banner_image/397' alt='' width={275} height={4} />
- </div>
- </div>
</div>
</div>
))}
diff --git a/src/lib/category/components/PopularBrand.jsx b/src/lib/category/components/PopularBrand.jsx
deleted file mode 100644
index 09c0f8a1..00000000
--- a/src/lib/category/components/PopularBrand.jsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import odooApi from '@/core/api/odooApi'
-import React, { useEffect, useState } from 'react'
-import axios from 'axios';
-import { useQuery } from 'react-query'
-import Link from '@/core/components/elements/Link/Link'
-import { createSlug } from '@/core/utils/slug'
-import Image from 'next/image'
-import { ChevronRightIcon } from '@heroicons/react/24/outline'
-import useProductSearch from '../../../lib/product/hooks/useProductSearch';
-import { SolrResponse } from "~/types/solr";
-import { fetchPromoItemsSolr } from '../api/popularProduct'
-
-const SOLR_HOST = process.env.SOLR_HOST
-
-const PopularBrand = ({ category }) => {
- const [topBrands, setTopBrands] = useState([]);
-
- const fetchTopBrands = async () => {
- try {
- const items = await fetchPromoItemsSolr(`category_id_ids:(${category?.categoryDataIds?.join(' OR ')})`);
- // console.log("id",items)
- // Fungsi untuk deduplikasi dan mengambil 12 nama brand teratas
- const getTop12UniqueBrands = (prod) => {
- const brandSet = new Set();
- const topBrands = [];
-
- for (const product of prod) {
- if (!brandSet.has(product.manufacture_name)) {
- brandSet.add(product.manufacture_name);
- topBrands.push({ name: product.manufacture_name, id: product.manufacture_id });
- }else{
- }
- if (topBrands.length === 18) break;
- }
- return topBrands;
- }
-
- // Menggunakan hasil pencarian produk
- const products = items;
- const top12UniqueBrands = getTop12UniqueBrands(products);
-
- // console.log('top12UniqueBrands', top12UniqueBrands);
- setTopBrands(top12UniqueBrands);
- } catch (error) {
- console.error("Error fetching data from Solr", error);
- throw error;
- }
- }
-
- useEffect(() => {
- fetchTopBrands();
- }, [category]);
-
- return (
- <div className='flex flex-col'>
- <div className='grid grid-cols-3 max-h-full w-full gap-2'>
- {topBrands.map((brand, index) => (
- <div key={index} className='w-full flex items-center justify-center pb-2'>
- <Link
- href={createSlug('/shop/brands/', brand.name, brand.id)}
- className='category-mega-box__child-one w-8 h-full flex items-center justify-center '
- >
- <Image src={`https://erp.indoteknik.com/api/image/x_manufactures/x_logo_manufacture/${brand.id}` } alt={`${brand.name}`} width={104} height={44} objectFit='cover' />
- </Link>
- </div>
- ))}
- </div>
- {/* {topBrands.length > 8 && (
- <div className='flex hover:bg-gray_r-8/35 rounded-10'>
- <Link
- href={createSlug('/shop/category/', category.name, category.id)}
- className='category-mega-box__child-one flex items-center gap-4 font-bold hover:ml-4'
- >
- <p className='mt-2 mb-0 text-danger-500 font-semibold'>Lihat Semua Brand</p>
- <ChevronRightIcon className='w-4 text-danger-500 font-bold' />
- </Link>
- </div>
- )} */}
- </div>
- )
-}
-
-export default PopularBrand;
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 6deba693..09a791ee 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -1004,7 +1004,7 @@ const Checkout = () => {
<div className='p-4 flex flex-col gap-y-4'>
{!!products &&
snakecaseKeys(products).map((item, index) => (
- <CartItem key={index} item={item} editable={false} selfPicking={selectedExpedisi === '1,32' ? true : false}/>
+ <CartItem key={index} item={item} editable={false} />
))}
</div>
@@ -1295,7 +1295,7 @@ const Checkout = () => {
<div className='flex flex-col gap-y-8 border-t border-gray-300 pt-8'>
{!!products &&
snakecaseKeys(products).map((item, index) => (
- <CartItem key={index} item={item} editable={false} selfPicking={selectedExpedisi === '1,32' ? true : false} />
+ <CartItem key={index} item={item} editable={false} />
))}
</div>
</div>
diff --git a/src/lib/flashSale/components/FlashSale.jsx b/src/lib/flashSale/components/FlashSale.jsx
index 5be6d4e3..85afb818 100644
--- a/src/lib/flashSale/components/FlashSale.jsx
+++ b/src/lib/flashSale/components/FlashSale.jsx
@@ -26,38 +26,41 @@ const FlashSale = () => {
}
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 className='sm:mt-4'>
+ {flashSales?.length > 0 && (
+ <div className='px-4 sm:px-0 grid grid-cols-1 gap-y-8 sm:mt-4'>
+ {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}
+ width={1080}
+ height={192}
+ className='w-full rounded mb-4 hidden sm:block'
+ />
+ <Image
+ src={flashSale.bannerMobile}
+ alt={flashSale.name}
+ width={256}
+ height={48}
+ className='w-full rounded mb-4 block sm:hidden'
+ />
+ <FlashSaleProduct flashSaleId={flashSale.pricelistId} />
</div>
- <CountDown initialTime={flashSale.duration} />
- </div>
-
- <div className='relative'>
- <Image
- src={flashSale.banner}
- alt={flashSale.name}
- width={1080}
- height={192}
- className='w-full rounded mb-4 hidden sm:block'
- />
- <Image
- src={flashSale.bannerMobile}
- alt={flashSale.name}
- width={256}
- height={48}
- className='w-full rounded mb-4 block sm:hidden'
- />
- <FlashSaleProduct flashSaleId={flashSale.pricelistId} />
</div>
- </div>
- ))}
- </div>
- )
+ ))}
+ </div>
+ )}
+
+ </div>
);
};
diff --git a/src/lib/flashSale/components/FlashSaleNonDisplay.jsx b/src/lib/flashSale/components/FlashSaleNonDisplay.jsx
index 0068c98d..6e379500 100644
--- a/src/lib/flashSale/components/FlashSaleNonDisplay.jsx
+++ b/src/lib/flashSale/components/FlashSaleNonDisplay.jsx
@@ -13,21 +13,19 @@ import { useRouter } from 'next/router'
const FlashSaleNonDisplay = () => {
const [flashSales, setFlashSales] = useState(null);
const [isLoading, setIsLoading] = useState(true);
- const [pencarian, setPencarian] = useState('');
const router = useRouter()
useEffect(() => {
const loadFlashSales = async () => {
const dataFlashSales = await flashSaleApi();
setFlashSales(dataFlashSales);
- setPencarian(`fq=-flashsale_id_i:${dataFlashSales[0]?.pricelistId}&fq=flashsale_price_f:[1 TO *]&orderBy=flashsale-discount-desc`)
setIsLoading(false);
};
loadFlashSales();
}, []);
const handleSubmit = () => {
- router.push(`/shop/search?${pencarian}`)
+ router.push(`/shop/search?penawaran=${flashSales[0]?.pricelistId}`)
}
if (isLoading) {
diff --git a/src/lib/home/api/CategoryPilihanApi.js b/src/lib/home/api/CategoryPilihanApi.js
deleted file mode 100644
index 8a0b38d3..00000000
--- a/src/lib/home/api/CategoryPilihanApi.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import odooApi from '@/core/api/odooApi'
-
-const categoryPilihanApi = async () => {
- const dataCategoryPilihan = await odooApi('GET', '/api/v1/lob_homepage')
- return dataCategoryPilihan
-}
-
-export default categoryPilihanApi
diff --git a/src/lib/home/api/categoryManagementApi.js b/src/lib/home/api/categoryManagementApi.js
deleted file mode 100644
index b70d60ce..00000000
--- a/src/lib/home/api/categoryManagementApi.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import odooApi from '@/core/api/odooApi'
-
-const categoryManagementApi = async () => {
- const dataCategoryManagement = await odooApi('GET', '/api/v1/categories_management')
- return dataCategoryManagement
-}
-
-export default categoryManagementApi
diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx
deleted file mode 100644
index 0cc43d91..00000000
--- a/src/lib/home/components/CategoryDynamic.jsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import useCategoryManagement from '../hooks/useCategoryManagement';
-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'
-
-const CategoryDynamic = () => {
- const { categoryManagement } = useCategoryManagement();
- const [categoryData, setCategoryData] = useState({});
- const [subCategoryData, setSubCategoryData] = useState({});
-
- useEffect(() => {
- const fetchCategoryData = async () => {
- if (categoryManagement && categoryManagement.data) {
- const updatedCategoryData = {};
- const updatedSubCategoryData = {};
-
- for (const category of categoryManagement.data) {
- const countLevel1 = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.categoryIdI}`);
-
- updatedCategoryData[category.categoryIdI] = countLevel1?.numFound;
-
- for (const subCategory of countLevel1.children) {
- updatedSubCategoryData[subCategory.id] = subCategory.numFound;
- }
- }
-
- setCategoryData(updatedCategoryData);
- setSubCategoryData(updatedSubCategoryData);
- }
- };
-
- fetchCategoryData();
- }, [categoryManagement.isLoading]);
-
- return (
- <div>
- {categoryManagement && categoryManagement.data?.map((category) => {
- const countLevel1 = categoryData[category.categoryIdI] || 0;
-
- return (
- <Skeleton key={category.id} isLoaded={categoryManagement}>
- <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'>{category.name}</div>
- <Skeleton isLoaded={countLevel1 !=0}>
- <p className={`text-gray_r-10 text-sm`}>{countLevel1} Produk tersedia</p>
- </Skeleton>
- <Link href={createSlug('/shop/category/', category?.name, category?.categoryIdI)} className="!text-red-500 font-semibold">Lihat Semua</Link>
- </div>
- <div className='grid grid-cols-3 gap-2'>
- {category.categories.map((subCategory) => {
- const countLevel2 = subCategoryData[subCategory.idLevel2] || 0;
-
- return (
- <div key={subCategory.id} className='border rounded justify-start items-start'>
- <div className='p-3'>
- <div className='flex flex-row border rounded mb-2 justify-start items-center'>
- <NextImage
- src={subCategory.image ? subCategory.image : "/images/noimage.jpeg"}
- alt={subCategory.name}
- width={90}
- height={30}
- className='object-fit'
- />
- <div className='bagian-judul flex flex-col justify-center items-start gap-2 ml-2'>
- <div className='font-semibold text-lg mr-2'>{subCategory.name}</div>
- <Skeleton isLoaded={countLevel2 != 0}>
- <p className={`text-gray_r-10 text-sm`}>
- {countLevel2} Produk tersedia
- </p>
- </Skeleton>
- <Link href={createSlug('/shop/category/', subCategory?.name, subCategory?.idLevel2)} className="!text-red-500 font-semibold">Lihat Semua</Link>
- </div>
- </div>
- <div className='grid grid-cols-2 gap-2 overflow-y-auto max-h-[240px]'>
- {subCategory.childFrontendIdI.map((childCategory) => (
- <div key={childCategory.id}>
- <Link href={createSlug('/shop/category/', childCategory?.name, childCategory?.idLevel3)} className="flex flex-row gap-2 border rounded group hover:border-red-500">
- <NextImage
- src={childCategory.image ? childCategory.image : "/images/noimage.jpeg"}
- alt={childCategory.name}
- width={40}
- 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'>{childCategory.name}</div>
- </div>
- </Link>
- </div>
- ))}
- </div>
- </div>
- </div>
- );
- })}
- </div>
- </div>
- </Skeleton>
- );
- })}
- </div>
- );
-};
-
-export default CategoryDynamic;
diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx
deleted file mode 100644
index c1433a2d..00000000
--- a/src/lib/home/components/CategoryDynamicMobile.jsx
+++ /dev/null
@@ -1,101 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import useCategoryManagement from '../hooks/useCategoryManagement';
-import NextImage from 'next/image';
-import Link from "next/link";
-import { createSlug } from '@/core/utils/slug';
-import { Swiper, SwiperSlide } from 'swiper/react';
-import 'swiper/css';
-
-const CategoryDynamicMobile = () => {
- const { categoryManagement } = useCategoryManagement()
- const [selectedCategory, setSelectedCategory] = useState({});
-
- useEffect(() => {
- const loadPromo = async () => {
- try {
- if (categoryManagement.data?.length > 0) {
- const initialSelections = categoryManagement.data.reduce((acc, category) => {
- if (category.categories.length > 0) {
- acc[category.id] = category.categories[0].idLevel2;
- }
- return acc;
- }, {});
- setSelectedCategory(initialSelections);
- }
- } catch (loadError) {
- // console.error("Error loading promo items:", loadError);
- }
- };
-
- loadPromo();
- }, [categoryManagement.data]);
-
- const handleCategoryLevel2Click = (categoryIdI, idLevel2) => {
- setSelectedCategory(prev => ({
- ...prev,
- [categoryIdI]: idLevel2
- }));
- };
-
- return (
- <div className='p-4'>
- {categoryManagement.data && categoryManagement.data.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>
- <Link href={createSlug('/shop/category/', category?.name, category?.categoryIdI)} className="!text-red-500 font-semibold text-sm">Lihat Semua</Link>
- </div>
- <Swiper slidesPerView={2.3} spaceBetween={10}>
- {category.categories.map((index) => (
- <SwiperSlide key={index.id}>
- <div
- onClick={() => handleCategoryLevel2Click(category.id, index?.idLevel2)}
- className={`border flex justify-start items-center max-w-48 max-h-16 rounded ${selectedCategory[category.id] === index?.idLevel2 ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`}
- >
- <div className='p-1 flex justify-start items-center'>
- <div className='flex flex-row justify-center items-center'>
- <NextImage
- src={index.image ? index.image : "/images/noimage.jpeg"}
- alt={index.name}
- width={30}
- height={30}
- className='object-'
- />
- <div className='bagian-judul flex flex-col justify-center items-start gap-1 ml-2'>
- <div className='font-semibold text-[10px] line-clamp-1'>{index.name}</div>
- <p className='text-gray_r-10 text-[10px]'>999 rb+ Produk</p>
- </div>
- </div>
- </div>
- </div>
- </SwiperSlide>
- ))}
- </Swiper>
- <div className='p-3 mt-2 border'>
- <div className='grid grid-cols-2 gap-2 overflow-y-auto max-h-[240px]'>
- {category.categories.map((index) => (
- selectedCategory[category.id] === index?.idLevel2 && index.childFrontendIdI.map((x) => (
- <div key={x.id}>
- <Link href={createSlug('/shop/category/', x?.name, x?.idLevel3)} className="flex flex-row gap-1 border rounded group hover:border-red-500">
- <NextImage
- src={x.image ? x.image : "/images/noimage.jpeg"}
- alt={x.name}
- width={40}
- height={40}
- />
- <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]'>{x.name}</div>
- </div>
- </Link>
- </div>
- ))
- ))}
- </div>
- </div>
- </div>
- ))}
- </div>
- );
-};
-
-export default CategoryDynamicMobile;
diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx
deleted file mode 100644
index 6568621c..00000000
--- a/src/lib/home/components/CategoryPilihan.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-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')
-import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton';
-import useCategoryPilihan from '../hooks/useCategoryPilihan';
-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 (
- <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>
- ))}
- </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={100}
- 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='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>
- )
-}
-
-export default CategoryPilihan
diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx
index ae12505d..6b64a444 100644
--- a/src/lib/home/components/PreferredBrand.jsx
+++ b/src/lib/home/components/PreferredBrand.jsx
@@ -1,5 +1,4 @@
import { Swiper, SwiperSlide } from 'swiper/react'
-import { Navigation, Pagination, Autoplay } from 'swiper';
import { useCallback, useEffect, useState } from 'react'
import usePreferredBrand from '../hooks/usePreferredBrand'
import PreferredBrandSkeleton from './Skeleton/PreferredBrandSkeleton'
@@ -39,23 +38,7 @@ const PreferredBrand = () => {
const { preferredBrands } = usePreferredBrand(query)
const { isMobile, isDesktop } = useDevice()
- const swiperBanner = {
- modules:[Navigation, Pagination, Autoplay],
- autoplay: {
- delay: 4000,
- disableOnInteraction: false
- },
- loop: true,
- className: 'h-[70px] md:h-[100px] w-full',
- slidesPerView: isMobile ? 4 : 8,
- spaceBetween: isMobile ? 12 : 0,
- pagination: {
- dynamicBullets: true,
- dynamicMainBullets: isMobile ? 6 : 8,
- clickable: true,
- }
- }
- const preferredBrandsData = manufactures ? manufactures.slice(0, 20) : []
+
return (
<div className='px-4 sm:px-0'>
<div className='flex justify-between items-center mb-4'>
@@ -65,21 +48,24 @@ const PreferredBrand = () => {
Lihat Semua
</Link>
)}
- </div>
- <div className='border rounded border-gray_r-6'>
- {manufactures.isLoading && <PreferredBrandSkeleton />}
- {!manufactures.isLoading && (
- <Swiper {...swiperBanner}>
- {preferredBrandsData.map((manufacture) => (
- <SwiperSlide key={manufacture.id}>
- <BrandCard brand={manufacture} />
- </SwiperSlide>
- ))}
- </Swiper>
+ {isMobile && (
+ <Link href='/shop/brands' className='!text-red-500 font-semibold sm:text-h-sm'>
+ Lihat Semua
+ </Link>
)}
</div>
+ {manufactures.isLoading && <PreferredBrandSkeleton />}
+ {!manufactures.isLoading && (
+ <Swiper slidesPerView={isMobile ? 3.5 : 7.5} spaceBetween={isMobile ? 12 : 24} freeMode>
+ {manufactures.map((manufacture) => (
+ <SwiperSlide key={manufacture.id}>
+ <BrandCard brand={manufacture} />
+ </SwiperSlide>
+ ))}
+ </Swiper>
+ )}
</div>
)
}
-export default PreferredBrand \ No newline at end of file
+export default PreferredBrand
diff --git a/src/lib/home/components/PromotionProgram.jsx b/src/lib/home/components/PromotionProgram.jsx
index c2f76069..99258d94 100644
--- a/src/lib/home/components/PromotionProgram.jsx
+++ b/src/lib/home/components/PromotionProgram.jsx
@@ -3,16 +3,11 @@ import Image from 'next/image'
import { bannerApi } from '@/api/bannerApi';
import useDevice from '@/core/hooks/useDevice'
import { Swiper, SwiperSlide } from 'swiper/react';
-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()
- if (promotionProgram.isLoading) {
- return <BannerPromoSkeleton />;
- }
-
return (
<div className='px-4 sm:px-0'>
<div className='flex justify-between items-center mb-4 '>
diff --git a/src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx b/src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx
deleted file mode 100644
index c5f39f19..00000000
--- a/src/lib/home/components/Skeleton/BannerPromoSkeleton.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import useDevice from '@/core/hooks/useDevice'
-import Skeleton from 'react-loading-skeleton'
-
-const BannerPromoSkeleton = () => {
- const { isDesktop } = useDevice()
-
- return (
- <div className='grid grid-cols-1 md:grid-cols-3 gap-x-3'>
- {Array.from({ length: isDesktop ? 3 : 1.2 }, (_, index) => (
- <Skeleton count={1} height={isDesktop ? 60 : 36} key={index} />
- ))}
- </div>
- )
-}
-
-export default BannerPromoSkeleton
diff --git a/src/lib/home/hooks/useCategoryManagement.js b/src/lib/home/hooks/useCategoryManagement.js
deleted file mode 100644
index c1dda585..00000000
--- a/src/lib/home/hooks/useCategoryManagement.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import categoryManagementApi from '../api/categoryManagementApi'
-import { useQuery } from 'react-query'
-
-const useCategoryManagement = () => {
- const fetchCategoryManagement = async () => await categoryManagementApi()
- const { isLoading, data } = useQuery('categoryManagementApi', fetchCategoryManagement)
-
- return {
- categoryManagement: { data, isLoading }
- }
-}
-
-export default useCategoryManagement \ No newline at end of file
diff --git a/src/lib/home/hooks/useCategoryPilihan.js b/src/lib/home/hooks/useCategoryPilihan.js
deleted file mode 100644
index 12a86f7e..00000000
--- a/src/lib/home/hooks/useCategoryPilihan.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import categoryPilihanApi from '../api/CategoryPilihanApi'
-import { useQuery } from 'react-query'
-
-const useCategoryPilihan = () => {
- const fetchCategoryPilihan = async () => await categoryPilihanApi()
- const { isLoading, data } = useQuery('categoryPilihanApi', fetchCategoryPilihan)
-
- return {
- categoryPilihan: { data, isLoading }
- }
-}
-
-export default useCategoryPilihan \ No newline at end of file
diff --git a/src/lib/lob/components/Breadcrumb.jsx b/src/lib/lob/components/Breadcrumb.jsx
deleted file mode 100644
index 5722fd39..00000000
--- a/src/lib/lob/components/Breadcrumb.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import odooApi from '@/core/api/odooApi'
-import { createSlug } from '@/core/utils/slug'
-import {
- Breadcrumb as ChakraBreadcrumb,
- BreadcrumbItem,
- BreadcrumbLink,
- Skeleton
-} from '@chakra-ui/react'
-import Link from 'next/link'
-import React from 'react'
-import { useQuery } from 'react-query'
-
-/**
- * Render a breadcrumb component.
- *
- * @param {object} categoryId - The ID of the category.
- * @return {JSX.Element} The breadcrumb component.
- */
-const Breadcrumb = ({ categoryId }) => {
- const breadcrumbs = useQuery(
- `lob-breadcrumbs/${categoryId}`,
- async () => await odooApi('GET', `/api/v1/lob_homepage/${categoryId}/category_id`)
- )
- return (
- <div className='container mx-auto py-4 md:py-6'>
- <Skeleton isLoaded={!breadcrumbs.isLoading} className='w-2/3'>
- <ChakraBreadcrumb>
- <BreadcrumbItem>
- <BreadcrumbLink as={Link} href='/' className='!text-danger-500 whitespace-nowrap'>
- Home
- </BreadcrumbLink>
- </BreadcrumbItem>
-
- {breadcrumbs?.data?.map((category, index) => (
- <BreadcrumbItem key={index} isCurrentPage={index === breadcrumbs.data.length - 1}>
- {index === breadcrumbs.data.length - 1 ? (
- <BreadcrumbLink className='whitespace-nowrap'>{category.industries}</BreadcrumbLink>
- ) : (
- <BreadcrumbLink
- as={Link}
- href={createSlug('/shop/lob/', category.industries, category.id)}
- className='!text-danger-500 whitespace-nowrap'
- >
- {category.industries}
- </BreadcrumbLink>
- )}
- </BreadcrumbItem>
- ))}
- </ChakraBreadcrumb>
- </Skeleton>
- </div>
- )
-}
-
-export default Breadcrumb
diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx
deleted file mode 100644
index 2af3db10..00000000
--- a/src/lib/product/components/CategorySection.jsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import Image from "next/image";
-import Link from 'next/link';
-import { createSlug } from '@/core/utils/slug';
-import useDevice from '@/core/hooks/useDevice';
-import { Swiper, SwiperSlide } from 'swiper/react';
-import 'swiper/css';
-import { useQuery } from 'react-query';
-import { useRouter } from 'next/router';
-import {
- ChevronDownIcon,
- ChevronUpIcon, // Import ChevronUpIcon for toggling
- DocumentCheckIcon,
- HeartIcon,
-} from '@heroicons/react/24/outline';
-import { useState } from 'react'; // Import useState
-import { getIdFromSlug } from '@/core/utils/slug'
-
-const CategorySection = ({ categories }) => {
- const { isDesktop, isMobile } = useDevice();
- const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility
-
- const handleToggleCategories = () => {
- setIsOpenCategory(!isOpenCategory);
- };
-
-
- const displayedCategories = isOpenCategory ? categories : categories.slice(0, 10);
-
- return (
- <section>
- {isDesktop && (
- <div className="group/item grid grid-cols-5 gap-y-2 gap-x-2 w-full h-full col-span-2 ">
- {displayedCategories.map((category) => (
- <Link href={createSlug('/shop/category/', category?.name, category?.id)} key={category?.id} passHref>
- <div className="group transition-colors duration-300 ">
- <div className="KartuInti h-12 w-26 max-w-sm lg:max-w-full flex flex-col border-[2px] border-gray-200 group-hover:border-red-400 rounded relative ">
- <div className="flex items-center justify-start h-full px-1 flex-row ">
- <Image className="h-full" src={category?.image1920 ? category?.image1920 : '/images/noimage.jpeg'} width={56} height={48} alt={category?.name} />
- <h2 className="text-gray-700 group-hover:text-[#E20613] line-clamp-2 content-center h-fit w-60 px-1 font-semibold text-sm text-start">{category?.name}</h2>
- </div>
- </div>
- </div>
- </Link>
- ))}
- </div>
- )}
- {isDesktop && categories.length > 10 && (
- <div className="w-full flex justify-center mt-4">
- <button
- onClick={handleToggleCategories}
- className="flex justify-end mt-4 text-red-500 font-bold px-4 py-2 rounded"
- >
- {isOpenCategory ? 'Sembunyikan' : 'Lihat semua'}
- {isOpenCategory ? (
- <ChevronUpIcon className="ml-auto w-5 font-bold" />
- ) : (
- <ChevronDownIcon className="ml-auto w-5 font-bold" />
- )}
- </button>
- </div>
- )}
-
- {isMobile && (
- <div className="py-4">
- <Swiper slidesPerView={2.3} spaceBetween={10}>
- {displayedCategories.map((category) => (
- <SwiperSlide key={category?.id}>
- <Link href={createSlug('/shop/category/', category?.name, category?.id)} passHref>
- <div className="group transition-colors duration-300">
- <div className="KartuInti min-h-16 max-h-16 w-26 max-w-sm lg:max-w-full flex flex-col border-[2px] border-gray-200 group-hover:bg-red-200 group-hover:border-red-400 rounded relative">
- <div className="flex items-center justify-center h-full px-1 flex-row">
- <Image
- src={category?.image1920 ? category?.image1920 : '/images/noimage.jpeg'}
- width={56}
- height={48}
- alt={category?.name}
- />
- <h2 className="text-gray-700 group-hover:text-[#E20613] line-clamp-2 content-center h-fit w-60 px-1 font-semibold text-sm text-start">
- {category?.name}
- </h2>
- </div>
- </div>
- </div>
- </Link>
- </SwiperSlide>
- ))}
- </Swiper>
- {categories.length > 10 && (
- <div className="w-full flex justify-end mt-4">
- <button
- onClick={handleToggleCategories}
- className="flex justify-end mt-4 bg-red-500 text-white text-sm px-4 py-2 rounded"
- >
- {isOpenCategory ? 'Sembunyikan Semua' : 'Lihat Semua'}
- </button>
- </div>
- )}
- </div>
- )}
- </section>
- )
-}
-
-export default CategorySection
diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx
deleted file mode 100644
index 03d6e8c0..00000000
--- a/src/lib/product/components/LobSectionCategory.jsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import Image from "next/image";
-import Link from 'next/link';
-import { createSlug } from '@/core/utils/slug';
-import useDevice from '@/core/hooks/useDevice';
-import { Swiper, SwiperSlide } from 'swiper/react';
-import 'swiper/css';
-import { useQuery } from 'react-query';
-import { useRouter } from 'next/router';
-import {
- ChevronDownIcon,
- ChevronUpIcon, // Import ChevronUpIcon for toggling
- DocumentCheckIcon,
- HeartIcon,
-} from '@heroicons/react/24/outline';
-import { useState } from 'react'; // Import useState
-import { getIdFromSlug } from '@/core/utils/slug'
-
-const LobSectionCategory = ({ categories }) => {
- const { isDesktop, isMobile } = useDevice();
- const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility
-
- const handleToggleCategories = () => {
- setIsOpenCategory(!isOpenCategory);
- };
-
- const displayedCategories = categories[0]?.categoryIds;
-
- return (
- <section>
- {isDesktop && (
- <div className="group/item grid grid-flow-col gap-y-2 gap-x-4 w-full h-full">
- {displayedCategories?.map((category) => (
- <Link
- href={createSlug('/shop/category/', category?.name, category?.id)}
- key={category?.id}
- passHref
- className="block hover:scale-105 transition-transform duration-300 bg-cover bg-center h-[144px]"
- style={{
- backgroundImage: `url('${category?.image ? category?.image : 'https://erp.indoteknik.com/web/image?model=x_banner.banner&id=5&field=x_banner_image&unique=09202023100557'}')`,
- }}
- >
- </Link>
- ))}
- </div>
- )}
-
- {isMobile && (
- <div className="py-4">
- <Swiper slidesPerView={1.2} spaceBetween={10}>
- {displayedCategories?.map((category) => (
- <SwiperSlide key={category?.id}>
- <Link
- href={createSlug('/shop/category/', category?.name, category?.id)}
- key={category?.id}
- passHref
- className="block bg-cover bg-center h-[144px]"
- style={{
- backgroundImage: `url('${category?.image ? category?.image : 'https://erp.indoteknik.com/web/image?model=x_banner.banner&id=5&field=x_banner_image&unique=09202023100557'}')`,
- }}
- >
- </Link>
- </SwiperSlide>
- ))}
- </Swiper>
- {categories.length > 10 && (
- <div className="w-full flex justify-end mt-4">
- <button
- onClick={handleToggleCategories}
- className="flex justify-end mt-4 bg-red-500 text-white text-sm px-4 py-2 rounded"
- >
- {isOpenCategory ? 'Sembunyikan Semua' : 'Lihat Semua'}
- </button>
- </div>
- )}
- </div>
- )}
- </section>
- )
-}
-
-export default LobSectionCategory
diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx
index c8a5a205..09b30a44 100644
--- a/src/lib/product/components/Product/ProductDesktopVariant.jsx
+++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx
@@ -6,11 +6,6 @@ import { useRouter } from 'next/router';
import { useCallback, useEffect, useRef, useState } from 'react';
import { toast } from 'react-hot-toast';
import LazyLoad from 'react-lazy-load';
-import { Button } from '@chakra-ui/react'
-import { MessageCircleIcon, Share2Icon } from 'lucide-react'
-import AddToWishlist from '../../../../../src-migrate/modules/product-detail/components/AddToWishlist'
-import { RWebShare } from 'react-web-share'
-// import Link from 'next/link'
import { useProductCartContext } from '@/contexts/ProductCartContext';
import odooApi from '@/core/api/odooApi';
@@ -23,14 +18,11 @@ import { updateItemCart } from '@/core/utils/cart';
import currencyFormat from '@/core/utils/currencyFormat';
import { createSlug } from '@/core/utils/slug';
import whatsappUrl from '@/core/utils/whatsappUrl';
-import Breadcrumb from '../../../../../src-migrate/modules/product-detail/components/Breadcrumb';
import productSimilarApi from '../../api/productSimilarApi';
import ProductCard from '../ProductCard';
import ProductSimilar from '../ProductSimilar';
-const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST
-
const ProductDesktopVariant = ({
product,
wishlist,
@@ -40,7 +32,7 @@ const ProductDesktopVariant = ({
const router = useRouter();
const auth = useAuth();
const { slug } = router.query;
- const [ askAdminUrl, setAskAdminUrl ] = useState()
+
const [lowestPrice, setLowestPrice] = useState(null);
const [addCartAlert, setAddCartAlert] = useState(false);
@@ -61,20 +53,6 @@ const ProductDesktopVariant = ({
setLowestPrice(lowest);
}, [getLowestPrice]);
- useEffect(() => {
- const createdAskUrl = whatsappUrl({
- template: 'product',
- payload: {
- manufacture: product.manufacture.name,
- productName: product.name,
- url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath
- },
- fallbackUrl: router.asPath
- })
-
- setAskAdminUrl(createdAskUrl)
- }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl])
-
const [informationTab, setInformationTab] = useState(
informationTabOptions[0].value
);
@@ -137,25 +115,20 @@ const ProductDesktopVariant = ({
});
}
};
- const regex = /\b(?![A-Z\s]+\b)[A-Za-z\s]+\b/g;
- const matches = product?.parent?.name?.match(regex);
- const extractedName = matches ? matches.join(' ').trim() : '';
- console.log("extractedName",extractedName)
const productSimilarQuery = [
product?.name,
`fq=-product_id_i:${product.id}`,
`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}`,
- `fq=display_name_s:${extractedName}`,
].join('&');
const dataProductSimilar = await productSimilarApi({
query: productSimilarQuery,
@@ -181,7 +154,6 @@ const ProductDesktopVariant = ({
return (
<DesktopView>
<div className='container mx-auto pt-10'>
- <Breadcrumb id={product.id} name={product.parent.name} />
<div className='flex'>
<div className='w-full flex flex-wrap'>
<div className='w-5/12'>
@@ -291,42 +263,9 @@ const ProductDesktopVariant = ({
</div>
</div>
</div>
- <div className='h-6' />
- <div className="flex gap-x-5">
- <Button
- as={Link}
- href={askAdminUrl}
- variant='link'
- target='_blank'
- colorScheme='gray'
- leftIcon={<MessageCircleIcon size={18} />}
- >
- Ask Admin
- </Button>
-
- <AddToWishlist productId={product.id} />
-
- <RWebShare
- data={{
- text: 'Check out this product',
- title: `${product.name} - Indoteknik.com`,
- url: SELF_HOST + router.asPath
- }}
- >
- <Button
- variant='link'
- colorScheme='gray'
- leftIcon={<Share2Icon size={18} />}
- >
- Share
- </Button>
- </RWebShare>
- </div>
</div>
-
-
- <div className='p-4 md:p-6 md:bg-gray-50 rounded-xl w-[99%]'>
+ <div className='p-4 md:p-6 md:bg-gray-50 rounded-xl'>
<h2 className='text-h-md md:text-h-lg font-medium'>Informasi Produk</h2>
<div className='h-4' />
<div
@@ -340,7 +279,7 @@ const ProductDesktopVariant = ({
/>
</div>
</div>
- <div className='w-[35%]'>
+ <div className='w-[25%]'>
{product?.isFlashsale > 0 &&
product?.price?.discountPercentage > 0 ? (
<>
@@ -420,11 +359,24 @@ const ProductDesktopVariant = ({
Beli
</button>
</div>
+ <div className='flex mt-4'>
+ <button
+ className='flex items-center gap-x-1'
+ onClick={toggleWishlist}
+ >
+ {wishlist.data?.productTotal > 0 ? (
+ <HeartIcon className='w-6 fill-danger-500 text-danger-500' />
+ ) : (
+ <HeartIcon className='w-6' />
+ )}
+ 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-[500px]'>
+ <div className='h-full divide-y divide-gray_r-6 max-h-96'>
{productSimilarInBrand &&
productSimilarInBrand?.map((product) => (
<div className='py-2' key={product.id}>
diff --git a/src/lib/product/components/Product/ProductMobileVariant.jsx b/src/lib/product/components/Product/ProductMobileVariant.jsx
index ce836d5b..af9e52bb 100644
--- a/src/lib/product/components/Product/ProductMobileVariant.jsx
+++ b/src/lib/product/components/Product/ProductMobileVariant.jsx
@@ -16,14 +16,8 @@ import currencyFormat from '@/core/utils/currencyFormat';
import { gtagAddToCart } from '@/core/utils/googleTag';
import { createSlug } from '@/core/utils/slug';
import whatsappUrl from '@/core/utils/whatsappUrl';
-import Breadcrumb from '../../../../../src-migrate/modules/product-detail/components/Breadcrumb';
-import { Button } from '@chakra-ui/react'
-import { MessageCircleIcon, Share2Icon } from 'lucide-react'
-import AddToWishlist from '../../../../../src-migrate/modules/product-detail/components/AddToWishlist'
-import { RWebShare } from 'react-web-share'
-import ProductSimilar from '../ProductSimilar';
-const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST
+import ProductSimilar from '../ProductSimilar';
const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
const router = useRouter();
@@ -34,7 +28,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
informationTabOptions[0].value
);
const [addCartAlert, setAddCartAlert] = useState(false);
- const [ askAdminUrl, setAskAdminUrl ] = useState()
+
const [isLoadingSLA, setIsLoadingSLA] = useState(true);
const getLowestPrice = () => {
@@ -66,20 +60,6 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
}
}, [selectedVariant, product]);
- useEffect(() => {
- const createdAskUrl = whatsappUrl({
- template: 'product',
- payload: {
- manufacture: product.manufacture.name,
- productName: product.name,
- url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath
- },
- fallbackUrl: router.asPath
- })
-
- setAskAdminUrl(createdAskUrl)
- }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl])
-
const validAction = () => {
let isValid = true;
if (!selectedVariant) {
@@ -140,17 +120,14 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
return (
<MobileView>
- <div className='p-4'>
- <Breadcrumb id={product.id} name={product.name} />
- </div>
<Image
src={product.image + '?variant=True'}
alt={product.name}
- className='h-72 object-contain mt-4 object-center w-full border-b border-gray_r-4'
+ className='h-72 object-contain object-center w-full border-b border-gray_r-4'
/>
<div className='p-4'>
- <div className='flex items-center mb-2'>
+ <div className='flex items-end mb-2'>
{product.manufacture?.name ? (
<Link
href={createSlug(
@@ -164,45 +141,15 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
) : (
<div>-</div>
)}
- <div className="ml-2 flex gap-x-5">
- <Button
- as={Link}
- href={askAdminUrl}
- variant='link'
- target='_blank'
- colorScheme='gray'
- leftIcon={<MessageCircleIcon size={18} />}
- >
- Ask Admin
- </Button>
-
- <AddToWishlist productId={product.id} />
-
- <RWebShare
- data={{
- text: 'Check out this product',
- title: `${product.name} - Indoteknik.com`,
- url: SELF_HOST + router.asPath
- }}
- >
- <Button
- variant='link'
- colorScheme='gray'
- leftIcon={<Share2Icon size={18} />}
- >
- Share
- </Button>
- </RWebShare>
- </div>
- {/* <button type='button' className='ml-auto' onClick={toggleWishlist}>
+ <button type='button' className='ml-auto' onClick={toggleWishlist}>
{wishlist.data?.productTotal > 0 ? (
<HeartIcon className='w-6 fill-danger-500 text-danger-500' />
) : (
<HeartIcon className='w-6' />
)}
- </button> */}
+ </button>
</div>
- <h1 className='font-medium text-h-lg leading-8 md:text-title-md md:leading-10 mb-3'>{activeVariant?.name}</h1>
+ <h1 className='leading-6 font-medium mb-3'>{activeVariant?.name}</h1>
{activeVariant.isFlashSale &&
activeVariant?.price?.discountPercentage > 0 ? (
@@ -226,11 +173,11 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
</div>
</>
) : (
- <h3 className='font-medium text-danger-500 text-title-md mt-1'>
+ <h3 className='text-danger-500 font-semibold mt-1'>
{activeVariant?.price?.price > 0 ? (
<>
{currencyFormat(activeVariant?.price?.price)}
- <div className='text-gray_r-9 text-base font-medium mt-1'>
+ <div className='text-gray_r-9 text-base font-normal mt-1'>
Termasuk PPN:{' '}
{currencyFormat(
activeVariant?.price.price * process.env.NEXT_PUBLIC_PPN
diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx
index a1491c7f..35e2a665 100644
--- a/src/lib/product/components/ProductCard.jsx
+++ b/src/lib/product/components/ProductCard.jsx
@@ -146,20 +146,13 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
)}
</Link>
<div className='p-2 sm:p-3 pb-3 text-caption-2 sm:text-body-2 leading-5'>
- <div className='flex justify-between '>
- {product?.manufacture?.name ? (
- <Link href={URL.manufacture} className='mb-1 mt-1'>
- {product.manufacture.name}
- </Link>
- ) : (
- <div>-</div>
- )}
- {product?.is_in_bu && (
- <div className=''>
- <Image src='/images/PICKUP-NOW.png' alt='pickup now' width={90} height={12} />
- </div>
- )}
- </div>
+ {product?.manufacture?.name ? (
+ <Link href={URL.manufacture} className='mb-1'>
+ {product.manufacture.name}
+ </Link>
+ ) : (
+ <div>-</div>
+ )}
<Link
href={URL.product}
className={`mb-2 !text-gray_r-12 leading-6 block line-clamp-3 h-[64px]`}
@@ -299,18 +292,9 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
</div>
)}
{product?.manufacture?.name ? (
- <div className='flex justify-between'>
- <Link href={URL.manufacture} className='mb-1'>
+ <Link href={URL.manufacture} className='mb-1'>
{product.manufacture.name}
</Link>
- {/* {product?.is_in_bu && (
- <div className='bg-red-500 rounded'>
- <span className='p-[6px] text-xs text-white'>
- Click & Pickup
- </span>
- </div>
- )} */}
- </div>
) : (
<div>-</div>
)}
diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx
index d52fcb90..dd9ec8f4 100644
--- a/src/lib/product/components/ProductFilter.jsx
+++ b/src/lib/product/components/ProductFilter.jsx
@@ -62,6 +62,7 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr
const handleSubmit = () => {
let params = {
+ penawaran: router.query.penawaran,
q: router.query.q,
orderBy: order,
brand,
diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx
index 1933c5f0..2bdf962a 100644
--- a/src/lib/product/components/ProductFilterDesktop.jsx
+++ b/src/lib/product/components/ProductFilterDesktop.jsx
@@ -93,6 +93,7 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu
const handleSubmit = () => {
let params = {
+ penawaran: router.query.penawaran,
q: router.query.q,
orderBy: order,
brand: brandValues.join(','),
@@ -107,11 +108,7 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu
const slug = Array.isArray(router.query.slug) ? router.query.slug[0] : router.query.slug;
if (slug) {
- if(prefixUrl.includes('category') || prefixUrl.includes('lob')){
- router.push(`${prefixUrl}?${params}`)
- }else{
- router.push(`${prefixUrl}/${slug}?${params}`)
- }
+ router.push(`${prefixUrl}/${slug}?${params}`)
} else {
router.push(`${prefixUrl}?${params}`)
}
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index a83e5e1e..a427e134 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -142,6 +142,23 @@ const ProductSearch = ({
}
}, [prefixUrl,dataCategoriesProduct, query, finalQuery]);
+ useEffect(() => {
+ const checkIfPenawaran = async () => {
+ if (router.asPath.includes('penawaran')) {
+ query = {
+ ...query,
+ fq: [
+ `-flashsale_id_i:${router.query.penawaran}`,
+ `flashsale_price_f:[1 TO *]`
+ ],
+ orderBy: 'flashsale-discount-desc'
+ };
+ setOrderBy('flashsale-discount-desc')
+ }
+ };
+ checkIfPenawaran();
+ }, [router]);
+
const { productSearch } = useProductSearch({
query: queryFinal,
operation: 'AND',
@@ -340,6 +357,7 @@ const ProductSearch = ({
const handleDeleteFilter = async (source, value) => {
let params = {
+ penawaran: router.query.penawaran,
q: router.query.q,
orderBy: orderBy,
brand: brandValues.join(','),
@@ -367,6 +385,7 @@ const ProductSearch = ({
break;
case 'delete':
params = {
+ penawaran: router.query.penawaran,
q: router.query.q,
orderBy: orderBy,
};
diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx
index 0ad042de..df234dc2 100644
--- a/src/lib/quotation/components/Quotation.jsx
+++ b/src/lib/quotation/components/Quotation.jsx
@@ -9,7 +9,6 @@ import _ from 'lodash';
import { deleteItemCart, getCart, getItemCart } from '@/core/utils/cart';
import currencyFormat from '@/core/utils/currencyFormat';
import { toast } from 'react-hot-toast';
-import { useProductCartContext } from '@/contexts/ProductCartContext';
// import checkoutApi from '@/lib/checkout/api/checkoutApi'
import { useRouter } from 'next/router';
import VariantGroupCard from '@/lib/variant/components/VariantGroupCard';
@@ -39,12 +38,11 @@ const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi');
const Quotation = () => {
const router = useRouter();
const auth = useAuth();
-
+
const { data: cartCheckout } = useQuery('cartCheckout', () =>
getProductsCheckout()
-);
+ );
-const { setRefreshCart } = useProductCartContext();
const SELF_PICKUP_ID = 32;
const [products, setProducts] = useState(null);
@@ -295,7 +293,6 @@ const { setRefreshCart } = useProductCartContext();
if (isSuccess?.id) {
for (const product of products) deleteItemCart({ productId: product.id });
router.push(`/shop/quotation/finish?id=${isSuccess.id}`);
- setRefreshCart(true);
return;
}
diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx
deleted file mode 100644
index 4529c977..00000000
--- a/src/lib/quotation/components/Quotationheader.jsx
+++ /dev/null
@@ -1,265 +0,0 @@
-import { useCallback, useEffect, useMemo, useState } from 'react';
-import { createSlug } from '@/core/utils/slug';
-import useAuth from '@/core/hooks/useAuth';
-import { useRouter } from 'next/router';
-import odooApi from '@/core/api/odooApi';
-import { useProductCartContext } from '@/contexts/ProductCartContext';
-import Image from '@/core/components/elements/Image/Image';
-import whatsappUrl from '@/core/utils/whatsappUrl';
-import { AnimatePresence, motion } from 'framer-motion';
-import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css';
-import useTransactions from '../../transaction/hooks/useTransactions';
-import currencyFormat from '@/core/utils/currencyFormat';
-const { DocumentCheckIcon, PhotoIcon } = require('@heroicons/react/24/outline');
-const { default: Link } = require('next/link');
-
-const Quotationheader = (quotationCount) => {
- const auth = useAuth();
- const query = {
- 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 [isHovered, setIsHovered] = useState(false);
- const [isTop, setIsTop] = useState(true);
-
- const qotation = useMemo(() => {
- return productQuotation || [];
- }, [productQuotation]);
-
- const handleMouseEnter = () => {
- setIsHovered(true);
- getCart();
- };
-
- const handleMouseLeave = () => {
- setIsHovered(false);
- };
-
- const getCart = () => {
- if (!productQuotation && auth) {
- refreshCartf();
- }
- };
- let { transactions } = useTransactions({ query });
-
- const refreshCartf = useCallback(async () => {
- setIsloading(true);
- let pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft');
- setProductQuotation(pendingTransactions);
- setCountQuotation(pendingTransactions?.length ? pendingTransactions?.length : pendingTransactions?.length);
- setIsloading(false);
- }, [setProductQuotation, setIsloading]);
-
- useEffect(() => {
- if (!qotation) return
-
- let calculateTotalDiscountAmount = 0
- for (const product of qotation) {
- // if (qotation.quantity == '') continue
- calculateTotalDiscountAmount += product.amountUntaxed
- }
- let subTotal = calculateTotalDiscountAmount
- setSubTotal(subTotal)
- }, [qotation])
-
- useEffect(() => {
- if (refreshCart) {
- refreshCartf();
- }
- setRefreshCart(false);
- }, [ refreshCartf, setRefreshCart]);
-
- useEffect(() => {
- setCountQuotation(quotationCount.quotationCount);
- setProductQuotation(quotationCount.data);
- }, [quotationCount]);
-
- useEffect(() => {
- const handleScroll = () => {
- setIsTop(window.scrollY === 0);
- };
- window.addEventListener('scroll', handleScroll);
- return () => {
- window.removeEventListener('scroll', handleScroll);
- };
- }, []);
-
- const handleCheckout = async () => {
- SetButtonTerapkan(true);
- let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`);
- router.push('/my/quotations');
- };
-
- return (
- <div className='relative group'>
- <div>
- <Link
- href='/my/quotations'
- target='_blank'
- rel='noreferrer'
- className='flex items-center gap-x-2 !text-gray_r-12/80'
- onMouseEnter={handleMouseEnter}
- onMouseLeave={handleMouseLeave}
- >
- <div className={`relative ${countQuotation > 0 && 'mr-2'}`}>
- <DocumentCheckIcon className='w-7' />
- {countQuotation > 0 && (
- <span className='absolute -top-2 -right-2 badge-solid-red rounded-full w-5 h-5 flex items-center justify-center'>
- {countQuotation}
- </span>
- )}
- </div>
- <span>
- List
- <br />
- Quotation
- </span>
- </Link>
- </div>
- <AnimatePresence>
- {isHovered && (
- <>
- <motion.div
- initial={{ opacity: 0 }}
- animate={{ opacity: 1, top: isTop ? 230 : 155 }}
- exit={{ opacity: 0 }}
- transition={{ duration: 0.15, top: { duration: 0.3 } }}
- className={`fixed left-0 w-full h-full bg-black/50 z-10`}
- />
- <motion.div
- initial={{ opacity: 0 }}
- animate={{ opacity: 1, transition: { duration: 0.2 } }}
- exit={{ opacity: 0, transition: { duration: 0.3 } }}
- className='absolute z-10 left-0 w-96'
- onMouseEnter={handleMouseEnter}
- onMouseLeave={handleMouseLeave}
- >
- <motion.div
- initial={{ height: 0 }}
- animate={{ height: 'auto' }}
- exit={{ height: 0 }}
- 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>
- </div>
- <hr className='mt-3 mb-3 border border-gray-100' />
- <div className='flow-root max-h-[250px] overflow-y-auto'>
- {!auth && (
- <div className='justify-center p-4'>
- <p className='text-gray-500 text-center '>
- Silahkan{' '}
- <Link href='/login' className='text-red-600 underline leading-6'>
- Login
- </Link>{' '}
- Untuk Melihat Daftar Quotation Anda
- </p>
- </div>
- )}
- {isLoading &&
- itemLoading.map((item) => (
- <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' />
- </div>
- <div className='flex-1 min-w-0'>
- <div className='h-2.5 bg-gray-200 rounded-full dark:bg-gray-700 w-48 mb-4'></div>
- <div className='h-2 bg-gray-200 rounded-full dark:bg-gray-700 max-w-[360px] mb-2.5'></div>
- <div className='h-2 bg-gray-200 rounded-full dark:bg-gray-700 mb-2.5'></div>
- </div>
- </div>
- </div>
- ))}
- {auth && qotation.length === 0 && !isLoading && (
- <div className='justify-center p-4'>
- <p className='text-gray-500 text-center '>
- Tidak Ada Quotation
- </p>
- </div>
- )}
- {auth && qotation.length > 0 && !isLoading && (
- <>
- <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
- href={`/my/quotations/${product?.id}`}
- 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>
- </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>
- </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>
- </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>
- </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>
- </div>
- </Link>
- </div>
- </li>
- </>
- ))}
- </ul>
- <hr />
- </>
- )}
- </div>
- {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>
- </div>
- <div className='mt-5 mb-2'>
- <button
- type='button'
- className='btn-solid-red rounded-lg w-full'
- onClick={handleCheckout}
- disabled={buttonLoading}
- >
- {buttonLoading ? 'Loading...' : 'Lihat Semua'}
- </button>
- </div>
- </>
- )}
- </motion.div>
- </motion.div>
- </>
- )}
- </AnimatePresence>
- </div>
- );
-};
-
-export default Quotationheader;
diff --git a/src/lib/tracking-order/api/trackingOrder.js b/src/lib/tracking-order/api/trackingOrder.js
deleted file mode 100644
index cc48c40c..00000000
--- a/src/lib/tracking-order/api/trackingOrder.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import odooApi from "@/core/api/odooApi";
-
-export const trackingOrder = async ({query}) => {
- const params = new URLSearchParams(query).toString();
- const list = await odooApi('GET', `/api/v1/tracking_order?${params}`)
-
- return list;
-}
diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx
deleted file mode 100644
index 394979c1..00000000
--- a/src/lib/tracking-order/component/TrackingOrder.jsx
+++ /dev/null
@@ -1,139 +0,0 @@
-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'
-
-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 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>
- </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>
- </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'),
-})
-
-const defaultValues = {
- email: '',
- id: ''
-}
-
-export default TrackingOrder
diff --git a/src/lib/transaction/api/checkoutPoApi.js b/src/lib/transaction/api/checkoutPoApi.js
index af41d277..04421368 100644
--- a/src/lib/transaction/api/checkoutPoApi.js
+++ b/src/lib/transaction/api/checkoutPoApi.js
@@ -1,11 +1,11 @@
import odooApi from '@/core/api/odooApi'
import { getAuth } from '@/core/utils/auth'
-const checkoutPoApi = async ({ id, status }) => {
+const checkoutPoApi = async ({ id }) => {
const auth = getAuth()
const dataCheckout = await odooApi(
'POST',
- `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout`,{status}
+ `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout`
)
return dataCheckout
}
diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx
index a9e04c0e..9bef895a 100644
--- a/src/lib/transaction/components/Transaction.jsx
+++ b/src/lib/transaction/components/Transaction.jsx
@@ -1,12 +1,10 @@
import Spinner from '@/core/components/elements/Spinner/Spinner';
import NextImage from 'next/image';
-import rejectImage from '../../../../public/images/reject.png';
+import rejectImage from "../../../../public/images/reject.png"
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 { Button, Tooltip } from '@chakra-ui/react';
-import clsxm from '~/libs/clsxm';
import ImageNext from 'next/image';
import {
downloadPurchaseOrder,
@@ -42,7 +40,7 @@ import rejectProductApi from '../api/rejectProductApi';
import { useRouter } from 'next/router';
const Transaction = ({ id }) => {
- const router = useRouter();
+ const router = useRouter()
const [isModalOpen, setIsModalOpen] = useState(false);
const [selectedProduct, setSelectedProduct] = useState(null);
const [reason, setReason] = useState('');
@@ -109,7 +107,7 @@ const Transaction = ({ id }) => {
toast.error('Mohon upload dokumen PO anda sebelum melanjutkan pesanan');
return;
}
- await checkoutPoApi({ id, status: true });
+ await checkoutPoApi({ id });
toast.success('Berhasil melanjutkan pesanan');
transaction.refetch();
};
@@ -154,10 +152,7 @@ const Transaction = ({ id }) => {
const memoizeVariantGroupCardReject = useMemo(
() => (
<div className='p-4 pt-0 flex flex-col gap-y-3'>
- <VariantGroupCard
- variants={transaction.data?.productsRejectLine}
- buyMore
- />
+ <VariantGroupCard variants={transaction.data?.productsRejectLine} buyMore />
</div>
),
[transaction.data]
@@ -187,25 +182,26 @@ const Transaction = ({ id }) => {
};
const handleRejectProduct = async () => {
- try {
+ try{
if (!reason.trim()) {
toast.error('Masukkan alasan terlebih dahulu');
return;
- } else {
- let idSo = transaction?.data.id;
- let idProduct = selectedProduct?.id;
- await rejectProductApi({ idSo, idProduct, reason });
+ }else{
+ let idSo = transaction?.data.id
+ let idProduct = selectedProduct?.id
+ await rejectProductApi({ idSo, idProduct, reason});
closeModal();
- toast.success('Produk berhasil di reject');
+ toast.success("Produk berhasil di reject")
setTimeout(() => {
window.location.reload();
- }, 1500);
+ }, 1500);
}
- } catch (error) {
+ }catch(error){
toast.error('Gagal reject produk. Silakan coba lagi.');
}
};
+
return (
transaction.data?.name && (
<>
@@ -394,20 +390,14 @@ const Transaction = ({ id }) => {
<p className='text-gray_r-11 leading-none'>Dokumen PO</p>
<button
type='button'
- className='inline-block text-danger-500'
+ className='btn-light py-1.5 px-3 ml-auto'
onClick={
transaction.data?.purchaseOrderFile
? () => downloadPurchaseOrder(transaction.data)
- : transaction?.data.invoices.length < 1
- ? openUploadPo
- : ''
+ : openUploadPo
}
>
- {transaction?.data?.purchaseOrderFile
- ? 'Download'
- : transaction?.data.invoices.length < 1
- ? 'Upload'
- : '-'}
+ {transaction.data?.purchaseOrderFile ? 'Download' : 'Upload'}
</button>
</div>
</div>
@@ -416,13 +406,13 @@ const Transaction = ({ id }) => {
<Divider />
<div className='font-medium p-4'>Detail Produk</div>
- {transaction?.data?.products.length > 0 ? (
- <div>{memoizeVariantGroupCard}</div>
- ) : (
- <div className='badge-red text-sm px-2 ml-4'>
- Semua produk telah di reject
+ {transaction?.data?.products.length > 0? (
+ <div>
+ {memoizeVariantGroupCard}
</div>
- )}
+ ) : (
+ <div className='badge-red text-sm px-2 ml-4'>Semua produk telah di reject</div>
+ )}
{transaction?.data?.productsRejectLine.length > 0 && (
<div>
@@ -565,27 +555,10 @@ const Transaction = ({ id }) => {
)}
{transaction.data?.status == 'draft' &&
!auth?.feature.soApproval && (
- <div>
- <Tooltip
- label={clsxm({
- 'Mohon upload dokumen PO anda sebelum melanjutkan pesanan': !transaction?.data?.purchaseOrderFile,
- })}>
- <Button colorScheme='yellow' onClick={checkout}
- isDisabled={
- // transaction.data?.status === 'draft'
- // ? true
- // : false ||
- auth?.webRole === statusApprovalWeb
- ? true
- : false || transaction?.data?.purchaseOrderFile === true ? false : true
- }
- >
- Lanjutkan Transaksi
- </Button>
- </Tooltip>
-
- </div>
- )}
+ <button className='btn-yellow' onClick={checkout}>
+ Lanjutkan Transaksi
+ </button>
+ )}
{transaction.data?.status != 'draft' &&
!auth?.feature.soApproval && (
<button
@@ -621,16 +594,12 @@ const Transaction = ({ id }) => {
onClick={
transaction.data?.purchaseOrderFile
? () => downloadPurchaseOrder(transaction.data)
- : transaction?.data.invoices.length < 1
- ? openUploadPo
- : ''
+ : openUploadPo
}
>
{transaction?.data?.purchaseOrderFile
? 'Download'
- : transaction?.data.invoices.length < 1
- ? 'Upload'
- : '-'}
+ : 'Upload'}
</button>
</div>
</>
@@ -659,11 +628,9 @@ const Transaction = ({ id }) => {
<div className='text-h-sm font-semibold mt-10 mb-4'>
Pengiriman
</div>
- {transaction?.data?.pickings.length == 0 && (
- <div className='badge-red text-sm'>
- Belum ada pengiriman
- </div>
- )}
+ {transaction?.data?.pickings.length == 0 && (
+ <div className='badge-red text-sm'>Belum ada pengiriman</div>
+ )}
<div className='grid grid-cols-1 gap-1 w-2/3'>
{transaction?.data?.pickings?.map((airway) => (
<button
@@ -679,9 +646,7 @@ const Transaction = ({ id }) => {
</div>
<div className='flex gap-x-2'>
<div className='text-sm text-gray-600 badge-green leading-[1.5] mt-1'>
- {airway?.delivered
- ? 'Pesanan Tiba'
- : 'Sedang Dikirim'}
+ {airway?.delivered ? 'Pesanan Tiba' : 'Sedang Dikirim'}
</div>
<ChevronRightIcon className='w-5 stroke-2' />
</div>
@@ -690,53 +655,51 @@ const Transaction = ({ id }) => {
</div>
</div>
<div className='invoice w-1/2 '>
- <div className='text-h-sm font-semibold mt-10 mb-4 '>
- Invoice
- </div>
- {transaction.data?.invoices?.length === 0 && (
- <div className='badge-red text-sm'>Belum ada invoice</div>
- )}
- <div className='grid grid-cols-1 gap-1 w-2/3 '>
- {transaction.data?.invoices?.map((invoice, index) => (
- <Link href={`/my/invoices/${invoice.id}`} key={index}>
- <div className='shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between'>
- <div>
- <p className='mb-1'>{invoice?.name}</p>
- <div className='flex items-center gap-x-1'>
- {invoice.amountResidual > 0 ? (
- <div className='badge-red'>Belum Lunas</div>
- ) : (
- <div className='badge-green'>Lunas</div>
- )}
- <p className='text-caption-2 text-gray_r-11'>
- {currencyFormat(invoice.amountTotal)}
- </p>
+ <div className='text-h-sm font-semibold mt-10 mb-4 '>Invoice</div>
+ {transaction.data?.invoices?.length === 0 && (
+ <div className='badge-red text-sm'>Belum ada invoice</div>
+ )}
+ <div className='grid grid-cols-1 gap-1 w-2/3 '>
+ {transaction.data?.invoices?.map((invoice, index) => (
+ <Link href={`/my/invoices/${invoice.id}`} key={index}>
+ <div className='shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between'>
+ <div>
+ <p className='mb-1'>{invoice?.name}</p>
+ <div className='flex items-center gap-x-1'>
+ {invoice.amountResidual > 0 ? (
+ <div className='badge-red'>Belum Lunas</div>
+ ) : (
+ <div className='badge-green'>Lunas</div>
+ )}
+ <p className='text-caption-2 text-gray_r-11'>
+ {currencyFormat(invoice.amountTotal)}
+ </p>
+ </div>
</div>
+ <ChevronRightIcon className='w-5 stroke-2' />
</div>
- <ChevronRightIcon className='w-5 stroke-2' />
- </div>
- </Link>
- ))}
- </div>
+ </Link>
+ ))}
+ </div>
</div>
</div>
<div className='text-h-sm font-semibold mt-4 mb-4'>
Rincian Pembelian
</div>
- {transaction?.data?.products?.length > 0 ? (
- <table className='table-data'>
- <thead>
- <tr>
- <th>Nama Produk</th>
- {/* <th>Diskon</th> */}
- <th>Jumlah</th>
- <th>Harga</th>
- <th>Subtotal</th>
- <th></th>
- </tr>
- </thead>
- <tbody>
+ {transaction?.data?.products?.length > 0? (
+ <table className='table-data'>
+ <thead>
+ <tr>
+ <th>Nama Produk</th>
+ {/* <th>Diskon</th> */}
+ <th>Jumlah</th>
+ <th>Harga</th>
+ <th>Subtotal</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
{transaction?.data?.products?.map((product) => (
<tr key={product.id}>
<td className='flex'>
@@ -748,37 +711,37 @@ const Transaction = ({ id }) => {
)}
className='w-[20%] flex-shrink-0'
>
- <div className='relative'>
+ <div className='relative'>
<Image
src={product?.parent?.image}
alt={product?.name}
className='object-contain object-center border border-gray_r-6 h-32 w-full rounded-md'
/>
- <div className='absolute top-0 right-4 flex mt-3'>
- <div className='gambarB '>
- {product.isSni && (
- <ImageNext
- src='/images/sni-logo.png'
- alt='SNI Logo'
- className='w-2 h-4 object-contain object-top sm:h-4'
- width={50}
- height={50}
- />
- )}
- </div>
- <div className='gambarC '>
- {product.isTkdn && (
- <ImageNext
- src='/images/TKDN.png'
- alt='TKDN'
- className='w-5 h-4 object-contain object-top ml-1 sm:h-4'
- width={50}
- height={50}
- />
- )}
- </div>
+ <div className='absolute top-0 right-4 flex mt-3'>
+ <div className='gambarB '>
+ {product.isSni && (
+ <ImageNext
+ src='/images/sni-logo.png'
+ alt='SNI Logo'
+ className='w-2 h-4 object-contain object-top sm:h-4'
+ width={50}
+ height={50}
+ />
+ )}
+ </div>
+ <div className='gambarC '>
+ {product.isTkdn && (
+ <ImageNext
+ src='/images/TKDN.png'
+ alt='TKDN'
+ className='w-5 h-4 object-contain object-top ml-1 sm:h-4'
+ width={50}
+ height={50}
+ />
+ )}
</div>
</div>
+ </div>
</Link>
<div className='px-2 text-left'>
<Link
@@ -811,42 +774,33 @@ const Transaction = ({ id }) => {
{currencyFormat(product.price.price)}
</div>
)} */}
- <div>
- {currencyFormat(product.price.priceDiscount)}
- </div>
+ <div>{currencyFormat(product.price.priceDiscount)}</div>
</td>
<td>{currencyFormat(product.price.subtotal)}</td>
{/* {auth?.feature.soApproval && (auth.webRole == 2 || auth.webRole == 3) && (transaction.data.isReaject == false) && ( */}
- {auth?.feature.soApproval &&
- (auth.webRole == 2 || auth.webRole == 3) &&
- router.asPath.includes('/my/quotations/') &&
- transaction.data?.status == 'draft' && (
- <td>
- <button
- className='bg-red-500 text-white py-1 px-3 rounded'
- onClick={() => openModal(product)}
- >
- Reject
- </button>
- </td>
- )}
+ {auth?.feature.soApproval && (auth.webRole == 2 || auth.webRole == 3) && (router.asPath.includes("/my/quotations/")) && transaction.data?.status == 'draft' && (
+ <td>
+ <button
+ className="bg-red-500 text-white py-1 px-3 rounded"
+ onClick={() => openModal(product)}
+ >
+ Reject
+ </button>
+ </td>
+ )}
</tr>
))}
</tbody>
</table>
) : (
- <div className='badge-red text-sm'>
- Semua produk telah di reject
- </div>
+ <div className='badge-red text-sm'>Semua produk telah di reject</div>
)}
-
+
{isModalOpen && (
<div className='fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center'>
- <div
- className='bg-white p-4 rounded w-96
+ <div className='bg-white p-4 rounded w-96
ease-in-out opacity-100
- transform transition-transform duration-300 scale-100'
- >
+ transform transition-transform duration-300 scale-100'>
<h2 className='text-lg mb-2'>Berikan Alasan</h2>
<textarea
value={reason}
@@ -872,116 +826,117 @@ const Transaction = ({ id }) => {
</div>
)}
- {transaction?.data?.products?.length > 0 && (
- <div className='flex justify-end mt-4'>
- <div className='w-1/4 grid grid-cols-2 gap-y-3 text-gray_r-12/80'>
- <div className='text-right'>Subtotal</div>
- <div className='text-right font-medium'>
- {currencyFormat(transaction.data?.amountUntaxed)}
- </div>
+ {transaction?.data?.products?.map((product) => (
+ <div className='flex justify-end mt-4' key={product.id}>
+ <div className='w-1/4 grid grid-cols-2 gap-y-3 text-gray_r-12/80'>
+ <div className='text-right'>Subtotal</div>
+ <div className='text-right font-medium'>
+ {currencyFormat(transaction.data?.amountUntaxed)}
+ </div>
- <div className='text-right'>PPN 11%</div>
- <div className='text-right font-medium'>
- {currencyFormat(transaction.data?.amountTax)}
- </div>
+ <div className='text-right'>PPN 11%</div>
+ <div className='text-right font-medium'>
+ {currencyFormat(transaction.data?.amountTax)}
+ </div>
- <div className='text-right whitespace-nowrap'>
- Biaya Pengiriman
- </div>
- <div className='text-right font-medium'>
- {currencyFormat(transaction.data?.deliveryAmount)}
- </div>
+ <div className='text-right whitespace-nowrap'>
+ Biaya Pengiriman
+ </div>
+ <div className='text-right font-medium'>
+ {currencyFormat(transaction.data?.deliveryAmount)}
+ </div>
- <div className='text-right'>Grand Total</div>
- <div className='text-right font-medium text-gray_r-12'>
- {currencyFormat(transaction.data?.amountTotal)}
- </div>
+ <div className='text-right'>Grand Total</div>
+ <div className='text-right font-medium text-gray_r-12'>
+ {currencyFormat(transaction.data?.amountTotal)}
</div>
</div>
- )}
+ </div>
+ ))}
+
+
{transaction?.data?.productsRejectLine.length > 0 && (
- <div className='text-h-sm font-semibold mt-10 mb-4'>
- Rincian Produk Reject
- </div>
+ <div className='text-h-sm font-semibold mt-10 mb-4'>
+ Rincian Produk Reject
+ </div>
)}
{transaction?.data?.productsRejectLine.length > 0 && (
- <table className='table-data'>
- <thead>
- <tr>
- <th>Nama Produk</th>
- {/* <th>Diskon</th> */}
- <th>Jumlah</th>
- <th>Harga</th>
- <th>Subtotal</th>
- </tr>
- </thead>
- <tbody>
- {transaction?.data?.productsRejectLine?.map((product) => (
- <tr key={product.id}>
- <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-32 w-full rounded-md'
- />
- </Link>
- <div className='px-2 text-left'>
+ <table className='table-data'>
+ <thead>
+ <tr>
+ <th>Nama Produk</th>
+ {/* <th>Diskon</th> */}
+ <th>Jumlah</th>
+ <th>Harga</th>
+ <th>Subtotal</th>
+ </tr>
+ </thead>
+ <tbody>
+ {transaction?.data?.productsRejectLine?.map((product) => (
+ <tr key={product.id}>
+ <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-32 w-full rounded-md'
+ />
</Link>
- <div className='text-gray_r-11 mt-2'>
- {product?.code}{' '}
- {product?.attributes.length > 0
- ? `| ${product?.attributes.join(', ')}`
- : ''}
+ <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>
- </div>
- </td>
- {/* <td>
+ </td>
+ {/* <td>
{product.price.discountPercentage > 0
? `${product.price.discountPercentage}%`
: ''}
</td> */}
- <td>{product.quantity}</td>
- <td>
- {/* {product.price.discountPercentage > 0 && (
+ <td>{product.quantity}</td>
+ <td>
+ {/* {product.price.discountPercentage > 0 && (
<div className='line-through mb-1 text-caption-1 text-gray_r-12/70'>
{currencyFormat(product.price.price)}
</div>
)} */}
- <div>
- {currencyFormat(product.price.priceDiscount)}
- </div>
- </td>
- <td className='flex justify-center'>
- <NextImage
- src={rejectImage}
- alt='Reject'
- width={90}
- height={30}
- />
- </td>
- </tr>
- ))}
- </tbody>
- </table>
+ <div>{currencyFormat(product.price.priceDiscount)}</div>
+ </td>
+ <td className='flex justify-center'>
+ <NextImage
+ src={rejectImage}
+ alt='Reject'
+ width={90}
+ height={30}
+ />
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
)}
+
</div>
</div>
</DesktopView>