From 6b173eaf8a95432316822b1d41b084875adfbd83 Mon Sep 17 00:00:00 2001 From: "tri.susilo" Date: Wed, 8 May 2024 14:47:11 +0700 Subject: [agnes] - Feature category management --- src/lib/category/components/Category.jsx | 79 ++++++++++++++++++++------ src/lib/home/components/CategoryPilihan.jsx | 32 +++++++++++ src/lib/product/components/CategorySection.jsx | 22 +++++++ src/lib/product/components/ProductSearch.jsx | 20 +++++++ 4 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 src/lib/home/components/CategoryPilihan.jsx create mode 100644 src/lib/product/components/CategorySection.jsx (limited to 'src/lib') diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx index e6ea5acf..c147a3b3 100644 --- a/src/lib/category/components/Category.jsx +++ b/src/lib/category/components/Category.jsx @@ -2,10 +2,14 @@ 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' const Category = () => { const [categories, setCategories] = useState([]) + const [openCategories, setOpenCategory] = useState([]); + useEffect(() => { const loadCategories = async () => { @@ -31,7 +35,7 @@ const Category = () => {
{categories?.map((category) => ( -
+
{ {category.name}
-
+
{category.childs.map((child1Category) => ( -
+
{child1Category.name} -
- {child1Category.childs.map((child2Category) => ( - - {child2Category.name} - +
+ {child1Category.childs.map((child2Category, index) => ( + (index < 4) && ( + + {child2Category.name} + + ) ))} + {child1Category.childs.length > 5 && ( +
+ +

Lihat Semua

+ + +
+ )}
))}
+
+
+
+ {category.childs.map((brand, index) => ( + (index < 8 ) && ( +
+ + + +
+ ) + ))} +
+ {category.childs.length > 8 && ( +
+ +

Lihat Semua Brand

+ + +
+ )} +
+
+ +
+
))} diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx new file mode 100644 index 00000000..c506ef29 --- /dev/null +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -0,0 +1,32 @@ +import Image from 'next/image' +import useCategoryHome from '../hooks/useCategoryHome' + +const CategoryPilihan = ({ id, categories }) => { + const { categoryHome } = useCategoryHome({ id }) + + return ( +
+
+

Kategori Pilihan

+

total produk

+
+
+ {categories.map((category) => ( +
+ +
+

{category?.name}

+
+
+ ))} +
+
+ ) +} + +export default CategoryPilihan diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx new file mode 100644 index 00000000..7c347fe8 --- /dev/null +++ b/src/lib/product/components/CategorySection.jsx @@ -0,0 +1,22 @@ +import Image from "next/image" + +const CategorySection = ({ categories }) => { + return ( +
+
+ {categories.map((category) => ( +
+
+ {category?.name} +
+
+

{category?.name}

+
+
+ ))} +
+
+ ) +} + +export default CategorySection \ No newline at end of file diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 08b64c13..253c3703 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -26,6 +26,8 @@ import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton'; import SideBanner from '~/modules/side-banner'; import FooterBanner from '~/modules/footer-banner'; +import CategorySection from './CategorySection'; +import { getIdFromSlug } from '@/core/utils/slug' const ProductSearch = ({ query, @@ -68,6 +70,10 @@ const ProductSearch = ({ const productStart = productSearch.data?.responseHeader.params.start; const productRows = limit; const productFound = productSearch.data?.response.numFound; + const [dataCategories, setDataCategories] = useState([]) + + const categoryId = getIdFromSlug(prefixUrl) + useEffect(() => { if (productFound == 0 && query.q && !spellings) { @@ -116,6 +122,18 @@ const ProductSearch = ({ } }, [q]); + useEffect(() => { + const loadCategories = async () => { + const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() + }, []) + + console.log('Data Category : ', dataCategories) + const brands = []; for ( let i = 0; @@ -409,7 +427,9 @@ const ProductSearch = ({
+
+ {bannerPromotionHeader && bannerPromotionHeader?.image && (
Date: Wed, 3 Jul 2024 08:34:16 +0700 Subject: update category management --- src/lib/home/components/CategoryPilihan.jsx | 38 ++++++++++++++++---------- src/lib/product/components/CategorySection.jsx | 22 +++++++++------ src/lib/product/components/ProductSearch.jsx | 7 ++--- 3 files changed, 39 insertions(+), 28 deletions(-) (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index c506ef29..3f1066e2 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -1,30 +1,40 @@ import Image from 'next/image' import useCategoryHome from '../hooks/useCategoryHome' +import Link from '@/core/components/elements/Link/Link' +import { createSlug } from '@/core/utils/slug' const CategoryPilihan = ({ id, categories }) => { const { categoryHome } = useCategoryHome({ id }) - + console.log("id",id) + console.log("categories",categories) return (
-
-

Kategori Pilihan

-

total produk

+
+
Kategori Pilihan
+

200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!

-
+
{categories.map((category) => ( -
-
- {category?.name} - +
+
+
+
+ {category?.name} +
+

{category?.name}

+
-
-

{category?.name}

+
+ + Lihat semua +
))} -
+
) } diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 7c347fe8..c250efeb 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -1,20 +1,24 @@ import Image from "next/image" +import Link from '@/core/components/elements/Link/Link' +import { createSlug } from '@/core/utils/slug' const CategorySection = ({ categories }) => { return ( -
-
+
+
{categories.map((category) => ( -
-
- {category?.name} -
-
-

{category?.name}

+
+
+
+
+ {category?.name} +
+

{category?.name}

+
))} -
+
) } diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 253c3703..29cf94da 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -74,7 +74,6 @@ const ProductSearch = ({ const categoryId = getIdFromSlug(prefixUrl) - useEffect(() => { if (productFound == 0 && query.q && !spellings) { searchSpellApi({ query: query.q }).then((response) => { @@ -121,18 +120,16 @@ const ProductSearch = ({ checkIfBrand(); } }, [q]); - + useEffect(() => { const loadCategories = async () => { - const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) + const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) if(getCategories){ setDataCategories(getCategories) } } loadCategories() }, []) - - console.log('Data Category : ', dataCategories) const brands = []; for ( -- cgit v1.2.3 From 1a70984f3497652b8d8b64d16053c1f2be452bd7 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 5 Jul 2024 10:06:49 +0700 Subject: update category management --- src/lib/home/components/CategoryPilihan.jsx | 34 ++++++++++++++++++++++---- src/lib/product/components/CategorySection.jsx | 22 ++++++++--------- 2 files changed, 40 insertions(+), 16 deletions(-) (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 3f1066e2..4a1106b0 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -2,17 +2,41 @@ 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'; + const CategoryPilihan = ({ id, categories }) => { - const { categoryHome } = useCategoryHome({ id }) - console.log("id",id) - console.log("categories",categories) - return ( -
+ const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'index-a-1' })); + + return ( +
Kategori Pilihan

200 Rb+ Produk Unggulan & 800+ Brand Rekomendasi tersedia!

+
+ {heroBanner.data && + heroBanner.data?.length > 0 && ( +
+ {/* {heroBanner.data?.map((banner) => ( */} + + {heroBanner.data[0].name} + + {/* ))} */} +
+ + )} +
{categories.map((category) => (
diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index c250efeb..4c66e861 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -1,26 +1,26 @@ import Image from "next/image" -import Link from '@/core/components/elements/Link/Link' +import Link from 'next/link' import { createSlug } from '@/core/utils/slug' const CategorySection = ({ categories }) => { return (
-
+
{categories.map((category) => ( -
-
-
-
- {category?.name} + +
+
+
+ {category?.name} +

{category?.name}

-

{category?.name}

-
+ ))} -
+
) } -export default CategorySection \ No newline at end of file +export default CategorySection -- cgit v1.2.3 From 59cba752134fa41063956569a3f4e7ed2a6d2537 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 8 Jul 2024 08:48:29 +0700 Subject: add dynamic category --- src/lib/home/components/CategoryDynamic.jsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/lib/home/components/CategoryDynamic.jsx (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx new file mode 100644 index 00000000..59a1858b --- /dev/null +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -0,0 +1,9 @@ +const CategoryDynamic = ({}) =>{ + return( +
+ DISINI CATEGORY DYNAMIC +
+ ) +}; + +export default CategoryDynamic; \ No newline at end of file -- cgit v1.2.3 From 0840f5ccc7493dfa091508db84bad8a21e073268 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 18 Jul 2024 17:24:36 +0700 Subject: update category-management --- src/lib/home/components/CategoryDynamic.jsx | 95 ++++++++++++++++++++++++++--- src/lib/home/hooks/useCategoryManagement.js | 34 +++++++++++ 2 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 src/lib/home/hooks/useCategoryManagement.js (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index 59a1858b..e3052d11 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -1,9 +1,90 @@ -const CategoryDynamic = ({}) =>{ - return( -
- DISINI CATEGORY DYNAMIC -
- ) +import React, { useEffect, useState } from 'react'; +import {fetchProductManagementSolr} from '../hooks/useCategoryManagement'; +import NextImage from 'next/image'; +import Link from "next/link" +import router from 'next/router'; +import { createSlug } from '@/core/utils/slug' + +const CategoryDynamic = () => { + const [promoItems, setPromoItems] = useState([]); + useEffect(() => { + const loadPromo = async () => { + + try { + const items = await fetchProductManagementSolr(); + setPromoItems(items); + + } catch (loadError) { + // console.error("Error loading promo items:", loadError) + } + } + + + loadPromo() + + },[]); + + const image = 'https://erp.indoteknik.com/api/image/product.template/image_256/544371?ratio=square' + const handleLink = (name, id) => { + return `/shop/category/${name}/${id}`; }; -export default CategoryDynamic; \ No newline at end of file + console.log("promoItems",promoItems) + + return ( +
+
Kategori Pilihan
+ {/* Render category data */} + {promoItems && promoItems.map((category) => ( +
+
+
{category.name}
+

999 rb+ Produk tersedia

+ Lihat Semua +
+

+ Kategori level 1 : {category.name} - ID level 1 : {category.id} + +

+
+ {category.category_id2.map((index)=> ( +
+

+ id LEVEL 2: {index.id_level_2} - Name LEVEL 2: {index.name} + +

+ {index.child_frontend_id_i.map((x)=> ( +
+

+ id LEVEL 3: {x.id_level_3} - name LEVEL 3: {x.name} + +

+
+ ))} +
+

+
+ ))} +
+
+ ))} +
+ ); +} + +export default CategoryDynamic; diff --git a/src/lib/home/hooks/useCategoryManagement.js b/src/lib/home/hooks/useCategoryManagement.js new file mode 100644 index 00000000..7c01df6e --- /dev/null +++ b/src/lib/home/hooks/useCategoryManagement.js @@ -0,0 +1,34 @@ +export const fetchProductManagementSolr = async () => { + try { + const queryParams = new URLSearchParams({q: 'type_value_s:bundling'}) + const response = await fetch(`/solr/product_category_management/query?q=*:*&q.op=OR&indent=true`); + // console.log("response", response) + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + // console.log("data",data) + const dataManagement = await map(data.response.docs); + // console.log("dataManagement",dataManagement) + return dataManagement; + } 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, + category_id: promotion.category_id_i, + name: promotion.name_s, + sequence: promotion.sequence_i, + image: promotion.image_s, + category_id2: JSON.parse(promotion.category_id2_s), + }; + result.push(data); + } + return result; +}; -- cgit v1.2.3 From 8564ea1361d40560679df6823b28dfc7e02ab197 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 19 Jul 2024 16:45:46 +0700 Subject: update view category dynamic --- src/lib/home/components/CategoryDynamic.jsx | 81 +++++++++++++---------------- src/lib/home/hooks/useCategoryManagement.js | 2 +- 2 files changed, 38 insertions(+), 45 deletions(-) (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index e3052d11..4180438a 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -18,66 +18,59 @@ const CategoryDynamic = () => { // console.error("Error loading promo items:", loadError) } } - - loadPromo() },[]); - - const image = 'https://erp.indoteknik.com/api/image/product.template/image_256/544371?ratio=square' - const handleLink = (name, id) => { - return `/shop/category/${name}/${id}`; -}; console.log("promoItems",promoItems) return (
-
Kategori Pilihan
+ {/*
Kategori Pilihan
*/} {/* Render category data */} {promoItems && promoItems.map((category) => (
-
+
{category.name}

999 rb+ Produk tersedia

- Lihat Semua + Lihat Semua
-

- Kategori level 1 : {category.name} - ID level 1 : {category.id} - -

-
+
{category.category_id2.map((index)=> ( -
-

- id LEVEL 2: {index.id_level_2} - Name LEVEL 2: {index.name} - -

- {index.child_frontend_id_i.map((x)=> ( -
-

- id LEVEL 3: {x.id_level_3} - name LEVEL 3: {x.name} - -

-
- ))} +
+
+
+ +
+
{index.name}
+

999 rb+ Produk

+ Lihat Semua +
+
+
+ {index.child_frontend_id_i.map((x)=> ( +
+ + +
+
{x.name}
+
+ +
+ ))}
-

+
))}
diff --git a/src/lib/home/hooks/useCategoryManagement.js b/src/lib/home/hooks/useCategoryManagement.js index 7c01df6e..db4e79e1 100644 --- a/src/lib/home/hooks/useCategoryManagement.js +++ b/src/lib/home/hooks/useCategoryManagement.js @@ -1,7 +1,7 @@ export const fetchProductManagementSolr = async () => { try { const queryParams = new URLSearchParams({q: 'type_value_s:bundling'}) - const response = await fetch(`/solr/product_category_management/query?q=*:*&q.op=OR&indent=true`); + const response = await fetch(`/solr/product_category_management/query?q=*:*&q.op=OR&sort=sequence_i asc&indent=true`); // console.log("response", response) if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); -- cgit v1.2.3 From 911e0fdc6beb2f97c7e390a6aec5773202189d68 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 19 Jul 2024 17:07:23 +0700 Subject: update mobile view --- src/lib/home/components/CategoryDynamicMobile.jsx | 69 +++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/lib/home/components/CategoryDynamicMobile.jsx (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx new file mode 100644 index 00000000..a550bd62 --- /dev/null +++ b/src/lib/home/components/CategoryDynamicMobile.jsx @@ -0,0 +1,69 @@ +import React, { useEffect, useState } from 'react'; +import {fetchProductManagementSolr} from '../hooks/useCategoryManagement'; +import NextImage from 'next/image'; +import Link from "next/link" +import router from 'next/router'; +import { createSlug } from '@/core/utils/slug' +import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; + +const CategoryDynamicMobile = () => { + const [promoItems, setPromoItems] = useState([]); + useEffect(() => { + const loadPromo = async () => { + + try { + const items = await fetchProductManagementSolr(); + setPromoItems(items); + + } catch (loadError) { + // console.error("Error loading promo items:", loadError) + } + } + loadPromo() + + },[]); + + console.log("promoItems",promoItems) + + return ( +
+ {/*
Kategori Pilihan
*/} + {/* Render category data */} + {promoItems && promoItems.map((category) => ( +
+
+
{category.name}
+ Lihat Semua +
+ + {category.category_id2.map((index)=> ( + +
+
+
+ +
+
{index.name}
+

999 rb+ Produk

+ Lihat Semua +
+
+
+
+
+ ))} +
+
+ ))} +
+ ); +} + +export default CategoryDynamicMobile; -- cgit v1.2.3 From d6b459b3ea396775fae25b44d34c8dc724379224 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 20 Jul 2024 11:45:41 +0700 Subject: update mobile view --- src/lib/home/components/CategoryDynamic.jsx | 14 ++-- src/lib/home/components/CategoryDynamicMobile.jsx | 97 +++++++++++++++-------- src/lib/home/components/CategoryPilihan.jsx | 2 +- src/lib/product/components/CategorySection.jsx | 51 +++++++++--- src/lib/product/components/ProductSearch.jsx | 1 + 5 files changed, 111 insertions(+), 54 deletions(-) (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index 4180438a..244543be 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -26,22 +26,20 @@ const CategoryDynamic = () => { return (
- {/*
Kategori Pilihan
*/} - {/* Render category data */} {promoItems && promoItems.map((category) => (
{category.name}

999 rb+ Produk tersedia

- Lihat Semua + Lihat Semua
{category.category_id2.map((index)=> ( -
+
-
+
{
{index.child_frontend_id_i.map((x)=> (
- + { +const CategoryDynamicMobile = () => { const [promoItems, setPromoItems] = useState([]); + const [selectedCategory, setSelectedCategory] = useState({}); + useEffect(() => { const loadPromo = async () => { - try { const items = await fetchProductManagementSolr(); setPromoItems(items); - + if (items.length > 0) { + const initialSelections = items.reduce((acc, category) => { + if (category.category_id2.length > 0) { + acc[category.id] = category.category_id2[0].id_level_2; + } + return acc; + }, {}); + setSelectedCategory(initialSelections); + } } catch (loadError) { // console.error("Error loading promo items:", loadError) } - } - loadPromo() + }; + loadPromo(); + }, []); - },[]); - - console.log("promoItems",promoItems) + const handleCategoryLevel2Click = (categoryLevel1Id, categoryLevel2Id) => { + setSelectedCategory(prev => ({ + ...prev, + [categoryLevel1Id]: categoryLevel2Id + })); + }; return (
- {/*
Kategori Pilihan
*/} - {/* Render category data */} {promoItems && promoItems.map((category) => (
-
{category.name}
- Lihat Semua +
{category.name}
+ Lihat Semua
- {category.category_id2.map((index)=> ( - -
-
-
+ {category.category_id2.map((index) => ( + +
handleCategoryLevel2Click(category.id, index?.id_level_2)} + className={`border flex justify-start items-center max-w-48 max-h-16 rounded ${selectedCategory[category.id] === index?.id_level_2 ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} + > +
+
-
-
{index.name}
-

999 rb+ Produk

- Lihat Semua +
+
{index.name}
+

999 rb+ Produk

+
-
-
+ ))} +
+
+ {category.category_id2.map((index) => ( + selectedCategory[category.id] === index?.id_level_2 && index.child_frontend_id_i.map((x) => ( +
+ + +
+
{x.name}
+
+ +
+ )) + ))} +
+
))}
); -} +}; export default CategoryDynamicMobile; diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 4a1106b0..409a8918 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -43,7 +43,7 @@ const CategoryPilihan = ({ id, categories }) => {
- {category?.name} + {category?.name}

{category?.name}

diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 4c66e861..278bda94 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -1,24 +1,49 @@ 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'; const CategorySection = ({ categories }) => { + const { isDesktop, isMobile } = useDevice(); return (
-
- {categories.map((category) => ( - -
-
-
- {category?.name} -

{category?.name}

+ {isDesktop && +
+ {categories.map((category) => ( + +
+
+
+ {category?.name} +

{category?.name}

+
-
- - ))} -
+ + ))} +
+ } + {isMobile && +
+ + {categories.map((category) => ( + + +
+
+
+ {category?.name} +

{category?.name}

+
+
+
+ +
+ ))} +
+
+ }
) } diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 29cf94da..c4970b21 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -336,6 +336,7 @@ const ProductSearch = ({ SpellingComponent )}
+ {productFound > 0 && (
-- cgit v1.2.3 From 1a3bef5d01fb50ad731f269f0a76b5c5fd52813d Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 22 Jul 2024 16:56:30 +0700 Subject: { return ( diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index 571c4745..fc899665 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -1,4 +1,5 @@ -import { Swiper, SwiperSlide } from 'swiper/react' +import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; +import { Navigation, Pagination, Autoplay } from 'swiper'; import usePreferredBrand from '../hooks/usePreferredBrand' import PreferredBrandSkeleton from './Skeleton/PreferredBrandSkeleton' import BrandCard from '@/lib/brand/components/BrandCard' @@ -10,6 +11,22 @@ const PreferredBrand = () => { let params = 'prioritas' 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, + } + } return (
@@ -21,16 +38,18 @@ const PreferredBrand = () => { )}
- {preferredBrands.isLoading && } - {!preferredBrands.isLoading && ( - - {preferredBrands.data?.data.map((brand) => ( - - - - ))} - - )} +
+ {preferredBrands.isLoading && } + {!preferredBrands.isLoading && ( + + {preferredBrands.data?.data.map((brand) => ( + + + + ))} + + )} +
) } -- cgit v1.2.3 From a78251dc5cdfdd5438aad3ce7b7e342fceb7275e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 22 Jul 2024 16:57:47 +0700 Subject: update category management --- src/lib/home/components/CategoryDynamic.jsx | 4 -- src/lib/product/components/CategorySection.jsx | 67 +++++++++++++++++++------- 2 files changed, 50 insertions(+), 21 deletions(-) (limited to 'src/lib') diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index 244543be..2edd5485 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -19,11 +19,7 @@ const CategoryDynamic = () => { } } loadPromo() - },[]); - - console.log("promoItems",promoItems) - return (
{promoItems && promoItems.map((category) => ( diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 278bda94..e80429f4 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -4,44 +4,77 @@ 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' + const CategorySection = ({ categories }) => { const { isDesktop, isMobile } = useDevice(); + const router = useRouter() + + let teks = router.query.slug; + let hasil = teks?.match(/(\d+)$/)[0]; + + const breadcrumbs = useQuery( + `category-breadcrumbs/${hasil}`, + async () => await odooApi('GET', `/api/v1/category/${hasil}/category-breadcrumb`) + ) + return (
- {isDesktop && + {isDesktop && (
- {categories.map((category) => ( + {categories.slice(0, 10).map((category) => (
- {category?.name} -

{category?.name}

+ {category?.name} +

{category?.name}

))}
- } + )} + {isDesktop && categories.length > 10 && ( +
+ Lihat Semua + +
+ )} + {isMobile &&
- {categories.map((category) => ( - - -
-
-
- {category?.name} -

{category?.name}

-
-
+ {categories.slice(0, 10).map((category) => ( + + +
+
+
+ {category?.name} +

+ {category?.name} +

- +
+
+
- ))} + ))} + {categories.length > 10 && ( +
+ Lihat Semua + +
+ )}
}
-- cgit v1.2.3 From bf5c3b1d48da54e0e44689412ad9de9c10cf9edb Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 09:28:21 +0700 Subject: update category management --- src/lib/home/api/categoryManagementApi.js | 8 +++++ src/lib/home/components/CategoryDynamic.jsx | 32 ++++++----------- src/lib/home/components/CategoryDynamicMobile.jsx | 41 +++++++++++---------- src/lib/home/components/CategoryPilihan.jsx | 2 +- src/lib/home/hooks/useCategoryManagement.js | 43 ++++++----------------- src/lib/product/components/CategorySection.jsx | 10 +++--- 6 files changed, 55 insertions(+), 81 deletions(-) create mode 100644 src/lib/home/api/categoryManagementApi.js (limited to 'src/lib') diff --git a/src/lib/home/api/categoryManagementApi.js b/src/lib/home/api/categoryManagementApi.js new file mode 100644 index 00000000..b70d60ce --- /dev/null +++ b/src/lib/home/api/categoryManagementApi.js @@ -0,0 +1,8 @@ +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 index 2edd5485..cac8a138 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -1,36 +1,24 @@ import React, { useEffect, useState } from 'react'; -import {fetchProductManagementSolr} from '../hooks/useCategoryManagement'; +import useCategoryManagement from '../hooks/useCategoryManagement'; import NextImage from 'next/image'; import Link from "next/link" import router from 'next/router'; import { createSlug } from '@/core/utils/slug' -const CategoryDynamic = () => { - const [promoItems, setPromoItems] = useState([]); - useEffect(() => { - const loadPromo = async () => { - - try { - const items = await fetchProductManagementSolr(); - setPromoItems(items); - - } catch (loadError) { - // console.error("Error loading promo items:", loadError) - } - } - loadPromo() - },[]); +const CategoryDynamic = () => { + const { categoryManagement } = useCategoryManagement() + return (
- {promoItems && promoItems.map((category) => ( + {categoryManagement && categoryManagement.data?.map((category) => (
{category.name}

999 rb+ Produk tersedia

- Lihat Semua + Lihat Semua
- {category.category_id2.map((index)=> ( + {category.categories.map((index)=> (
@@ -44,13 +32,13 @@ const CategoryDynamic = () => {
{index.name}

999 rb+ Produk

- Lihat Semua + Lihat Semua
- {index.child_frontend_id_i.map((x)=> ( + {index.childFrontendIdI.map((x)=> (
- + { - const [promoItems, setPromoItems] = useState([]); + const { categoryManagement } = useCategoryManagement() const [selectedCategory, setSelectedCategory] = useState({}); useEffect(() => { const loadPromo = async () => { try { - const items = await fetchProductManagementSolr(); - setPromoItems(items); - if (items.length > 0) { - const initialSelections = items.reduce((acc, category) => { - if (category.category_id2.length > 0) { - acc[category.id] = category.category_id2[0].id_level_2; + 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) + // console.error("Error loading promo items:", loadError); } }; + loadPromo(); - }, []); + }, [categoryManagement.data]); - const handleCategoryLevel2Click = (categoryLevel1Id, categoryLevel2Id) => { + const handleCategoryLevel2Click = (categoryIdI, idLevel2) => { setSelectedCategory(prev => ({ ...prev, - [categoryLevel1Id]: categoryLevel2Id + [categoryIdI]: idLevel2 })); }; - + return (
- {promoItems && promoItems.map((category) => ( + {categoryManagement.data && categoryManagement.data.map((category) => (
{category.name}
- Lihat Semua + Lihat Semua
- {category.category_id2.map((index) => ( + {category.categories.map((index) => (
handleCategoryLevel2Click(category.id, index?.id_level_2)} - className={`border flex justify-start items-center max-w-48 max-h-16 rounded ${selectedCategory[category.id] === index?.id_level_2 ? 'bg-red-50 border-red-500 text-red-500' : 'border-gray-200 text-gray-900'}`} + 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'}`} >
@@ -74,10 +73,10 @@ const CategoryDynamicMobile = () => {
- {category.category_id2.map((index) => ( - selectedCategory[category.id] === index?.id_level_2 && index.child_frontend_id_i.map((x) => ( + {category.categories.map((index) => ( + selectedCategory[category.id] === index?.idLevel2 && index.childFrontendIdI.map((x) => (
- + {
- {category?.name} + {category?.name}

{category?.name}

diff --git a/src/lib/home/hooks/useCategoryManagement.js b/src/lib/home/hooks/useCategoryManagement.js index db4e79e1..c1dda585 100644 --- a/src/lib/home/hooks/useCategoryManagement.js +++ b/src/lib/home/hooks/useCategoryManagement.js @@ -1,34 +1,13 @@ -export const fetchProductManagementSolr = async () => { - try { - const queryParams = new URLSearchParams({q: 'type_value_s:bundling'}) - const response = await fetch(`/solr/product_category_management/query?q=*:*&q.op=OR&sort=sequence_i asc&indent=true`); - // console.log("response", response) - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - const data = await response.json(); - // console.log("data",data) - const dataManagement = await map(data.response.docs); - // console.log("dataManagement",dataManagement) - return dataManagement; - } catch (error) { - console.error("Error fetching promotion data:", error); - return []; - } -}; +import categoryManagementApi from '../api/categoryManagementApi' +import { useQuery } from 'react-query' + +const useCategoryManagement = () => { + const fetchCategoryManagement = async () => await categoryManagementApi() + const { isLoading, data } = useQuery('categoryManagementApi', fetchCategoryManagement) -const map = async (promotions) => { - const result = []; - for (const promotion of promotions) { - const data = { - id: promotion.id, - category_id: promotion.category_id_i, - name: promotion.name_s, - sequence: promotion.sequence_i, - image: promotion.image_s, - category_id2: JSON.parse(promotion.category_id2_s), - }; - result.push(data); + return { + categoryManagement: { data, isLoading } } - return result; -}; +} + +export default useCategoryManagement \ No newline at end of file diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index e80429f4..749a56eb 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -25,10 +25,10 @@ const CategorySection = ({ categories }) => {
{categories.slice(0, 10).map((category) => ( -
-
-
- {category?.name} +
+
+
+ {category?.name}

{category?.name}

@@ -54,7 +54,7 @@ const CategorySection = ({ categories }) => {
{category?.name} Date: Tue, 23 Jul 2024 14:29:08 +0700 Subject: update categories management --- src/lib/brand/components/BrandCard.jsx | 6 +- src/lib/home/components/CategoryDynamic.jsx | 119 ++++++++++++++----------- src/lib/home/components/PreferredBrand.jsx | 44 +++++++-- src/lib/product/components/CategorySection.jsx | 109 +++++++++++++--------- 4 files changed, 176 insertions(+), 102 deletions(-) (limited to 'src/lib') diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx index 39b1aec1..2d78d956 100644 --- a/src/lib/brand/components/BrandCard.jsx +++ b/src/lib/brand/components/BrandCard.jsx @@ -16,9 +16,9 @@ const BrandCard = ({ brand }) => { {brand.name} )} {!brand.logo && ( diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index cac8a138..fa1df286 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -1,65 +1,84 @@ import React, { useEffect, useState } from 'react'; -import useCategoryManagement from '../hooks/useCategoryManagement'; +import useCategoryManagement from '../hooks/useCategoryManagement'; import NextImage from 'next/image'; -import Link from "next/link" +import Link from "next/link"; import router from 'next/router'; -import { createSlug } from '@/core/utils/slug' +import { createSlug } from '@/core/utils/slug'; + +const CategoryDynamic = () => { + const { categoryManagement } = useCategoryManagement(); + + const calculateLevel3Products = (category) => { + return category.childFrontendIdI.reduce((total, child) => total + (child.numFound || 0), 0); + }; + + const calculateLevel2Products = (category) => { + return category.categories.reduce((total, subCategory) => { + const level3Products = calculateLevel3Products(subCategory); + return total + (subCategory.numFound || 0) + level3Products; + }, 0); + }; -const CategoryDynamic = () => { - const { categoryManagement } = useCategoryManagement() - return (
- {categoryManagement && categoryManagement.data?.map((category) => ( -
-
+ {categoryManagement && categoryManagement.data?.map((category) => { + const countLevel2 = calculateLevel2Products(category); + + return ( +
+
{category.name}
-

999 rb+ Produk tersedia

+

{countLevel2} Produk tersedia

Lihat Semua -
-
- {category.categories.map((index)=> ( -
-
-
- -
-
{index.name}
-

999 rb+ Produk

- Lihat Semua +
+
+ {category.categories.map((subCategory) => { + const countLevel3 = calculateLevel3Products(subCategory); + + return ( +
+
+
+ +
+
{subCategory.name}
+

{(subCategory.numFound || 0) + countLevel3} Produk

+ Lihat Semua +
+
+
+ {subCategory.childFrontendIdI.map((childCategory) => ( +
+ + +
+
{childCategory.name}
+
+ +
+ ))}
-
- {index.childFrontendIdI.map((x)=> ( -
- - -
-
{x.name}
-
- -
- ))} -
-
-
- ))} +
+ ); + })} +
-
- ))} + ); + })}
); -} +}; export default CategoryDynamic; diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index fc899665..ae12505d 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -1,14 +1,42 @@ -import { Swiper, SwiperProps, SwiperSlide } from 'swiper/react'; +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' import BrandCard from '@/lib/brand/components/BrandCard' import useDevice from '@/core/hooks/useDevice' import Link from '@/core/components/elements/Link/Link' +import axios from 'axios' const PreferredBrand = () => { let query = 'level_s' let params = 'prioritas' + const [isLoading, setIsLoading] = useState(true) + const [startWith, setStartWith] = useState(null) + const [manufactures, setManufactures] = useState([]) + + const loadBrand = useCallback(async () => { + setIsLoading(true) + const name = startWith ? `${startWith}*` : '' + const result = await axios(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/brands?params=${name}`) + + setIsLoading(false) + setManufactures((manufactures) => [...result.data]) + }, [startWith]) + + const toggleStartWith = (alphabet) => { + setManufactures([]) + if (alphabet == startWith) { + setStartWith(null) + return + } + setStartWith(alphabet) + } + + useEffect(() => { + loadBrand() + }, [loadBrand]) + const { preferredBrands } = usePreferredBrand(query) const { isMobile, isDesktop } = useDevice() const swiperBanner = { @@ -27,7 +55,7 @@ const PreferredBrand = () => { clickable: true, } } - + const preferredBrandsData = manufactures ? manufactures.slice(0, 20) : [] return (
@@ -39,12 +67,12 @@ const PreferredBrand = () => { )}
- {preferredBrands.isLoading && } - {!preferredBrands.isLoading && ( + {manufactures.isLoading && } + {!manufactures.isLoading && ( - {preferredBrands.data?.data.map((brand) => ( - - + {preferredBrandsData.map((manufacture) => ( + + ))} @@ -54,4 +82,4 @@ const PreferredBrand = () => { ) } -export default PreferredBrand +export default PreferredBrand \ No newline at end of file diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 749a56eb..14a39e7e 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -1,15 +1,23 @@ -import Image from "next/image" -import Link from 'next/link' -import { createSlug } from '@/core/utils/slug' +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 { 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 const CategorySection = ({ categories }) => { const { isDesktop, isMobile } = useDevice(); - const router = useRouter() + const router = useRouter(); + const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility let teks = router.query.slug; let hasil = teks?.match(/(\d+)$/)[0]; @@ -17,18 +25,24 @@ const CategorySection = ({ categories }) => { const breadcrumbs = useQuery( `category-breadcrumbs/${hasil}`, async () => await odooApi('GET', `/api/v1/category/${hasil}/category-breadcrumb`) - ) - + ); + + const handleToggleCategories = () => { + setIsOpenCategory(!isOpenCategory); + }; + + const displayedCategories = isOpenCategory ? categories : categories.slice(0, 10); + return (
{isDesktop && (
- {categories.slice(0, 10).map((category) => ( + {displayedCategories.map((category) => (
-
- {category?.name} +
+ {category?.name}

{category?.name}

@@ -38,45 +52,58 @@ const CategorySection = ({ categories }) => {
)} {isDesktop && categories.length > 10 && ( -
- Lihat Semua - -
+
+ +
)} - {isMobile && + {isMobile && (
- {categories.slice(0, 10).map((category) => ( - - -
-
-
- {category?.name} -

- {category?.name} -

-
-
-
- -
- ))} + {displayedCategories.map((category) => ( + + +
+
+
+ {category?.name} +

+ {category?.name} +

+
+
+
+ +
+ ))}
- {categories.length > 10 && ( + {categories.length > 10 && (
- Lihat Semua - +
)}
- } + )}
) } -- cgit v1.2.3