diff options
| author | Miqdad <ahmadmiqdad27@gmail.com> | 2025-08-26 12:04:46 +0700 |
|---|---|---|
| committer | Miqdad <ahmadmiqdad27@gmail.com> | 2025-08-26 12:04:46 +0700 |
| commit | 2403eae1686c565364691022d294123a16f4f031 (patch) | |
| tree | bb4d7ecb245c95f820b32d6ebb21980a81ac5a89 | |
| parent | bcf7be5a0c1d9635383605afc0600386b0b356ea (diff) | |
<Miqdad> Fix Breadcrumb & image
| -rw-r--r-- | src-migrate/modules/product-detail/components/Breadcrumb.tsx | 139 | ||||
| -rw-r--r-- | src-migrate/modules/product-detail/components/ProductDetail.tsx | 4 |
2 files changed, 108 insertions, 35 deletions
diff --git a/src-migrate/modules/product-detail/components/Breadcrumb.tsx b/src-migrate/modules/product-detail/components/Breadcrumb.tsx index ba53aca4..d495b77b 100644 --- a/src-migrate/modules/product-detail/components/Breadcrumb.tsx +++ b/src-migrate/modules/product-detail/components/Breadcrumb.tsx @@ -1,68 +1,141 @@ import React, { Fragment } from 'react'; import { useQuery } from 'react-query'; -import { getProductCategoryBreadcrumb } from '~/services/product'; import Link from 'next/link'; +import { getProductCategoryBreadcrumb } from '~/services/product'; import { createSlug } from '~/libs/slug'; +import useDevice from '@/core/hooks/useDevice'; -type Props = { - id: number; - name: string; -}; - -const MAX_VISIBLE_CATEGORIES = 2; // tampilkan 2 level terakhir +type Props = { id: number; name: string }; const Breadcrumb = ({ id, name }: Props) => { + const { isDesktop, isMobile } = useDevice(); + const { data: breadcrumbs = [] } = useQuery({ - queryKey: ['product-category-breadcrumb', id], // penting: ikutkan id + queryKey: ['product-category-breadcrumb', id], queryFn: () => getProductCategoryBreadcrumb(id), refetchOnWindowFocus: false, }); const total = breadcrumbs.length; - const showEllipsis = total > MAX_VISIBLE_CATEGORIES; - const visible = showEllipsis - ? breadcrumbs.slice(total - MAX_VISIBLE_CATEGORIES) - : breadcrumbs; - const hiddenText = showEllipsis + const lastCat = total ? breadcrumbs[total - 1] : null; + const hasHidden = total > 1; + const hiddenText = hasHidden ? breadcrumbs - .slice(0, total - MAX_VISIBLE_CATEGORIES) + .slice(0, total - 1) .map((c) => c.name) .join(' / ') : ''; - return ( - <div className='flex items-center whitespace-nowrap overflow-hidden text-caption-1 leading-7'> - <Link href='/' className='text-danger-500 shrink-0'> + // ===== MOBILE: Home + .. + lastCat + product (truncate) ===== + if (isMobile) { + const crumbsMobile: React.ReactNode[] = []; + + // Home + crumbsMobile.push( + <Link href='/' className='text-danger-500 shrink-0' key='home'> Home </Link> - <span className='mx-2 shrink-0'>/</span> + ); + + // Indicator kategori tersembunyi (tanpa slash bawaan) + if (hasHidden) { + crumbsMobile.push( + <span + className='text-danger-500 shrink-0' + title={hiddenText} + aria-label='Kategori tersembunyi' + key='hidden' + > + .. + </span> + ); + } - {showEllipsis && ( - <> - <span className='text-danger-500 shrink-0' title={hiddenText}> - … - </span> - <span className='mx-2 shrink-0'>/</span> - </> - )} + // Kategori terakhir + if (lastCat) { + crumbsMobile.push( + <Link + key={`cat-${lastCat.id}`} + href={createSlug('/shop/category/', lastCat.name, String(lastCat.id))} + className='text-danger-500 shrink-0' + > + {lastCat.name} + </Link> + ); + } - {visible.map((category, index) => ( - <Fragment key={category.id ?? index}> + // Nama produk (dipotong bila tidak muat) + crumbsMobile.push( + <span className='truncate min-w-0 flex-1' title={name} key='product'> + {name} + </span> + ); + + return ( + <div className='flex items-center whitespace-nowrap overflow-hidden text-caption-1 leading-7'> + {crumbsMobile.map((node, i) => ( + <Fragment key={i}> + {node} + {i < crumbsMobile.length - 1 && ( + <span className='mx-2 shrink-0'>/</span> + )} + </Fragment> + ))} + </div> + ); + } + + // ===== DESKTOP: biarkan seperti semula ===== + if (isDesktop) { + return ( + <div className='line-clamp-2 md:line-clamp-1 leading-7 text-caption-1'> + <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> + ); + } + + // Fallback → layout desktop + return ( + <div className='line-clamp-2 md:line-clamp-1 leading-7 text-caption-1'> + <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, - String(category.id) + category.id.toString() )} - className='text-danger-500 shrink-0' + className='text-danger-500' > {category.name} </Link> - <span className='mx-2 shrink-0'>/</span> + <span className='mx-2'>/</span> </Fragment> ))} - - <span className='truncate min-w-0 flex-1'>{name}</span> + <span>{name}</span> </div> ); }; diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index 8ecdb2fc..35df97df 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -161,7 +161,7 @@ return ( <img src={img} alt={`Gambar ${i + 1}`} - className='w-[80%] max-w-[320px] aspect-square object-contain' + className='w-[80%] aspect-square object-contain' onError={(e) => { (e.target as HTMLImageElement).src = '/path/to/fallback-image.jpg'; @@ -174,7 +174,7 @@ return ( <img src={mainImage || '/path/to/fallback-image.jpg'} alt='Gambar produk' - className='w-[80%] max-w-[320px] aspect-square object-contain' + className='w-[80%] aspect-square object-contain' /> </div> )} |
