summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHATEC\SPVDEV001 <tri.susilo@altama.co.id>2023-10-13 09:16:04 +0700
committerHATEC\SPVDEV001 <tri.susilo@altama.co.id>2023-10-13 09:16:04 +0700
commit26cee59f3abad5a9c45821ebdccc8ccb819c930b (patch)
tree6d90eef71db8d1ab9b456b43aef36b5873d13998 /src
parent6115a7b9e9e1cd2231c946609cb1ceac6d167386 (diff)
parent80295b97150495f56bd236a5345c2ddeb8313267 (diff)
Merge branch 'CR/breadcrumb' into CR/UI
Diffstat (limited to 'src')
-rw-r--r--src/core/components/elements/Product/cartProductsList.jsx5
-rw-r--r--src/lib/brand/components/Brand.jsx125
-rw-r--r--src/lib/brand/components/Breadcrumb.jsx40
-rw-r--r--src/lib/category/components/Breadcrumb.jsx56
-rw-r--r--src/lib/category/components/Category.jsx2
-rw-r--r--src/lib/checkout/components/Checkout.jsx79
-rw-r--r--src/lib/product/components/Product/Breadcrumb.jsx69
-rw-r--r--src/lib/product/components/Product/Product.jsx38
-rw-r--r--src/lib/product/components/Product/ProductDesktop.jsx73
-rw-r--r--src/lib/product/components/Product/ProductMobile.jsx2
-rw-r--r--src/lib/product/components/ProductSearch.jsx4
-rw-r--r--src/lib/promotinProgram/components/PromotionType.jsx2
-rw-r--r--src/lib/variant/components/VariantCard.jsx2
-rw-r--r--src/pages/shop/brands/[slug].jsx3
-rw-r--r--src/pages/shop/cart.jsx15
-rw-r--r--src/pages/shop/category/[slug].jsx4
-rw-r--r--src/pages/shop/product/[slug].jsx7
-rw-r--r--src/pages/shop/search.jsx20
18 files changed, 393 insertions, 153 deletions
diff --git a/src/core/components/elements/Product/cartProductsList.jsx b/src/core/components/elements/Product/cartProductsList.jsx
index 32df992b..9662cd3b 100644
--- a/src/core/components/elements/Product/cartProductsList.jsx
+++ b/src/core/components/elements/Product/cartProductsList.jsx
@@ -15,7 +15,6 @@ const CardProdcuctsList = ({
updateQuantity = () => {},
setDeleteConfirmation = () => {}
}) => {
-
return (
<table className='table-cart'>
<thead>
@@ -144,7 +143,9 @@ const CardProdcuctsList = ({
{product?.code}{' '}
{product?.attributes.length > 0 ? `| ${product?.attributes.join(', ')}` : ''}
</div>
- <div className='text-gray_r-11 mt-2'>Berat item : {product?.weight} Kg</div>
+ <div className='text-gray_r-11 mt-2'>
+ Berat item : {product?.weight} Kg x {product?.quantity} Barang
+ </div>
</div>
</td>
<td className='relative'>
diff --git a/src/lib/brand/components/Brand.jsx b/src/lib/brand/components/Brand.jsx
index 3c411969..4afbcb3e 100644
--- a/src/lib/brand/components/Brand.jsx
+++ b/src/lib/brand/components/Brand.jsx
@@ -6,10 +6,10 @@ import { Pagination, Autoplay } from 'swiper'
import 'swiper/css'
import 'swiper/css/pagination'
import 'swiper/css/autoplay'
-import Divider from '@/core/components/elements/Divider/Divider'
-import ImageSkeleton from '@/core/components/elements/Skeleton/ImageSkeleton'
import MobileView from '@/core/components/views/MobileView'
import DesktopView from '@/core/components/views/DesktopView'
+import { Skeleton } from '@chakra-ui/react'
+import classNames from 'classnames'
const swiperBanner = {
pagination: { dynamicBullets: true },
@@ -28,65 +28,77 @@ const Brand = ({ id }) => {
<MobileView>
<>
<div>
- {brand.isLoading && <ImageSkeleton />}
- {brand.data?.banners?.length == 0 && (
- <Image
- src='/images/default-banner-brand.jpg'
- alt='Brand - Indoteknik'
- width={1024}
- height={512}
- className='w-full h-auto'
- />
- )}
- {brand.data && (
- <>
- <Swiper
- slidesPerView={1}
- pagination={swiperBanner.pagination}
- modules={swiperBanner.modules}
- autoplay={swiperBanner.autoplay}
- className='border-b border-gray_r-6'
- >
- {brand.data?.banners?.map((banner, index) => (
- <SwiperSlide key={index}>
+ <Skeleton
+ isLoaded={!brand.isLoading}
+ aspectRatio='4/2'
+ className={classNames({
+ 'mb-6': brand.isLoading
+ })}
+ >
+ {brand.data?.banners?.length == 0 && (
+ <Image
+ src='/images/default-banner-brand.jpg'
+ alt='Brand - Indoteknik'
+ width={1024}
+ height={512}
+ className='w-full h-auto'
+ />
+ )}
+
+ {brand.data && (
+ <>
+ <Swiper
+ slidesPerView={1}
+ pagination={swiperBanner.pagination}
+ modules={swiperBanner.modules}
+ autoplay={swiperBanner.autoplay}
+ className='border-b border-gray_r-6'
+ >
+ {brand.data?.banners?.map((banner, index) => (
+ <SwiperSlide key={index}>
+ <Image
+ src={banner}
+ alt={`Brand ${brand.data?.name} - Indoteknik`}
+ width={1024}
+ height={512}
+ className='w-full h-auto'
+ />
+ </SwiperSlide>
+ ))}
+ </Swiper>
+ <div className='p-4'>
+ <div className='text-caption-1 text-gray_r-11 mb-2'>Produk dari brand:</div>
+ {brand?.data?.logo && (
<Image
- src={banner}
- alt={`Brand ${brand.data?.name} - Indoteknik`}
- width={1024}
- height={512}
- className='w-full h-auto'
+ src={brand?.data?.logo}
+ alt={brand?.data?.name}
+ className='w-32 p-2 border borde-gray_r-6 rounded'
+ width={256}
+ height={128}
/>
- </SwiperSlide>
- ))}
- </Swiper>
- <div className='p-4'>
- <div className='text-caption-1 text-gray_r-11 mb-2'>Produk dari brand:</div>
- {brand?.data?.logo && (
- <Image
- src={brand?.data?.logo}
- alt={brand?.data?.name}
- className='w-32 p-2 border borde-gray_r-6 rounded'
- width={256}
- height={128}
- />
- )}
- {!brand?.data?.logo && (
- <div className='bg-danger-500 text-white text-center text-caption-1 py-2 px-4 rounded w-fit'>
- {brand?.data?.name}
- </div>
- )}
- </div>
- </>
- )}
+ )}
+ {!brand?.data?.logo && (
+ <div className='bg-danger-500 text-white text-center text-caption-1 py-2 px-4 rounded w-fit'>
+ {brand?.data?.name}
+ </div>
+ )}
+ </div>
+ </>
+ )}
+ </Skeleton>
</div>
- <Divider />
</>
</MobileView>
<DesktopView>
- <div className='container mx-auto mt-10 mb-3'>
- <div className='min-h-[150px]'>
- {brand.isLoading && <ImageSkeleton />}
+ <div className='container mx-auto'>
+ <Skeleton
+ isLoaded={!brand.isLoading}
+ aspectRatio='4/1'
+ className={classNames({
+ 'mb-6': brand.isLoading
+ })}
+ >
{brand.data?.banners?.length == 0 && (
<Image
src='/images/default-banner-brand.jpg'
@@ -96,6 +108,7 @@ const Brand = ({ id }) => {
className='w-full h-auto'
/>
)}
+
{brand.data && (
<>
<Swiper
@@ -117,6 +130,7 @@ const Brand = ({ id }) => {
</SwiperSlide>
))}
</Swiper>
+
<div className='p-4'>
<div className='text-caption-1 text-gray_r-11 mb-2'>Produk dari brand:</div>
{brand?.data?.logo && (
@@ -136,8 +150,7 @@ const Brand = ({ id }) => {
</div>
</>
)}
- </div>
- <Divider />
+ </Skeleton>
</div>
</DesktopView>
</>
diff --git a/src/lib/brand/components/Breadcrumb.jsx b/src/lib/brand/components/Breadcrumb.jsx
new file mode 100644
index 00000000..0fec2dad
--- /dev/null
+++ b/src/lib/brand/components/Breadcrumb.jsx
@@ -0,0 +1,40 @@
+import { Breadcrumb as ChakraBreadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react'
+import Link from 'next/link'
+import React from 'react'
+
+/**
+ * Renders a breadcrumb component with links to navigate through different pages.
+ *
+ * @param {Object} props - The props object containing the brand name.
+ * @param {string} props.brandName - The name of the brand to display in the breadcrumb.
+ * @return {JSX.Element} The rendered breadcrumb component.
+ */
+const Breadcrumb = ({ brandName }) => {
+ return (
+ <div className='container mx-auto py-4 md:py-6'>
+ <ChakraBreadcrumb>
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500 whitespace-nowrap'>
+ Home
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ <BreadcrumbItem>
+ <BreadcrumbLink
+ as={Link}
+ href='/shop/brands'
+ className='!text-danger-500 whitespace-nowrap'
+ >
+ Brands
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ <BreadcrumbItem isCurrentPage>
+ <BreadcrumbLink className='whitespace-nowrap'>{brandName}</BreadcrumbLink>
+ </BreadcrumbItem>
+ </ChakraBreadcrumb>
+ </div>
+ )
+}
+
+export default Breadcrumb
diff --git a/src/lib/category/components/Breadcrumb.jsx b/src/lib/category/components/Breadcrumb.jsx
new file mode 100644
index 00000000..127904ee
--- /dev/null
+++ b/src/lib/category/components/Breadcrumb.jsx
@@ -0,0 +1,56 @@
+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(
+ `category-breadcrumbs/${categoryId}`,
+ async () => await odooApi('GET', `/api/v1/category/${categoryId}/category-breadcrumb`)
+ )
+
+ 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.name}</BreadcrumbLink>
+ ) : (
+ <BreadcrumbLink
+ as={Link}
+ href={createSlug('/shop/category/', category.name, category.id)}
+ className='!text-danger-500 whitespace-nowrap'
+ >
+ {category.name}
+ </BreadcrumbLink>
+ )}
+ </BreadcrumbItem>
+ ))}
+ </ChakraBreadcrumb>
+ </Skeleton>
+ </div>
+ )
+}
+
+export default Breadcrumb
diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx
index af696d42..e6ea5acf 100644
--- a/src/lib/category/components/Category.jsx
+++ b/src/lib/category/components/Category.jsx
@@ -30,7 +30,7 @@ const Category = () => {
return (
<DesktopView>
<div className='category-mega-box'>
- {categories.map((category) => (
+ {categories?.map((category) => (
<div key={category.id}>
<Link
href={createSlug('/shop/category/', category.name, category.id)}
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index e2c1a85b..35236e79 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -33,6 +33,8 @@ import { useQuery } from 'react-query'
import { gtagPurchase } from '@/core/utils/googleTag'
import { findVoucher, getVoucher } from '../api/getVoucher'
import CardProdcuctsList from '@/core/components/elements/Product/cartProductsList'
+import { Spinner } from '@chakra-ui/react'
+import { AnimatePresence, motion } from 'framer-motion'
const SELF_PICKUP_ID = 32
@@ -110,6 +112,7 @@ const Checkout = () => {
const [buttonTerapkan, SetButtonTerapkan] = useState(false)
const [checkoutValidation, setCheckoutValidation] = useState(false)
const [loadingVoucher, setLoadingVoucher] = useState(true)
+ const [loadingRajaOngkir, setLoadingRajaOngkir] = useState(false)
const expedisiValidation = useRef(null)
@@ -211,6 +214,7 @@ const Checkout = () => {
useEffect(() => {
setCheckoutValidation(false)
const loadServiceRajaOngkir = async () => {
+ setLoadingRajaOngkir(true)
const body = {
origin: 2127,
destination: selectedAddress.shipping.rajaongkirCityId,
@@ -221,6 +225,7 @@ const Checkout = () => {
}
setBiayaKirim(0)
const dataService = await axios('/api/rajaongkir-service?body=' + JSON.stringify(body))
+ setLoadingRajaOngkir(false)
setListServiceExpedisi(dataService.data[0].costs)
if (dataService.data[0].costs[0]) {
setBiayaKirim(dataService.data[0].costs[0]?.cost[0].value)
@@ -259,9 +264,8 @@ const Checkout = () => {
useEffect(() => {
if (selectedExpedisi) {
let serviceType = selectedExpedisi.split(',')
- if (serviceType[0] === 0) {
- setSelectedExpedisi(0)
- }
+ if (serviceType[0] === 0) return
+
setselectedCarrier(serviceType[0])
setselectedCarrierId(serviceType[1])
setListServiceExpedisi([])
@@ -723,6 +727,7 @@ const Checkout = () => {
checkWeigth={checkWeigth}
checkoutValidation={checkoutValidation}
expedisiValidation={expedisiValidation}
+ loadingRajaOngkir={loadingRajaOngkir}
/>
<Divider />
<SectionListService
@@ -980,6 +985,7 @@ const Checkout = () => {
checkWeigth={checkWeigth}
checkoutValidation={checkoutValidation}
expedisiValidation={expedisiValidation}
+ loadingRajaOngkir={loadingRajaOngkir}
/>
<Divider />
<SectionListService
@@ -990,7 +996,7 @@ const Checkout = () => {
<div className='p-4'>
<div className='font-medium'>Detail Pesanan</div>
<CardProdcuctsList isLoading={isLoading} products={products} />
-
+
{/* <table className='table-checkout'>
<thead>
<tr>
@@ -1158,7 +1164,9 @@ const Checkout = () => {
<div className='sticky top-48 border border-gray_r-6 bg-white rounded p-4'>
<div className='flex justify-between items-center'>
<div className='font-medium'>Ringkasan Pesanan</div>
- <div className='text-gray_r-11 text-caption-1'>{products?.length} Barang</div>
+ <div className='text-gray_r-11 text-caption-1'>
+ {products?.length} Barang - {cartCheckout?.totalWeight.kg} Kg
+ </div>
</div>
<hr className='my-4 border-gray_r-6' />
@@ -1403,32 +1411,51 @@ const SectionExpedisi = ({
setSelectedExpedisi,
checkWeigth,
checkoutValidation,
- expedisiValidation
+ expedisiValidation,
+ loadingRajaOngkir
}) =>
address?.rajaongkirCityId > 0 && (
<div className='p-4' ref={expedisiValidation}>
<div className='flex justify-between items-center'>
- <div className='font-medium'>Pilih Expedisi : </div>
+ <div className='font-medium'>Pilih Ekspedisi: </div>
<div className='w-[250px]'>
- <select
- className={`form-input ${checkoutValidation ? 'border-red-500 shake' : ''}`}
- onChange={(e) => setSelectedExpedisi(e.target.value)}
- required
- >
- <option value='0,0'>Pilih Pengiriman</option>
- <option value='1,32'>SELF PICKUP</option>
- {checkWeigth != true &&
- listExpedisi.map((expedisi) => (
- <option
- disabled={checkWeigth}
- value={expedisi.label + ',' + expedisi.carrierId}
- key={expedisi.value}
+ <div className='flex items-center gap-x-4'>
+ <select
+ className={`form-input ${checkoutValidation ? 'border-red-500 shake' : ''}`}
+ onChange={(e) => setSelectedExpedisi(e.target.value)}
+ required
+ >
+ <option value='0,0'>Pilih Pengiriman</option>
+ <option value='1,32'>SELF PICKUP</option>
+ {checkWeigth != true &&
+ listExpedisi.map((expedisi) => (
+ <option
+ disabled={checkWeigth}
+ value={expedisi.label + ',' + expedisi.carrierId}
+ key={expedisi.value}
+ >
+ {' '}
+ {expedisi.label.toUpperCase()}{' '}
+ </option>
+ ))}
+ </select>
+
+ <AnimatePresence>
+ {loadingRajaOngkir && (
+ <motion.div
+ initial={{ opacity: 0, width: 0 }}
+ animate={{ opacity: 1, width: '28px' }}
+ exit={{ opacity: 0, width: 0 }}
+ transition={{
+ duration: 0.25
+ }}
+ className='overflow-hidden'
>
- {' '}
- {expedisi.label.toUpperCase()}{' '}
- </option>
- ))}
- </select>
+ <Spinner thickness='3px' speed='0.5s' color='red.500' />
+ </motion.div>
+ )}
+ </AnimatePresence>
+ </div>
{checkoutValidation && (
<span className='text-sm text-red-500'>*silahkan pilih expedisi</span>
)}
@@ -1459,7 +1486,7 @@ const SectionListService = ({ listserviceExpedisi, setSelectedServiceType }) =>
<>
<div className='p-4'>
<div className='flex justify-between items-center'>
- <div className='font-medium'>Service Type Expedisi : </div>
+ <div className='font-medium'>Tipe Layanan Ekspedisi: </div>
<div>
<select className='form-input' onChange={(e) => setSelectedServiceType(e.target.value)}>
{listserviceExpedisi.map((service) => (
diff --git a/src/lib/product/components/Product/Breadcrumb.jsx b/src/lib/product/components/Product/Breadcrumb.jsx
new file mode 100644
index 00000000..0554dba5
--- /dev/null
+++ b/src/lib/product/components/Product/Breadcrumb.jsx
@@ -0,0 +1,69 @@
+import odooApi from '@/core/api/odooApi'
+import { createSlug } from '@/core/utils/slug'
+import {
+ Breadcrumb as ChakraBreadcrumb,
+ BreadcrumbItem,
+ BreadcrumbLink,
+ Skeleton
+} from '@chakra-ui/react'
+import classNames from 'classnames'
+import Link from 'next/link'
+import { useQuery } from 'react-query'
+
+/**
+ * Renders a breadcrumb component based on the provided `productId`.
+ *
+ * @param {Object} props - The properties passed to the component.
+ * @param {number} props.productId - The ID of the product.
+ * @param {string} props.productName - The ID of the product.
+ * @return {ReactElement} The rendered breadcrumb component.
+ */
+const Breadcrumb = ({ productId, productName }) => {
+ const categories = useQuery(
+ `detail/categories/${productId}`,
+ async () => await odooApi('GET', `/api/v1/product/${productId}/category-breadcrumb`),
+ {
+ enabled: !!productId
+ }
+ )
+
+ return (
+ <Skeleton
+ isLoaded={!categories.isLoading}
+ className={classNames({
+ 'w-2/3': categories.isLoading,
+ 'w-full': !categories.isLoading
+ })}
+ >
+ <ChakraBreadcrumb
+ mb={10}
+ overflowX={'auto'}
+ className='text-caption-2 md:text-body-2 p-4 md:p-0'
+ >
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500 whitespace-nowrap'>
+ Home
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ {categories.data?.map((category) => (
+ <BreadcrumbItem key={category.id}>
+ <BreadcrumbLink
+ as={Link}
+ href={createSlug('/shop/category/', category.name, category.id)}
+ className='!text-danger-500 whitespace-nowrap'
+ >
+ {category.name}
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+ ))}
+
+ <BreadcrumbItem isCurrentPage>
+ <BreadcrumbLink className='whitespace-nowrap'>{productName}</BreadcrumbLink>
+ </BreadcrumbItem>
+ </ChakraBreadcrumb>
+ </Skeleton>
+ )
+}
+
+export default Breadcrumb
diff --git a/src/lib/product/components/Product/Product.jsx b/src/lib/product/components/Product/Product.jsx
index 54490c26..6e983c2e 100644
--- a/src/lib/product/components/Product/Product.jsx
+++ b/src/lib/product/components/Product/Product.jsx
@@ -36,29 +36,21 @@ const Product = ({ product, isVariant = false }) => {
}
}, [product, isVariant])
- if (isVariant == true) {
- return (
- <>
- <ProductDesktopVariant
- product={product}
- wishlist={wishlist}
- toggleWishlist={toggleWishlist}
- />
- <ProductMobileVariant
- product={product}
- wishlist={wishlist}
- toggleWishlist={toggleWishlist}
- />
- </>
- )
- } else {
- return (
- <>
- <ProductMobile product={product} wishlist={wishlist} toggleWishlist={toggleWishlist} />
- <ProductDesktop products={product} wishlist={wishlist} toggleWishlist={toggleWishlist} />
- </>
- )
- }
+ return isVariant == true ? (
+ <>
+ <ProductDesktopVariant
+ product={product}
+ wishlist={wishlist}
+ toggleWishlist={toggleWishlist}
+ />
+ <ProductMobileVariant product={product} wishlist={wishlist} toggleWishlist={toggleWishlist} />
+ </>
+ ) : (
+ <>
+ <ProductMobile product={product} wishlist={wishlist} toggleWishlist={toggleWishlist} />
+ <ProductDesktop products={product} wishlist={wishlist} toggleWishlist={toggleWishlist} />
+ </>
+ )
}
export default Product
diff --git a/src/lib/product/components/Product/ProductDesktop.jsx b/src/lib/product/components/Product/ProductDesktop.jsx
index 47e98c1a..855c9f75 100644
--- a/src/lib/product/components/Product/ProductDesktop.jsx
+++ b/src/lib/product/components/Product/ProductDesktop.jsx
@@ -24,6 +24,7 @@ import ColumnsSLA from './ColumnsSLA'
import { useProductCartContext } from '@/contexts/ProductCartContext'
import { Box, Skeleton, Tooltip } from '@chakra-ui/react'
import { Info } from 'lucide-react'
+import Breadcrumb from './Breadcrumb'
const ProductDesktop = ({ products, wishlist, toggleWishlist }) => {
const router = useRouter()
@@ -199,47 +200,49 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => {
return (
<DesktopView>
<div className='container mx-auto pt-10'>
+ <Breadcrumb productId={product.id} productName={product.name} />
<div className='flex'>
<div className='w-full flex flex-wrap'>
<div className='w-5/12'>
<div className='relative mb-2'>
- {product?.flashSale?.remainingTime > 0 && lowestPrice?.price.discountPercentage > 0 && (
- <div className={`absolute bottom-0 w-full`}>
- <div className='absolute bottom-0 w-full h-full'>
- <ImageNext
- src={backgorundFlashSale || '/images/GAMBAR-BG-FLASH-SALE.jpg'}
- width={1000}
- height={100}
- />
- </div>
- <div className='relative'>
- <div className='flex gap-x-2 items-center p-2'>
- <div className='bg-yellow-400 rounded-full p-1 h-9 w-20 flex items-center justify-center '>
- <span className='text-lg font-bold'>
- {Math.floor(product.lowestPrice.discountPercentage)}%
- </span>
- </div>
- <div
- className={`bg-red-600 border border-solid border-yellow-400 rounded-full h-9 p-2 flex w-[50%] items-center justify-center gap-x-4`}
- >
- <ImageNext
- src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg'
- width={17}
- height={10}
- />
- <span className='text-white text-lg font-semibold'>
- {product?.flashSale?.tag != 'false' || product?.flashSale?.tag
- ? product?.flashSale?.tag
- : 'FLASH SALE'}
- </span>
- </div>
- <div>
- <CountDown2 initialTime={product.flashSale.remainingTime} />
+ {product?.flashSale?.remainingTime > 0 &&
+ lowestPrice?.price.discountPercentage > 0 && (
+ <div className={`absolute bottom-0 w-full`}>
+ <div className='absolute bottom-0 w-full h-full'>
+ <ImageNext
+ src={backgorundFlashSale || '/images/GAMBAR-BG-FLASH-SALE.jpg'}
+ width={1000}
+ height={100}
+ />
+ </div>
+ <div className='relative'>
+ <div className='flex gap-x-2 items-center p-2'>
+ <div className='bg-yellow-400 rounded-full p-1 h-9 w-20 flex items-center justify-center '>
+ <span className='text-lg font-bold'>
+ {Math.floor(product.lowestPrice.discountPercentage)}%
+ </span>
+ </div>
+ <div
+ className={`bg-red-600 border border-solid border-yellow-400 rounded-full h-9 p-2 flex w-[50%] items-center justify-center gap-x-4`}
+ >
+ <ImageNext
+ src='/images/ICON_FLASH_SALE_WEBSITE_INDOTEKNIK.svg'
+ width={17}
+ height={10}
+ />
+ <span className='text-white text-lg font-semibold'>
+ {product?.flashSale?.tag != 'false' || product?.flashSale?.tag
+ ? product?.flashSale?.tag
+ : 'FLASH SALE'}
+ </span>
+ </div>
+ <div>
+ <CountDown2 initialTime={product.flashSale.remainingTime} />
+ </div>
</div>
</div>
</div>
- </div>
- )}
+ )}
<Image
src={product.image}
alt={product.name}
@@ -390,7 +393,7 @@ const ProductDesktop = ({ products, wishlist, toggleWishlist }) => {
))}
</div>
<div className='flex'>
- <div className='w-3/4 leading-7 product__description'>
+ <div className='w-3/4 leading-8 product__description'>
<TabContent active={informationTab == 'description'}>
<span
dangerouslySetInnerHTML={{
diff --git a/src/lib/product/components/Product/ProductMobile.jsx b/src/lib/product/components/Product/ProductMobile.jsx
index ffa75f72..402490f7 100644
--- a/src/lib/product/components/Product/ProductMobile.jsx
+++ b/src/lib/product/components/Product/ProductMobile.jsx
@@ -19,6 +19,7 @@ import { gtagAddToCart } from '@/core/utils/googleTag'
import odooApi from '@/core/api/odooApi'
import ImageNext from 'next/image'
import CountDown2 from '@/core/components/elements/CountDown/CountDown2'
+import Breadcrumb from './Breadcrumb'
const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
const router = useRouter()
@@ -160,6 +161,7 @@ const ProductMobile = ({ product, wishlist, toggleWishlist }) => {
return (
<MobileView>
+ <Breadcrumb productId={product.id} productName={product.name} />
<div className='relative'>
{product?.flashSale?.remainingTime > 0 && activeVariant?.price.discountPercentage > 0 && (
<div className={`absolute bottom-0 w-full`}>
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx
index 1072b2ae..3c954548 100644
--- a/src/lib/product/components/ProductSearch.jsx
+++ b/src/lib/product/components/ProductSearch.jsx
@@ -158,7 +158,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
<>
<MobileView>
{productSearch.isLoading && <ProductSearchSkeleton />}
- <div className='p-4'>
+ <div className='p-4 pt-0'>
<h1 className='mb-2 font-semibold text-h-sm'>Produk</h1>
<div className='mb-2 leading-6 text-gray_r-11'>
@@ -238,7 +238,7 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => {
</MobileView>
<DesktopView>
- <div className='container mx-auto mt-10 flex mb-3'>
+ <div className='container mx-auto flex mb-3'>
<div className='w-3/12'>
<ProductFilterDesktop
brands={brands || []}
diff --git a/src/lib/promotinProgram/components/PromotionType.jsx b/src/lib/promotinProgram/components/PromotionType.jsx
index ad7185e3..51f2622a 100644
--- a/src/lib/promotinProgram/components/PromotionType.jsx
+++ b/src/lib/promotinProgram/components/PromotionType.jsx
@@ -24,7 +24,7 @@ const PromotionType = ({
const id = variantId
const listProgram = async () => {
const programs = await getPromotionProgram({ id })
- if (programs.length > 0) {
+ if (programs?.length > 0) {
setPromotionList(programs)
setActiveTitle(programs?.[0].type.value)
}
diff --git a/src/lib/variant/components/VariantCard.jsx b/src/lib/variant/components/VariantCard.jsx
index 64b6d146..6c0ab974 100644
--- a/src/lib/variant/components/VariantCard.jsx
+++ b/src/lib/variant/components/VariantCard.jsx
@@ -40,7 +40,7 @@ const VariantCard = ({ product, openOnClick = true, buyMore = false }) => {
{product.attributes.length > 0 ? ` ・ ${product.attributes.join(', ')}` : ''}
</p>
<p className='text-caption-2 text-gray_r-11 mt-1'>
- Berat Item : {product?.weight} Kg
+ Berat Item : {product?.weight} Kg x {product?.quantity} Barang
</p>
<div className='flex flex-wrap gap-x-1 items-center mt-auto'>
{product.hasFlashsale && (
diff --git a/src/pages/shop/brands/[slug].jsx b/src/pages/shop/brands/[slug].jsx
index 88f19bc0..d75475b7 100644
--- a/src/pages/shop/brands/[slug].jsx
+++ b/src/pages/shop/brands/[slug].jsx
@@ -3,6 +3,7 @@ import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'
import { useRouter } from 'next/router'
import _ from 'lodash'
import Seo from '@/core/components/Seo'
+import Breadcrumb from '@/lib/brand/components/Breadcrumb'
const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch'))
@@ -26,6 +27,8 @@ export default function BrandDetail() {
]}
/>
+ <Breadcrumb brandName={brandName} />
+
<Brand id={getIdFromSlug(slug)} />
{!_.isEmpty(router.query) && (
<ProductSearch
diff --git a/src/pages/shop/cart.jsx b/src/pages/shop/cart.jsx
index a7f2037b..2da58c96 100644
--- a/src/pages/shop/cart.jsx
+++ b/src/pages/shop/cart.jsx
@@ -3,7 +3,9 @@ import BasicLayout from '@/core/components/layouts/BasicLayout'
import DesktopView from '@/core/components/views/DesktopView'
import MobileView from '@/core/components/views/MobileView'
import IsAuth from '@/lib/auth/components/IsAuth'
+import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react'
import dynamic from 'next/dynamic'
+import Link from 'next/link'
const AppLayout = dynamic(() => import('@/core/components/layouts/AppLayout'))
const CartComponent = dynamic(() => import('@/lib/cart/components/Cart'))
@@ -22,6 +24,19 @@ export default function Cart() {
<DesktopView>
<BasicLayout>
+ <div className='container mx-auto py-4 md:py-6 pb-0'>
+ <Breadcrumb>
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500 whitespace-nowrap'>
+ Home
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ <BreadcrumbItem isCurrentPage>
+ <BreadcrumbLink className='whitespace-nowrap'>Keranjang</BreadcrumbLink>
+ </BreadcrumbItem>
+ </Breadcrumb>
+ </div>
<CartComponent />
</BasicLayout>
</DesktopView>
diff --git a/src/pages/shop/category/[slug].jsx b/src/pages/shop/category/[slug].jsx
index dbc17c06..e3650235 100644
--- a/src/pages/shop/category/[slug].jsx
+++ b/src/pages/shop/category/[slug].jsx
@@ -3,6 +3,7 @@ import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'
import { useRouter } from 'next/router'
import _ from 'lodash'
import Seo from '@/core/components/Seo'
+import Breadcrumb from '@/lib/category/components/Breadcrumb'
const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch'))
@@ -16,6 +17,7 @@ export default function CategoryDetail() {
const query = {
fq: `manufacture_id_i:${categoryId}`
}
+
return (
<BasicLayout>
<Seo
@@ -29,6 +31,8 @@ export default function CategoryDetail() {
]}
/>
+ <Breadcrumb categoryId={categoryId} />
+
{!_.isEmpty(router.query) && (
<ProductSearch query={query} prefixUrl={`/shop/category/${slug}`} />
)}
diff --git a/src/pages/shop/product/[slug].jsx b/src/pages/shop/product/[slug].jsx
index 63fb2e7e..4c17ab37 100644
--- a/src/pages/shop/product/[slug].jsx
+++ b/src/pages/shop/product/[slug].jsx
@@ -29,12 +29,6 @@ export async function getServerSideProps(context) {
// let productSolr = null
if (product?.length == 1) {
product = product[0]
- const regexHtmlTags = /(<([^>]+)>)/gi
- const regexHtmlTagsExceptP = /<\/?(?!p\b)[^>]*>/g
- product.description = product.description
- .replace(regexHtmlTagsExceptP, ' ')
- .replace(regexHtmlTags, ' ')
- .trim()
} else {
product = null
}
@@ -45,6 +39,7 @@ export async function getServerSideProps(context) {
}
export default function ProductDetail({ product }) {
+ console.log(product);
const router = useRouter()
const { setProduct } = useProductContext()
diff --git a/src/pages/shop/search.jsx b/src/pages/shop/search.jsx
index 907465b7..db3b449a 100644
--- a/src/pages/shop/search.jsx
+++ b/src/pages/shop/search.jsx
@@ -2,6 +2,8 @@ import dynamic from 'next/dynamic'
import { useRouter } from 'next/router'
import _ from 'lodash-contrib'
import Seo from '@/core/components/Seo'
+import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react'
+import Link from 'next/link'
const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout'))
const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch'))
@@ -13,6 +15,24 @@ export default function Search() {
<BasicLayout>
<Seo title={`Cari produk ${router.query.q || ''} di Indoteknik.com`} />
+ <div className='container mx-auto py-4 md:py-6'>
+ {router.query?.q && (
+ <Breadcrumb>
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500 whitespace-nowrap'>
+ Home
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ <BreadcrumbItem isCurrentPage>
+ <BreadcrumbLink className='whitespace-nowrap'>
+ Cari: {router.query.q || ''}
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+ </Breadcrumb>
+ )}
+ </div>
+
{!_.isEmpty(router.query) && <ProductSearch query={router.query} prefixUrl='/shop/search' />}
</BasicLayout>
)