summaryrefslogtreecommitdiff
path: root/src-migrate/modules
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2024-01-16 16:08:43 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2024-01-16 16:08:43 +0700
commita70fd5b6d9c7a769ac1aaa22a7d037ba3be27a05 (patch)
tree825d6b5de089bb22003bb2a517d371dc291f1962 /src-migrate/modules
parentd9dafa74857959974e9d379dc1a3abfbaf2af83d (diff)
Update improve product detail performance
Diffstat (limited to 'src-migrate/modules')
-rw-r--r--src-migrate/modules/product-detail/components/AddToWishlist.tsx2
-rw-r--r--src-migrate/modules/product-detail/components/Breadcrumb.tsx40
-rw-r--r--src-migrate/modules/product-detail/components/Image.tsx12
-rw-r--r--src-migrate/modules/product-detail/components/Information.tsx34
-rw-r--r--src-migrate/modules/product-detail/components/PriceAction.tsx10
-rw-r--r--src-migrate/modules/product-detail/components/ProductDetail.tsx68
-rw-r--r--src-migrate/modules/product-detail/components/VariantList.tsx10
7 files changed, 106 insertions, 70 deletions
diff --git a/src-migrate/modules/product-detail/components/AddToWishlist.tsx b/src-migrate/modules/product-detail/components/AddToWishlist.tsx
index eab3c7be..fccbdcf5 100644
--- a/src-migrate/modules/product-detail/components/AddToWishlist.tsx
+++ b/src-migrate/modules/product-detail/components/AddToWishlist.tsx
@@ -6,7 +6,7 @@ const AddToWishlist = () => {
return (
<Button
variant='link'
- className='!text-gray-500 !font-medium'
+ colorScheme='gray'
leftIcon={<HeartIcon size={18} />}
>
Wishlist
diff --git a/src-migrate/modules/product-detail/components/Breadcrumb.tsx b/src-migrate/modules/product-detail/components/Breadcrumb.tsx
new file mode 100644
index 00000000..0ee5b115
--- /dev/null
+++ b/src-migrate/modules/product-detail/components/Breadcrumb.tsx
@@ -0,0 +1,40 @@
+import React, { Fragment } from 'react'
+import { useQuery } from 'react-query'
+import { getProductCategoryBreadcrumb } from '~/services/product'
+import Link from 'next/link'
+import { createSlug } from '~/libs/slug'
+
+type Props = {
+ id: number,
+ name: string
+}
+
+const Breadcrumb = ({ id, name }: Props) => {
+ const query = useQuery({
+ queryKey: ['product-category-breadcrumb'],
+ queryFn: () => getProductCategoryBreadcrumb(id)
+ })
+
+ const breadcrumbs = query.data || []
+
+ return (
+ <div className='line-clamp-3 md:line-clamp-1 leading-7'>
+ <Link href='/' className='text-danger-500'>Home</Link>
+ <span className='mx-2'>/</span>
+ {breadcrumbs.map((category, index) => (
+ <Fragment key={index}>
+ <Link
+ href={createSlug('/shop/category/', category.name, category.id.toString())}
+ className='text-danger-500'
+ >
+ {category.name}
+ </Link>
+ <span className='mx-2'>/</span>
+ </Fragment>
+ ))}
+ <span>{name}</span>
+ </div>
+ )
+}
+
+export default Breadcrumb \ No newline at end of file
diff --git a/src-migrate/modules/product-detail/components/Image.tsx b/src-migrate/modules/product-detail/components/Image.tsx
index 361580ea..2c5e989b 100644
--- a/src-migrate/modules/product-detail/components/Image.tsx
+++ b/src-migrate/modules/product-detail/components/Image.tsx
@@ -11,14 +11,16 @@ type Props = {
const Image = ({ product }: Props) => {
return (
- <div className='h-[340px] border border-gray-200 rounded-lg p-2 relative'>
+ <div className='h-[250px] md:h-[340px] flex items-center justify-center border border-gray-200 rounded-lg p-4 relative'>
<ImageUI
src={product.image || '/images/noimage.jpeg'}
alt={product.name}
- width={512}
- height={512}
- className='object-contain object-center h-full'
- classNames={{ wrapper: 'h-full' }}
+ width={256}
+ height={256}
+ className='object-contain object-center h-full w-full'
+ classNames={{ wrapper: 'h-full w-full' }}
+ loading='eager'
+ priority
/>
<div className='absolute hidden md:block top-4 right-4'>
<Tooltip
diff --git a/src-migrate/modules/product-detail/components/Information.tsx b/src-migrate/modules/product-detail/components/Information.tsx
index fd0e0b3c..52eb6b88 100644
--- a/src-migrate/modules/product-detail/components/Information.tsx
+++ b/src-migrate/modules/product-detail/components/Information.tsx
@@ -9,6 +9,7 @@ import { IProductDetail } from '~/types/product'
import { IProductVariantSLA } from '~/types/productVariant'
import { createSlug } from '~/libs/slug'
import { getVariantSLA } from '~/services/productVariant'
+import { formatToShortText } from '~/libs/formatNumber'
const Skeleton = dynamic(() => import('@chakra-ui/react').then((mod) => mod.Skeleton))
@@ -31,10 +32,6 @@ const Information = ({ product }: Props) => {
<div className={style['label']}>SKU Number</div>
<div className={style['value']}>SKU-{product.id}</div>
</div>
- {/* <div className={style['row']}>
- <div className={style['label']}>Part Number</div>
- <div className={style['value']}>{product.code || '-'}</div>
- </div> */}
<div className={style['row']}>
<div className={style['label']}>Manufacture</div>
<div className={style['value']}>
@@ -48,35 +45,10 @@ const Information = ({ product }: Props) => {
) : '-'}
</div>
</div>
- {/* <div className={style['row']}>
- <div className={style['label']}>Preparation Time</div>
- <div className={style['value']}>
- {product.variant_total > 1 && 'Lihat Variant'}
- {product.variant_total === 1 && (
- <Skeleton isLoaded={querySLA.isSuccess} w={querySLA.isSuccess ? '100%' : '40px'} h='100%'>
- {sla?.sla_date}
- </Skeleton>
- )}
- </div>
- </div>
<div className={style['row']}>
- <div className={style['label']}>Stock</div>
- <div className={style['value']}>
- {product.variant_total > 1 && 'Lihat Variant'}
- {product.variant_total === 1 && (
- <Skeleton isLoaded={querySLA.isSuccess} w={querySLA.isSuccess ? '100%' : '10px'} h='100%'>
- {sla?.qty && sla.qty > 0 ? sla?.qty : '-'}
- </Skeleton>
- )}
- </div>
+ <div className={style['label']}>Terjual</div>
+ <div className={style['value']}>{product.qty_sold > 0 ? formatToShortText(product.qty_sold) : '-'}</div>
</div>
- <div className={style['row']}>
- <div className={style['label']}>Weight</div>
- <div className={style['value']}>
- {product.variant_total > 1 && 'Lihat Variant'}
- {product.variant_total === 1 && (product.weight > 0 ? `${product.weight} kg` : '-')}
- </div>
- </div> */}
</div>
)
}
diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx
index cfb596fa..dd211f6f 100644
--- a/src-migrate/modules/product-detail/components/PriceAction.tsx
+++ b/src-migrate/modules/product-detail/components/PriceAction.tsx
@@ -28,13 +28,6 @@ const PriceAction = ({ product }: Props) => {
return (
<div className='block md:sticky top-[150px] bg-white py-0 md:py-6 z-10'>
- {product.qty_sold > 0 && (
- <div className={style['secondary-text']}>
- {formatToShortText(product.qty_sold)} Terjual
- </div>
- )}
- <div className='h-2' />
-
{!!activePrice && activePrice.price > 0 && (
<>
<div className={style['main-price']}>
@@ -60,7 +53,8 @@ const PriceAction = ({ product }: Props) => {
<div className='h-4' />
<div className={style['action-wrapper']}>
- <input type='number' value={quantityInput} onChange={(e) => setQuantityInput(e.target.value)} className={style['quantity-input']} />
+ <label htmlFor="quantity" className='hidden'>Quantity</label>
+ <input type='number' id='quantity' value={quantityInput} onChange={(e) => setQuantityInput(e.target.value)} className={style['quantity-input']} />
<AddToCart variantId={activeVariantId} quantity={Number(quantityInput)} />
<AddToCart source='buy' variantId={activeVariantId} quantity={Number(quantityInput)} />
</div>
diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx
index 08ad7d51..93fa7118 100644
--- a/src-migrate/modules/product-detail/components/ProductDetail.tsx
+++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx
@@ -2,28 +2,34 @@ import style from '../styles/product-detail.module.css'
import React, { useEffect } from 'react'
import Link from 'next/link'
-import { MessageCircleIcon } from 'lucide-react'
+import { useRouter } from 'next/router'
+
+import { MessageCircleIcon, Share2Icon } from 'lucide-react'
import { Button } from '@chakra-ui/react'
import { IProductDetail } from '~/types/product'
+import useDevice from '@/core/hooks/useDevice'
+import { whatsappUrl } from '~/libs/whatsappUrl'
+import { useProductDetail } from '../stores/useProductDetail'
+
+import { RWebShare } from 'react-web-share'
import ProductImage from './Image'
import Information from './Information'
import AddToWishlist from './AddToWishlist'
import VariantList from './VariantList'
import SimilarSide from './SimilarSide'
import SimilarBottom from './SimilarBottom'
-import useDevice from '@/core/hooks/useDevice'
import PriceAction from './PriceAction'
-import { whatsappUrl } from '~/libs/whatsappUrl'
-import { useRouter } from 'next/router'
-import { useProductDetail } from '../stores/useProductDetail'
import ProductPromoSection from '~/modules/product-promo/components/Section'
+import Breadcrumb from './Breadcrumb'
type Props = {
product: IProductDetail
}
+const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST
+
const ProductDetail = ({ product }: Props) => {
const { isDesktop, isMobile } = useDevice()
const router = useRouter()
@@ -46,6 +52,9 @@ const ProductDetail = ({ product }: Props) => {
return (
<>
<div className='md:flex md:flex-wrap'>
+ <div className="w-full mb-4 md:mb-6 px-4 md:px-0">
+ <Breadcrumb id={product.id} name={product.name} />
+ </div>
<div className='md:w-9/12 md:flex md:flex-col md:pr-4'>
<div className='md:flex md:flex-wrap'>
<div className="md:w-4/12">
@@ -63,18 +72,39 @@ const ProductDetail = ({ product }: Props) => {
<Information product={product} />
- <div className='h-4' />
+ <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 />
+
+ <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
- as={Link}
- href={askAdminUrl}
- variant='link'
- target='_blank'
- colorScheme='red'
- leftIcon={<MessageCircleIcon size={18} />}
- >
- Ask Admin
- </Button>
</div>
</div>
@@ -117,9 +147,7 @@ const ProductDetail = ({ product }: Props) => {
<div className="md:w-3/12">
<PriceAction product={product} />
- <AddToWishlist />
-
- <div className='h-8' />
+ <div className='h-6' />
<div className={style['heading']}>
Produk Serupa
@@ -131,7 +159,7 @@ const ProductDetail = ({ product }: Props) => {
</div>
)}
- <div className='md:w-full py-0 md:py-10 px-4 md:px-0'>
+ <div className='md:w-full pt-4 md:py-10 px-4 md:px-0'>
<div className={style['heading']}>
Kamu Mungkin Juga Suka
</div>
diff --git a/src-migrate/modules/product-detail/components/VariantList.tsx b/src-migrate/modules/product-detail/components/VariantList.tsx
index 96b7486b..e8c18921 100644
--- a/src-migrate/modules/product-detail/components/VariantList.tsx
+++ b/src-migrate/modules/product-detail/components/VariantList.tsx
@@ -22,10 +22,10 @@ const VariantList = ({ variants }: Props) => {
<div className={style['header']}>
<div className="w-2/12 sticky left-0 bg-gray-200">Part Number</div>
<div className="w-2/12">Variant</div>
- <div className="w-2/12">Stock</div>
+ <div className="w-1/12">Stock</div>
<div className="w-2/12">Masa Persiapan</div>
<div className="w-1/12">Berat</div>
- <div className="w-2/12">Harga</div>
+ <div className="w-3/12">Harga</div>
</div>
{variants.map((variant) => (
<LazyLoadComponent key={variant.id}>
@@ -49,8 +49,8 @@ const Row = ({ variant }: { variant: IProductVariantDetail }) => {
return (
<div className={style['row']}>
<div className='w-2/12 sticky left-0 bg-white md:bg-transparent'>{variant.code}</div>
- <div className='w-2/12'>{variant.attributes.join(', ')}</div>
- <div className='w-2/12'>
+ <div className='w-2/12'>{variant.attributes.join(', ') || '-'}</div>
+ <div className='w-1/12'>
<Skeleton isLoaded={querySLA.isSuccess} h='21px' w={16}>
{sla?.qty !== undefined && (
<>
@@ -68,7 +68,7 @@ const Row = ({ variant }: { variant: IProductVariantDetail }) => {
<div className='w-1/12'>
{variant.weight > 0 ? `${variant.weight} Kg` : '-'}
</div>
- <div className='w-2/12'>
+ <div className='w-3/12'>
{variant.price.price > 0 && `Rp ${formatCurrency(variant.price.price)}`}
{variant.price.price === 0 && '-'}
</div>