summaryrefslogtreecommitdiff
path: root/src/lib/category/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/category/components')
-rw-r--r--src/lib/category/components/Breadcrumb.jsx224
1 files changed, 178 insertions, 46 deletions
diff --git a/src/lib/category/components/Breadcrumb.jsx b/src/lib/category/components/Breadcrumb.jsx
index 127904ee..50557c3e 100644
--- a/src/lib/category/components/Breadcrumb.jsx
+++ b/src/lib/category/components/Breadcrumb.jsx
@@ -1,56 +1,188 @@
-import odooApi from '@/core/api/odooApi'
-import { createSlug } from '@/core/utils/slug'
+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.
- */
+ Skeleton,
+} from '@chakra-ui/react';
+import Link from 'next/link';
+import React from 'react';
+import { useQuery } from 'react-query';
+import useDevice from '@/core/hooks/useDevice';
+
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>
- ) : (
+ ['category-breadcrumbs', categoryId],
+ async () =>
+ await odooApi('GET', `/api/v1/category/${categoryId}/category-breadcrumb`)
+ );
+ const { isDesktop, isMobile } = useDevice();
+
+ const items = breadcrumbs.data ?? [];
+ const lastIdx = items.length - 1;
+
+ if (isDesktop) {
+ return (
+ <div className='container mx-auto py-4 md:py-6'>
+ <Skeleton isLoaded={!breadcrumbs.isLoading} className='w-2/3'>
+ <ChakraBreadcrumb
+ spacing='8px'
+ sx={{
+ '& ol': {
+ display: 'flex',
+ flexWrap: { base: 'wrap', md: 'nowrap' },
+ alignItems: 'center',
+ },
+ '& li': { display: 'inline-flex', alignItems: 'center' },
+ '& li:not(:last-of-type)': {
+ flex: '0 0 auto',
+ whiteSpace: 'nowrap',
+ },
+ '& li:last-of-type': {
+ flex: '1 1 auto',
+ minWidth: 0,
+ },
+ }}
+ >
+ {/* Home */}
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500'>
+ Home
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ {/* Categories */}
+ {items.map((category, index) => {
+ const isLast = index === lastIdx;
+ return (
+ <BreadcrumbItem key={index} isCurrentPage={isLast}>
+ {isLast ? (
+ <BreadcrumbLink className='block whitespace-normal break-words md:whitespace-nowrap'>
+ {category.name}
+ </BreadcrumbLink>
+ ) : (
+ <BreadcrumbLink
+ as={Link}
+ href={createSlug(
+ '/shop/category/',
+ category.name,
+ category.id
+ )}
+ className='!text-danger-500'
+ >
+ {category.name}
+ </BreadcrumbLink>
+ )}
+ </BreadcrumbItem>
+ );
+ })}
+ </ChakraBreadcrumb>
+ </Skeleton>
+ </div>
+ );
+ }
+
+ if (isMobile) {
+ const items = breadcrumbs.data ?? [];
+ const n = items.length;
+ const lastCat = n >= 1 ? items[n - 1] : null; // terakhir (current)
+ const secondLast = n >= 2 ? items[n - 2] : null; // sebelum current
+ const beforeSecond = n >= 3 ? items[n - 3] : null; // sebelum secondLast
+ const hiddenText =
+ n >= 3
+ ? items
+ .slice(0, n - 2)
+ .map((c) => c.name)
+ .join(' / ')
+ : '';
+
+ return (
+ <div className='container mx-auto py-2 mt-2'>
+ <Skeleton isLoaded={!breadcrumbs.isLoading} className='w-full'>
+ <ChakraBreadcrumb
+ separator={<span className='mx-1'>/</span>} // lebih rapat
+ spacing='4px'
+ sx={{
+ '& ol': {
+ display: 'flex',
+ alignItems: 'center',
+ overflow: 'hidden', // untuk ellipsis
+ whiteSpace: 'nowrap', // untuk ellipsis
+ gap: '0', // no extra gap
+ },
+ '& li': { display: 'inline-flex', alignItems: 'center' },
+ '& li:not(:last-of-type)': {
+ flex: '0 0 auto',
+ whiteSpace: 'nowrap',
+ },
+ '& li:last-of-type': {
+ flex: '0 1 auto', // jangan ambil full space biar gak keliatan “space kosong”
+ minWidth: 0,
+ },
+ }}
+ className='text-caption-2 p-0'
+ >
+ {/* Home */}
+ <BreadcrumbItem>
+ <BreadcrumbLink as={Link} href='/' className='!text-danger-500'>
+ Home
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+
+ {/* Jika ada kategori sebelum secondLast, tampilkan '..' (link ke beforeSecond) */}
+ {beforeSecond && (
+ <BreadcrumbItem>
<BreadcrumbLink
as={Link}
- href={createSlug('/shop/category/', category.name, category.id)}
- className='!text-danger-500 whitespace-nowrap'
+ href={createSlug(
+ '/shop/category/',
+ beforeSecond.name,
+ beforeSecond.id
+ )}
+ title={hiddenText}
+ aria-label={`Kembali ke ${beforeSecond.name}`}
+ className='!text-danger-500'
>
- {category.name}
+ ..
</BreadcrumbLink>
- )}
- </BreadcrumbItem>
- ))}
- </ChakraBreadcrumb>
- </Skeleton>
- </div>
- )
-}
-
-export default Breadcrumb
+ </BreadcrumbItem>
+ )}
+
+ {/* secondLast sebagai link (kalau ada) */}
+ {secondLast && (
+ <BreadcrumbItem>
+ <BreadcrumbLink
+ as={Link}
+ href={createSlug(
+ '/shop/category/',
+ secondLast.name,
+ secondLast.id
+ )}
+ className='!text-danger-500'
+ >
+ {secondLast.name}
+ </BreadcrumbLink>
+ </BreadcrumbItem>
+ )}
+
+ {/* lastCat (current) dengan truncate & lebar dibatasi */}
+ {lastCat && (
+ <BreadcrumbItem isCurrentPage>
+ <span
+ className='inline-block truncate align-bottom'
+ style={{ maxWidth: '60vw' }} // batasi lebar supaya gak “makan” baris & keliatan space kosong
+ title={lastCat.name}
+ >
+ {lastCat.name}
+ </span>
+ </BreadcrumbItem>
+ )}
+ </ChakraBreadcrumb>
+ </Skeleton>
+ </div>
+ );
+ }
+};
+
+export default Breadcrumb;