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 +++++++ src/pages/index.jsx | 22 ++++++- src/pages/shop/category/[slug].jsx | 9 ++- src/styles/globals.css | 5 +- 7 files changed, 166 insertions(+), 23 deletions(-) create mode 100644 src/lib/home/components/CategoryPilihan.jsx create mode 100644 src/lib/product/components/CategorySection.jsx 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 && (
import('@/core/components/layouts/BasicLayout') @@ -52,7 +55,7 @@ const CustomerReviews = dynamic(() => ); const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList')); -export default function Home() { +export default function Home({categoryId}) { const bannerRef = useRef(null); const wrapperRef = useRef(null); @@ -61,6 +64,18 @@ export default function Home() { bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px'; }; + const [dataCategories, setDataCategories] = useState([]) + + useEffect(() => { + const loadCategories = async () => { + const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() + }, []) + return ( - + + {/* */}
diff --git a/src/pages/shop/category/[slug].jsx b/src/pages/shop/category/[slug].jsx index 1afe30bf..11840d47 100644 --- a/src/pages/shop/category/[slug].jsx +++ b/src/pages/shop/category/[slug].jsx @@ -5,6 +5,8 @@ import { useRouter } from 'next/router'; import Seo from '@/core/components/Seo'; import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'; import Breadcrumb from '@/lib/category/components/Breadcrumb'; +import { useEffect, useState } from 'react'; +import odooApi from '@/core/api/odooApi'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') @@ -12,10 +14,14 @@ const BasicLayout = dynamic(() => const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch') ); +const CategorySection = dynamic(() => + import('@/lib/product/components/CategorySection') +) export default function CategoryDetail() { const router = useRouter(); const { slug = '', page = 1 } = router.query; + const [dataCategories, setDataCategories] = useState([]) const categoryName = getNameFromSlug(slug); const categoryId = getIdFromSlug(slug); @@ -43,8 +49,9 @@ export default function CategoryDetail() { + {!_.isEmpty(router.query) && ( - + )} ); diff --git a/src/styles/globals.css b/src/styles/globals.css index f6561b00..505dcab4 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -583,12 +583,11 @@ button { @apply absolute left-[100%] top-12 - w-[40vw] bg-gray_r-1/90 backdrop-blur-md border border-gray_r-6 - p-6 + p-6 opacity-0 h-full transition-all @@ -604,6 +603,7 @@ button { transition-colors ease-linear duration-100 + w-fit font-semibold; } @@ -613,6 +613,7 @@ button { transition-colors ease-linear duration-100 + w-full font-normal; } -- cgit v1.2.3 From 6c79d14a11c8dba20778c0559230a406cd147cc7 Mon Sep 17 00:00:00 2001 From: it-fixcomart 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(-) 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(-) 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 +++++++++ src/pages/index.jsx | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 src/lib/home/components/CategoryDynamic.jsx 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 diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 9675c355..149352c2 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -12,6 +12,7 @@ import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBran import PromotinProgram from '@/lib/promotinProgram/components/HomePage'; import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; +import CategoryDynamic from '../lib/home/components/CategoryDynamic'; import odooApi from '@/core/api/odooApi'; import { getIdFromSlug } from '@/core/utils/slug' @@ -120,6 +121,7 @@ export default function Home({categoryId}) { + {/* */} -- cgit v1.2.3 From bc7c0d1891db37ad314bd5016e19917e0f1e63be Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 17 Jul 2024 15:38:45 +0700 Subject: update error code --- src/api/promoApi.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/promoApi.js b/src/api/promoApi.js index f262db8d..3f85db8e 100644 --- a/src/api/promoApi.js +++ b/src/api/promoApi.js @@ -13,11 +13,11 @@ export const fetchPromoItems = async (type) => { } }; -export const fetchPromoItemsSolr = async (type) => { +export const fetchPromoItemsSolr = async (type, start, rows) => { // let query = type ? `type_value_s:${type}` : '*:*'; let sort ='sort=if(exists(sequence_i),0,1) asc, sequence_i asc, if(exists(total_qty_sold_f), total_qty_sold_f, -1) desc'; - let start = 0 - let rows = 100 + // let start = 0 + // let rows = 100 // let start = 0 // let rows = 10 try { -- 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 +++++++++++ src/pages/index.jsx | 9 ++- 3 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 src/lib/home/hooks/useCategoryManagement.js 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; +}; diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 149352c2..b5d004ca 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -12,7 +12,7 @@ import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBran import PromotinProgram from '@/lib/promotinProgram/components/HomePage'; import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; -import CategoryDynamic from '../lib/home/components/CategoryDynamic'; +// import CategoryDynamic from '../lib/home/components/CategoryDynamic'; import odooApi from '@/core/api/odooApi'; import { getIdFromSlug } from '@/core/utils/slug' @@ -51,6 +51,11 @@ const BannerSection = dynamic(() => const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId') ); + +const CategoryDynamic = dynamic(() => + import('@/lib/home/components/CategoryDynamic') +); + const CustomerReviews = dynamic(() => import('@/lib/review/components/CustomerReviews') ); @@ -122,7 +127,7 @@ export default function Home({categoryId}) { - {/* */} +
-- 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(-) 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 +++++++++++++++++++++++ src/pages/index.jsx | 8 +++ 2 files changed, 77 insertions(+) create mode 100644 src/lib/home/components/CategoryDynamicMobile.jsx 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; diff --git a/src/pages/index.jsx b/src/pages/index.jsx index b5d004ca..0255e239 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -56,6 +56,10 @@ const CategoryDynamic = dynamic(() => import('@/lib/home/components/CategoryDynamic') ); +const CategoryDynamicMobile = dynamic(() => + import('@/lib/home/components/CategoryDynamicMobile') +); + const CustomerReviews = dynamic(() => import('@/lib/review/components/CustomerReviews') ); @@ -153,6 +157,10 @@ export default function Home({categoryId}) { + + {/* */} + + -- 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(-) 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 a181665f20207db5617d794df8159483fef0c2a8 Mon Sep 17 00:00:00 2001 From: trisusilo48 Date: Mon, 22 Jul 2024 11:16:47 +0700 Subject: no message --- src/lib/product/components/ProductCard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 818dbbcf..3b5fab28 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -18,7 +18,7 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { let voucherPastiHemat = 0; - if (product?.voucherPastiHemat.length > 0) { + if (product?.voucherPastiHemat?.length > 0) { const stringVoucher = product?.voucherPastiHemat[0]; const validJsonString = stringVoucher.replace(/'/g, '"'); voucherPastiHemat = JSON.parse(validJsonString); -- 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 +++++++++++++++++++------- src/pages/index.jsx | 2 +- 3 files changed, 51 insertions(+), 22 deletions(-) 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 + +
+ )}
}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 0255e239..cdbe0dd0 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -158,7 +158,7 @@ export default function Home({categoryId}) { - {/* */} + -- 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 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 09:42:57 +0700 Subject: marged develompent & category management --- src/lib/brand/components/BrandCard.jsx | 2 +- src/lib/category/components/Category.jsx | 79 +++++++++++++---- src/lib/home/api/categoryManagementApi.js | 8 ++ src/lib/home/components/CategoryDynamic.jsx | 65 ++++++++++++++ src/lib/home/components/CategoryDynamicMobile.jsx | 101 ++++++++++++++++++++++ src/lib/home/components/CategoryPilihan.jsx | 66 ++++++++++++++ src/lib/home/components/PreferredBrand.jsx | 42 ++++++--- src/lib/home/hooks/useCategoryManagement.js | 13 +++ src/lib/product/components/CategorySection.jsx | 84 ++++++++++++++++++ src/lib/product/components/ProductSearch.jsx | 18 ++++ src/pages/index.jsx | 35 +++++++- src/pages/shop/category/[slug].jsx | 9 +- src/styles/globals.css | 5 +- 13 files changed, 492 insertions(+), 35 deletions(-) create mode 100644 src/lib/home/api/categoryManagementApi.js create mode 100644 src/lib/home/components/CategoryDynamic.jsx create mode 100644 src/lib/home/components/CategoryDynamicMobile.jsx create mode 100644 src/lib/home/components/CategoryPilihan.jsx create mode 100644 src/lib/home/hooks/useCategoryManagement.js create mode 100644 src/lib/product/components/CategorySection.jsx diff --git a/src/lib/brand/components/BrandCard.jsx b/src/lib/brand/components/BrandCard.jsx index 731214ff..39b1aec1 100644 --- a/src/lib/brand/components/BrandCard.jsx +++ b/src/lib/brand/components/BrandCard.jsx @@ -8,7 +8,7 @@ const BrandCard = ({ brand }) => { return ( 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/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 new file mode 100644 index 00000000..cac8a138 --- /dev/null +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -0,0 +1,65 @@ +import React, { useEffect, useState } from 'react'; +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 { categoryManagement } = useCategoryManagement() + + return ( +
+ {categoryManagement && categoryManagement.data?.map((category) => ( +
+
+
{category.name}
+

999 rb+ Produk tersedia

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

999 rb+ Produk

+ Lihat Semua +
+
+
+ {index.childFrontendIdI.map((x)=> ( +
+ + +
+
{x.name}
+
+ +
+ ))} +
+
+
+ ))} +
+
+ ))} +
+ ); +} + +export default CategoryDynamic; diff --git a/src/lib/home/components/CategoryDynamicMobile.jsx b/src/lib/home/components/CategoryDynamicMobile.jsx new file mode 100644 index 00000000..c1433a2d --- /dev/null +++ b/src/lib/home/components/CategoryDynamicMobile.jsx @@ -0,0 +1,101 @@ +import React, { useEffect, useState } from 'react'; +import useCategoryManagement from '../hooks/useCategoryManagement'; +import NextImage from 'next/image'; +import Link from "next/link"; +import { createSlug } from '@/core/utils/slug'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; + +const CategoryDynamicMobile = () => { + const { categoryManagement } = useCategoryManagement() + const [selectedCategory, setSelectedCategory] = useState({}); + + useEffect(() => { + const loadPromo = async () => { + try { + 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); + } + }; + + loadPromo(); + }, [categoryManagement.data]); + + const handleCategoryLevel2Click = (categoryIdI, idLevel2) => { + setSelectedCategory(prev => ({ + ...prev, + [categoryIdI]: idLevel2 + })); + }; + + return ( +
+ {categoryManagement.data && categoryManagement.data.map((category) => ( +
+
+
{category.name}
+ Lihat Semua +
+ + {category.categories.map((index) => ( + +
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'}`} + > +
+
+ +
+
{index.name}
+

999 rb+ Produk

+
+
+
+
+
+ ))} +
+
+
+ {category.categories.map((index) => ( + selectedCategory[category.id] === index?.idLevel2 && index.childFrontendIdI.map((x) => ( +
+ + +
+
{x.name}
+
+ +
+ )) + ))} +
+
+
+ ))} +
+ ); +}; + +export default CategoryDynamicMobile; diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx new file mode 100644 index 00000000..7b9f0094 --- /dev/null +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -0,0 +1,66 @@ +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 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) => ( +
+
+
+
+ {category?.name} +
+

{category?.name}

+
+
+
+ + Lihat semua + +
+
+ ))} +
+
+ ) +} + +export default CategoryPilihan diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index 6b64a444..1aa9746b 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -1,5 +1,5 @@ -import { Swiper, SwiperSlide } from 'swiper/react' -import { useCallback, useEffect, useState } from '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' @@ -38,6 +38,22 @@ const PreferredBrand = () => { 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 (
@@ -54,16 +70,18 @@ const PreferredBrand = () => { )}
- {manufactures.isLoading && } - {!manufactures.isLoading && ( - - {manufactures.map((manufacture) => ( - - - - ))} - - )} +
+ {preferredBrands.isLoading && } + {!preferredBrands.isLoading && ( + + {preferredBrands.data?.data.map((brand) => ( + + + + ))} + + )} +
) } diff --git a/src/lib/home/hooks/useCategoryManagement.js b/src/lib/home/hooks/useCategoryManagement.js new file mode 100644 index 00000000..c1dda585 --- /dev/null +++ b/src/lib/home/hooks/useCategoryManagement.js @@ -0,0 +1,13 @@ +import categoryManagementApi from '../api/categoryManagementApi' +import { useQuery } from 'react-query' + +const useCategoryManagement = () => { + const fetchCategoryManagement = async () => await categoryManagementApi() + const { isLoading, data } = useQuery('categoryManagementApi', fetchCategoryManagement) + + return { + categoryManagement: { data, isLoading } + } +} + +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 new file mode 100644 index 00000000..749a56eb --- /dev/null +++ b/src/lib/product/components/CategorySection.jsx @@ -0,0 +1,84 @@ +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' + +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 && ( +
+ {categories.slice(0, 10).map((category) => ( + +
+
+
+ {category?.name} +

{category?.name}

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

+ {category?.name} +

+
+
+
+ +
+ ))} +
+ {categories.length > 10 && ( +
+ Lihat Semua + +
+ )} +
+ } +
+ ) +} + +export default CategorySection diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index b1a5d409..34018ffe 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,9 @@ 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) { @@ -115,6 +120,16 @@ const ProductSearch = ({ checkIfBrand(); } }, [q]); + + useEffect(() => { + const loadCategories = async () => { + const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() + }, []) const brands = []; for ( @@ -323,6 +338,7 @@ const ProductSearch = ({ SpellingComponent )}
+ {productFound > 0 && (
@@ -411,7 +427,9 @@ const ProductSearch = ({
+
+ {bannerPromotionHeader && bannerPromotionHeader?.image && (
const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId') ); + +const CategoryDynamic = dynamic(() => + import('@/lib/home/components/CategoryDynamic') +); + +const CategoryDynamicMobile = dynamic(() => + import('@/lib/home/components/CategoryDynamicMobile') +); + const CustomerReviews = dynamic(() => import('@/lib/review/components/CustomerReviews') ); const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList')); -export default function Home() { +export default function Home({categoryId}) { const bannerRef = useRef(null); const wrapperRef = useRef(null); @@ -70,6 +83,18 @@ export default function Home() { bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px'; }; + const [dataCategories, setDataCategories] = useState([]) + + useEffect(() => { + const loadCategories = async () => { + const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() + }, []) + return ( )} + + @@ -150,6 +177,10 @@ export default function Home() { + + + + diff --git a/src/pages/shop/category/[slug].jsx b/src/pages/shop/category/[slug].jsx index 1afe30bf..11840d47 100644 --- a/src/pages/shop/category/[slug].jsx +++ b/src/pages/shop/category/[slug].jsx @@ -5,6 +5,8 @@ import { useRouter } from 'next/router'; import Seo from '@/core/components/Seo'; import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'; import Breadcrumb from '@/lib/category/components/Breadcrumb'; +import { useEffect, useState } from 'react'; +import odooApi from '@/core/api/odooApi'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') @@ -12,10 +14,14 @@ const BasicLayout = dynamic(() => const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch') ); +const CategorySection = dynamic(() => + import('@/lib/product/components/CategorySection') +) export default function CategoryDetail() { const router = useRouter(); const { slug = '', page = 1 } = router.query; + const [dataCategories, setDataCategories] = useState([]) const categoryName = getNameFromSlug(slug); const categoryId = getIdFromSlug(slug); @@ -43,8 +49,9 @@ export default function CategoryDetail() { + {!_.isEmpty(router.query) && ( - + )} ); diff --git a/src/styles/globals.css b/src/styles/globals.css index f6561b00..505dcab4 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -583,12 +583,11 @@ button { @apply absolute left-[100%] top-12 - w-[40vw] bg-gray_r-1/90 backdrop-blur-md border border-gray_r-6 - p-6 + p-6 opacity-0 h-full transition-all @@ -604,6 +603,7 @@ button { transition-colors ease-linear duration-100 + w-fit font-semibold; } @@ -613,6 +613,7 @@ button { transition-colors ease-linear duration-100 + w-full font-normal; } -- cgit v1.2.3 From cf48c684d2f8da4dd70e2ed0f57623169bc5106f Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 10:01:58 +0700 Subject: update error code --- src/lib/home/components/PreferredBrand.jsx | 34 +----------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index 1aa9746b..f822b9a0 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -5,37 +5,10 @@ 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 = { @@ -64,11 +37,6 @@ const PreferredBrand = () => { Lihat Semua )} - {isMobile && ( - - Lihat Semua - - )}
{preferredBrands.isLoading && } @@ -86,4 +54,4 @@ const PreferredBrand = () => { ) } -export default PreferredBrand +export default PreferredBrand \ No newline at end of file -- cgit v1.2.3 From 1d770053ce0b75eab1d3755085d03c9d32fe3a83 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 10:07:46 +0700 Subject: update error log --- src/lib/home/components/CategoryPilihan.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 7b9f0094..73e42626 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -20,7 +20,7 @@ const CategoryPilihan = ({ id, categories }) => {
{heroBanner.data && heroBanner.data?.length > 0 && ( -
+
{/* {heroBanner.data?.map((banner) => ( */} {
{categories.map((category) => ( -
+
-- cgit v1.2.3 From b1341b76e94da9e64549768646bb54d2836976d0 Mon Sep 17 00:00:00 2001 From: it-fixcomart 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(-) 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 From 2fbfdb7a3d090b0ad8dae5527464b25e5df65c25 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 14:40:23 +0700 Subject: Merge branch 'Feature/category-management' into development # Conflicts: # src/lib/home/components/CategoryDynamic.jsx # src/lib/home/components/CategoryPilihan.jsx # src/lib/home/components/PreferredBrand.jsx # src/lib/product/components/CategorySection.jsx # src/pages/index.jsx --- src/pages/index.jsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index db868470..0f2add9a 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -64,13 +64,13 @@ const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId') ); -const CategoryDynamic = dynamic(() => - import('@/lib/home/components/CategoryDynamic') -); +// const CategoryDynamic = dynamic(() => +// import('@/lib/home/components/CategoryDynamic') +// ); -const CategoryDynamicMobile = dynamic(() => - import('@/lib/home/components/CategoryDynamicMobile') -); +// const CategoryDynamicMobile = dynamic(() => +// import('@/lib/home/components/CategoryDynamicMobile') +// ); const CategoryDynamic = dynamic(() => @@ -86,7 +86,7 @@ const CustomerReviews = dynamic(() => ); const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList')); -export default function Home({categoryId}) { + export default function Home({categoryId}) { const bannerRef = useRef(null); const wrapperRef = useRef(null); @@ -98,7 +98,7 @@ export default function Home({categoryId}) { bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px'; }; - const [dataCategories, setDataCategories] = useState([]) + // const [dataCategories, setDataCategories] = useState([]) useEffect(() => { const loadCategories = async () => { -- cgit v1.2.3 From ca30fe957369a16f6833d6a3bd37df74182b2911 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 14:45:17 +0700 Subject: update error code --- src/pages/index.jsx | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 0f2add9a..c720547e 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -1,7 +1,5 @@ import dynamic from 'next/dynamic'; import { useEffect, useRef, useState } from 'react'; -import { useEffect, useRef, useState } from 'react'; - import { HeroBannerSkeleton } from '@/components/skeleton/BannerSkeleton'; import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton'; import Seo from '@/core/components/Seo'; @@ -13,15 +11,8 @@ import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBran import PromotinProgram from '@/lib/promotinProgram/components/HomePage'; import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; -// import CategoryDynamic from '../lib/home/components/CategoryDynamic'; import odooApi from '@/core/api/odooApi'; -import { getIdFromSlug } from '@/core/utils/slug' -import useProductDetail from '~/modules/product-detail/stores/useProductDetail'; import { getAuth } from '~/libs/auth'; -import CategoryPilihan from '../lib/home/components/CategoryPilihan'; -// import CategoryDynamic from '../lib/home/components/CategoryDynamic'; -import odooApi from '@/core/api/odooApi'; -import { getIdFromSlug } from '@/core/utils/slug' const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') @@ -64,15 +55,6 @@ const CategoryHomeId = dynamic(() => import('@/lib/home/components/CategoryHomeId') ); -// const CategoryDynamic = dynamic(() => -// import('@/lib/home/components/CategoryDynamic') -// ); - -// const CategoryDynamicMobile = dynamic(() => -// import('@/lib/home/components/CategoryDynamicMobile') -// ); - - const CategoryDynamic = dynamic(() => import('@/lib/home/components/CategoryDynamic') ); -- cgit v1.2.3 From f6e0632292b1600341fccfd9d14c1ffe1be0f309 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 14:46:42 +0700 Subject: update error code --- src/pages/index.jsx | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index cdbe0dd0..578c4e2d 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -1,6 +1,5 @@ import dynamic from 'next/dynamic'; import { useEffect, useRef, useState } from 'react'; - import { HeroBannerSkeleton } from '@/components/skeleton/BannerSkeleton'; import { PopularProductSkeleton } from '@/components/skeleton/PopularProductSkeleton'; import Seo from '@/core/components/Seo'; @@ -12,9 +11,8 @@ import PreferredBrandSkeleton from '@/lib/home/components/Skeleton/PreferredBran import PromotinProgram from '@/lib/promotinProgram/components/HomePage'; import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; -// import CategoryDynamic from '../lib/home/components/CategoryDynamic'; import odooApi from '@/core/api/odooApi'; -import { getIdFromSlug } from '@/core/utils/slug' +import { getAuth } from '~/libs/auth'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') @@ -45,6 +43,11 @@ const FlashSale = dynamic( loading: () => , } ); + +const ProgramPromotion = dynamic(() => + import('@/lib/home/components/PromotionProgram') +); + const BannerSection = dynamic(() => import('@/lib/home/components/BannerSection') ); @@ -65,17 +68,18 @@ const CustomerReviews = dynamic(() => ); const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList')); + export default function Home({categoryId}) { const bannerRef = useRef(null); const wrapperRef = useRef(null); + const auth = getAuth(); + const handleOnLoad = () => { wrapperRef.current.style.height = bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px'; }; - const [dataCategories, setDataCategories] = useState([]) - useEffect(() => { const loadCategories = async () => { const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) @@ -86,6 +90,8 @@ export default function Home({categoryId}) { loadCategories() }, []) + const [dataCategories, setDataCategories] = useState([]) + return (
-
+
- + {!auth?.feature?.soApproval && ( + <> + + + )} + + @@ -151,11 +163,22 @@ export default function Home({categoryId}) {
+ {!auth?.feature?.soApproval && ( + <> + + + + + + + + )} - + - + + @@ -175,4 +198,4 @@ export default function Home({categoryId}) { ); -} +} \ No newline at end of file -- cgit v1.2.3 From c36d43c9b41eeb6f0c996476eaa8a2d13fbf42d1 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 14:47:17 +0700 Subject: update error code --- src/pages/index.jsx | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index c720547e..578c4e2d 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -80,8 +80,6 @@ export default function Home({categoryId}) { bannerRef.current?.querySelector(':first-child')?.clientHeight + 'px'; }; - // const [dataCategories, setDataCategories] = useState([]) - useEffect(() => { const loadCategories = async () => { const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) @@ -94,16 +92,6 @@ export default function Home({categoryId}) { const [dataCategories, setDataCategories] = useState([]) - useEffect(() => { - const loadCategories = async () => { - const getCategories = await odooApi('GET', '/api/v1/category/child?partner_id='+{categoryId}) - if(getCategories){ - setDataCategories(getCategories) - } - } - loadCategories() - }, []) - return ( ); -} +} \ No newline at end of file -- cgit v1.2.3 From 70ac7c6ee5d13f1aca58904d4cc3db3998e7dee0 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 15:00:28 +0700 Subject: update error code --- src/pages/index.jsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 578c4e2d..6558f605 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -141,8 +141,6 @@ export default function Home({categoryId}) { - - @@ -180,10 +178,6 @@ export default function Home({categoryId}) { - - - - -- cgit v1.2.3 From e244185f6a83ad396be4d1f84bf22c2d6be0997e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 15:11:48 +0700 Subject: update error code --- src/pages/index.jsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 6558f605..60dcb9e0 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -44,10 +44,6 @@ const FlashSale = dynamic( } ); -const ProgramPromotion = dynamic(() => - import('@/lib/home/components/PromotionProgram') -); - const BannerSection = dynamic(() => import('@/lib/home/components/BannerSection') ); @@ -135,7 +131,7 @@ export default function Home({categoryId}) {
{!auth?.feature?.soApproval && ( <> - + )} @@ -163,9 +159,6 @@ export default function Home({categoryId}) { {!auth?.feature?.soApproval && ( <> - - - -- cgit v1.2.3 From 44e1ed755b6714fbf76216ef914a8dfc73bef367 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 15:21:12 +0700 Subject: merge --- src/pages/index.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 578c4e2d..ad654922 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -13,6 +13,7 @@ import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; import odooApi from '@/core/api/odooApi'; import { getAuth } from '~/libs/auth'; +import { getAuth } from '~/libs/auth'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') @@ -92,6 +93,8 @@ export default function Home({categoryId}) { const [dataCategories, setDataCategories] = useState([]) + const [dataCategories, setDataCategories] = useState([]) + return (
+
-- cgit v1.2.3 From 233f2501a7ad23bedb8d02b7a3e7762632108098 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 15:23:28 +0700 Subject: update code --- src/pages/index.jsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index ad654922..0b2b6046 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -93,8 +93,6 @@ export default function Home({categoryId}) { const [dataCategories, setDataCategories] = useState([]) - const [dataCategories, setDataCategories] = useState([]) - return ( - -
+
@@ -184,10 +181,6 @@ export default function Home({categoryId}) { - - - - -- cgit v1.2.3 From d42a1c2bb522a3b29c60bbe75d0d250fa3fca6d8 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 23 Jul 2024 17:01:10 +0700 Subject: update category management --- src/lib/home/components/CategoryPilihan.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 7b9f0094..54807686 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -9,7 +9,7 @@ import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton' const CategoryPilihan = ({ id, categories }) => { - const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'index-a-1' })); + const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); return (
@@ -29,7 +29,7 @@ const CategoryPilihan = ({ id, categories }) => { quality={100} src={heroBanner.data[0].image} alt={heroBanner.data[0].name} - className='h-48 object-fill w-full rounded hover:scale-105 transition duration-500 ease-in-out' + className='h-48 object-fill w-full' /> {/* ))} */} @@ -41,9 +41,9 @@ const CategoryPilihan = ({ id, categories }) => { {categories.map((category) => (
-
-
- {category?.name} +
+
+ {category?.name}

{category?.name}

-- cgit v1.2.3 From 5214c9578aac1db612cd154cf04ee6d75750918d Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 24 Jul 2024 08:49:05 +0700 Subject: update error code --- src/pages/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 0b2b6046..110d8b17 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -13,7 +13,7 @@ import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; import odooApi from '@/core/api/odooApi'; import { getAuth } from '~/libs/auth'; -import { getAuth } from '~/libs/auth'; +// import { getAuth } from '~/libs/auth'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') -- cgit v1.2.3 From 0768abc2828369a0c41a8042e0d005d32b5315ba Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 24 Jul 2024 08:59:29 +0700 Subject: update error code --- src/pages/index.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 60dcb9e0..0e4ee5e6 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -124,6 +124,7 @@ export default function Home({categoryId}) {
+
@@ -141,6 +142,7 @@ export default function Home({categoryId}) {
+
-- cgit v1.2.3 From a264e12c5af60e82f6e496209b6ac81d4a994a10 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 24 Jul 2024 09:06:05 +0700 Subject: merge category management to development --- src/lib/home/components/CategoryPilihan.jsx | 10 +++++----- src/pages/index.jsx | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 73e42626..5aa1fbcc 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -9,7 +9,7 @@ import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton' const CategoryPilihan = ({ id, categories }) => { - const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'index-a-1' })); + const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); return (
@@ -29,7 +29,7 @@ const CategoryPilihan = ({ id, categories }) => { quality={100} src={heroBanner.data[0].image} alt={heroBanner.data[0].name} - className='h-48 object-fill w-full rounded hover:scale-105 transition duration-500 ease-in-out' + className='h-48 object-fill w-full' /> {/* ))} */} @@ -41,9 +41,9 @@ const CategoryPilihan = ({ id, categories }) => { {categories.map((category) => (
-
-
- {category?.name} +
+
+ {category?.name}

{category?.name}

diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 110d8b17..30a7ac1f 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -70,6 +70,7 @@ const CustomerReviews = dynamic(() => const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList')); + export default function Home({categoryId}) { const bannerRef = useRef(null); const wrapperRef = useRef(null); -- cgit v1.2.3 From 2e71abba4ca5b83cc1fec229d4d85961c4b56d71 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 25 Jul 2024 08:27:05 +0700 Subject: update category management --- src/lib/home/components/CategoryDynamic.jsx | 50 ++++++++++++++++++-------- src/lib/home/components/CategoryPilihan.jsx | 3 +- src/lib/product/components/CategorySection.jsx | 11 ++---- src/lib/product/components/ProductSearch.jsx | 35 ++++++++++++++++-- 4 files changed, 70 insertions(+), 29 deletions(-) diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index fa1df286..bbba2ceb 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -2,38 +2,58 @@ import React, { useEffect, useState } from 'react'; 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'; +import odooApi from '@/core/api/odooApi'; const CategoryDynamic = () => { const { categoryManagement } = useCategoryManagement(); + const [categoryData, setCategoryData] = useState({}); + const [subCategoryData, setSubCategoryData] = useState({}); + + useEffect(() => { + const fetchCategoryData = async () => { + if (categoryManagement && categoryManagement.data) { + const updatedCategoryData = {}; + const updatedSubCategoryData = {}; + + for (const category of categoryManagement.data) { + // Calculate level 1 products + const countLevel1 = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.categoryIdI}`); + // console.log("countLevel1.child",countLevel1) + + updatedCategoryData[category.categoryIdI] = countLevel1.numFound; + + + // Calculate level 2 products for each sub-category + for (const subCategory of countLevel1.children) { + updatedSubCategoryData[subCategory.id] = subCategory.numFound; + } + } - const calculateLevel3Products = (category) => { - return category.childFrontendIdI.reduce((total, child) => total + (child.numFound || 0), 0); - }; + setCategoryData(updatedCategoryData); + setSubCategoryData(updatedSubCategoryData); + } + }; - const calculateLevel2Products = (category) => { - return category.categories.reduce((total, subCategory) => { - const level3Products = calculateLevel3Products(subCategory); - return total + (subCategory.numFound || 0) + level3Products; - }, 0); - }; + fetchCategoryData(); + }, [categoryManagement, categoryData]); + return (
{categoryManagement && categoryManagement.data?.map((category) => { - const countLevel2 = calculateLevel2Products(category); - + const countLevel1 = categoryData[category.categoryIdI] || 0; + return (
{category.name}
-

{countLevel2} Produk tersedia

+

{countLevel1} Produk tersedia

Lihat Semua
{category.categories.map((subCategory) => { - const countLevel3 = calculateLevel3Products(subCategory); + const countLevel2 = subCategoryData[subCategory.idLevel2] || 0; return (
@@ -48,7 +68,7 @@ const CategoryDynamic = () => { />
{subCategory.name}
-

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

+

{countLevel2} Produk tersedia

Lihat Semua
diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 54807686..ea78b349 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -10,7 +10,6 @@ import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton' const CategoryPilihan = ({ id, categories }) => { const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); - return (
@@ -38,7 +37,7 @@ const CategoryPilihan = ({ id, categories }) => { )}
- {categories.map((category) => ( + {categories?.map((category) => (
diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 14a39e7e..2af3db10 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -13,23 +13,16 @@ import { HeartIcon, } from '@heroicons/react/24/outline'; import { useState } from 'react'; // Import useState +import { getIdFromSlug } from '@/core/utils/slug' const CategorySection = ({ categories }) => { const { isDesktop, isMobile } = useDevice(); - const router = useRouter(); const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility - 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`) - ); - const handleToggleCategories = () => { setIsOpenCategory(!isOpenCategory); }; + const displayedCategories = isOpenCategory ? categories : categories.slice(0, 10); diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index c4970b21..b5c1e87d 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -28,6 +28,7 @@ import SideBanner from '~/modules/side-banner'; import FooterBanner from '~/modules/footer-banner'; import CategorySection from './CategorySection'; import { getIdFromSlug } from '@/core/utils/slug' +import { data } from 'autoprefixer'; const ProductSearch = ({ query, @@ -63,6 +64,7 @@ const ProductSearch = ({ const [categoryValues, setCategory] = useState( query?.category?.split(',') || [] ); + const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null); const [priceTo, setPriceTo] = useState(query?.priceTo || null); @@ -71,6 +73,9 @@ const ProductSearch = ({ const productRows = limit; const productFound = productSearch.data?.response.numFound; const [dataCategories, setDataCategories] = useState([]) + const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const dataId = [] + // console.log("dataCategories",dataCategories) const categoryId = getIdFromSlug(prefixUrl) @@ -103,7 +108,7 @@ const ProductSearch = ({ }); } }, [productFound, query, spellings]); - + let id = [] useEffect(() => { const checkIfBrand = async () => { const brand = await axios( @@ -123,13 +128,37 @@ const ProductSearch = ({ useEffect(() => { const loadCategories = async () => { - const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) + const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) if(getCategories){ setDataCategories(getCategories) } } loadCategories() + + const loadProduct = async () => { + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`) + console.log("getCategoriesId",getCategoriesId) + if(getCategoriesId){ + setDataCategoriesProduct(getCategoriesId) + } + } + loadProduct() }, []) + collectIds(dataCategoriesProduct); + +// Fungsi rekursif untuk menambahkan ID dari kategori dan subkategori ke array dataId +function collectIds(category) { + if (category && category.id) { + dataId.push(category.id); + } + if (Array.isArray(category.children)) { + for (const child of category.children) { + collectIds(child); + } + } +} + +console.log("dataID",dataId) const brands = []; for ( @@ -275,7 +304,7 @@ const ProductSearch = ({ }; const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; - + console.log("query?.category?.split(',')",query.fq) return ( <> -- cgit v1.2.3 From 2c2885f57e9eb15e8c7d00c3a543a71c1d6ba83e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 25 Jul 2024 14:04:43 +0700 Subject: update search handle for category --- src/lib/product/components/ProductSearch.jsx | 83 ++++++++++++++++++---------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index b5c1e87d..413f4fb2 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -42,9 +42,56 @@ const ProductSearch = ({ const [search, setSearch] = useState(query?.q || '*'); const [limit, setLimit] = useState(query?.limit || 30); const [orderBy, setOrderBy] = useState(router.query?.orderBy || 'popular'); + const [finalQuery, setFinalQuery] = useState({}); + const [queryFinal, setQueryFinal] = useState({}); + const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const categoryId = getIdFromSlug(prefixUrl) if (defaultBrand) query.brand = defaultBrand.toLowerCase(); + useEffect(() => { + const loadProduct = async () => { + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`); + if (getCategoriesId) { + setDataCategoriesProduct(getCategoriesId); + } + }; + loadProduct(); + }, [categoryId]); + + const collectIds = (category) => { + const ids = []; + function recurse(cat) { + if (cat && cat.id) { + ids.push(cat.id); + } + if (Array.isArray(cat.children)) { + cat.children.forEach(recurse); + } + } + recurse(category); + return ids; + }; + + useEffect(() => { + const ids = collectIds(dataCategoriesProduct); + const newQuery = { + fq: `category_id_i:(${ids.join(' OR ')})`, + page: 1, + brand : router.query.brand? router.query.brand : '', + }; + setFinalQuery(newQuery); + }, [dataCategoriesProduct]); + + useEffect(() => { + if (prefixUrl.includes('category')) { + setQueryFinal({ ...finalQuery, q, limit, orderBy }); + // setQueryFinal({ ...query, q, limit, orderBy }); + } else { + setQueryFinal({ ...query, q, limit, orderBy }); + } + }, [prefixUrl, finalQuery, q, limit, orderBy]); + const { productSearch } = useProductSearch({ - query: { ...query, q, limit, orderBy }, + query: queryFinal, operation: 'AND', }); const [products, setProducts] = useState(null); @@ -73,12 +120,7 @@ const ProductSearch = ({ const productRows = limit; const productFound = productSearch.data?.response.numFound; const [dataCategories, setDataCategories] = useState([]) - const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) - const dataId = [] - // console.log("dataCategories",dataCategories) - - const categoryId = getIdFromSlug(prefixUrl) - + useEffect(() => { if (productFound == 0 && query.q && !spellings) { searchSpellApi({ query: query.q }).then((response) => { @@ -134,31 +176,10 @@ const ProductSearch = ({ } } loadCategories() - - const loadProduct = async () => { - const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`) - console.log("getCategoriesId",getCategoriesId) - if(getCategoriesId){ - setDataCategoriesProduct(getCategoriesId) - } - } - loadProduct() }, []) - collectIds(dataCategoriesProduct); -// Fungsi rekursif untuk menambahkan ID dari kategori dan subkategori ke array dataId -function collectIds(category) { - if (category && category.id) { - dataId.push(category.id); - } - if (Array.isArray(category.children)) { - for (const child of category.children) { - collectIds(child); - } - } -} + -console.log("dataID",dataId) const brands = []; for ( @@ -304,7 +325,9 @@ console.log("dataID",dataId) }; const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; - console.log("query?.category?.split(',')",query.fq) + + + return ( <> -- cgit v1.2.3 From 4758a0989f2ec0d79e1c5e3a3d42c249f28a9e72 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 26 Jul 2024 14:13:20 +0700 Subject: update code category management --- src/lib/product/components/ProductSearch.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 413f4fb2..cd7cda9f 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -74,7 +74,7 @@ const ProductSearch = ({ useEffect(() => { const ids = collectIds(dataCategoriesProduct); const newQuery = { - fq: `category_id_i:(${ids.join(' OR ')})`, + fq: `category_id_ids:(${ids.join(' OR ')})`, page: 1, brand : router.query.brand? router.query.brand : '', }; -- cgit v1.2.3 From e5a01976cb665b824b2ad6426a2c52a5bd0964e6 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 27 Jul 2024 08:27:54 +0700 Subject: add feature category lob --- src/lib/home/api/CategoryPilihanApi.js | 8 +++ src/lib/home/components/CategoryDynamic.jsx | 2 +- src/lib/home/components/CategoryPilihan.jsx | 12 +++-- src/lib/home/hooks/useCategoryPilihan.js | 13 +++++ src/lib/product/components/ProductSearch.jsx | 5 +- src/pages/api/shop/product-homepage.js | 3 +- src/pages/api/shop/search.js | 2 +- src/pages/shop/lob/[slug].jsx | 73 ++++++++++++++++++++++++++++ 8 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 src/lib/home/api/CategoryPilihanApi.js create mode 100644 src/lib/home/hooks/useCategoryPilihan.js create mode 100644 src/pages/shop/lob/[slug].jsx diff --git a/src/lib/home/api/CategoryPilihanApi.js b/src/lib/home/api/CategoryPilihanApi.js new file mode 100644 index 00000000..8a0b38d3 --- /dev/null +++ b/src/lib/home/api/CategoryPilihanApi.js @@ -0,0 +1,8 @@ +import odooApi from '@/core/api/odooApi' + +const categoryPilihanApi = async () => { + const dataCategoryPilihan = await odooApi('GET', '/api/v1/lob_homepage') + return dataCategoryPilihan +} + +export default categoryPilihanApi diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index bbba2ceb..6ab03ec3 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -21,7 +21,7 @@ const CategoryDynamic = () => { const countLevel1 = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.categoryIdI}`); // console.log("countLevel1.child",countLevel1) - updatedCategoryData[category.categoryIdI] = countLevel1.numFound; + updatedCategoryData[category.categoryIdI] = countLevel1?.numFound; // Calculate level 2 products for each sub-category diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index ea78b349..9f184709 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -6,9 +6,11 @@ import { useEffect, useState } from 'react'; import { bannerApi } from '../../../api/bannerApi'; const { useQuery } = require('react-query') import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton'; - +import useCategoryPilihan from '../hooks/useCategoryPilihan'; const CategoryPilihan = ({ id, categories }) => { + const { categoryPilihan } = useCategoryPilihan(); + console.log("categoryPilihan",categoryPilihan) const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); return (
@@ -37,19 +39,19 @@ const CategoryPilihan = ({ id, categories }) => { )}
- {categories?.map((category) => ( + {categoryPilihan?.data?.map((category) => (
- {category?.name} + {category?.name}
-

{category?.name}

+

{category?.industries}

Lihat semua diff --git a/src/lib/home/hooks/useCategoryPilihan.js b/src/lib/home/hooks/useCategoryPilihan.js new file mode 100644 index 00000000..12a86f7e --- /dev/null +++ b/src/lib/home/hooks/useCategoryPilihan.js @@ -0,0 +1,13 @@ +import categoryPilihanApi from '../api/CategoryPilihanApi' +import { useQuery } from 'react-query' + +const useCategoryPilihan = () => { + const fetchCategoryPilihan = async () => await categoryPilihanApi() + const { isLoading, data } = useQuery('categoryPilihanApi', fetchCategoryPilihan) + + return { + categoryPilihan: { data, isLoading } + } +} + +export default useCategoryPilihan \ No newline at end of file diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index cd7cda9f..735ef58e 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -78,8 +78,9 @@ const ProductSearch = ({ page: 1, brand : router.query.brand? router.query.brand : '', }; + console.log("newQuery",newQuery) setFinalQuery(newQuery); - }, [dataCategoriesProduct]); + }, [dataCategoriesProduct, prefixUrl, prefixUrl, finalQuery, q, limit, orderBy]); useEffect(() => { if (prefixUrl.includes('category')) { @@ -178,7 +179,7 @@ const ProductSearch = ({ loadCategories() }, []) - + console.log("queryFinal", queryFinal) const brands = []; diff --git a/src/pages/api/shop/product-homepage.js b/src/pages/api/shop/product-homepage.js index 02c01ee0..61732c77 100644 --- a/src/pages/api/shop/product-homepage.js +++ b/src/pages/api/shop/product-homepage.js @@ -36,7 +36,8 @@ const respoonseMap = (productHomepage, products) => { name: productHomepage.name_s, image: productHomepage.image_s, url: productHomepage.url_s, - products: products + products: products, + categoryIds: productHomepage.category_id_ids, } return productMapped diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index b6b8c795..66f517ae 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -56,7 +56,7 @@ export default async function handler(req, res) { `start=${parseInt(offset)}`, `rows=${limit}`, `sort=${paramOrderBy}`, - `fq=-publish_b:false`, + // `fq=-publish_b:false`, ]; if (priceFrom > 0 || priceTo > 0) { diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx new file mode 100644 index 00000000..be8db639 --- /dev/null +++ b/src/pages/shop/lob/[slug].jsx @@ -0,0 +1,73 @@ +import _ from 'lodash'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/router'; +import Seo from '@/core/components/Seo'; +import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'; +import Breadcrumb from '@/lib/category/components/Breadcrumb'; +import { useEffect, useState } from 'react'; +import odooApi from '@/core/api/odooApi'; + +const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')); +const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch')); +const CategorySection = dynamic(() => import('@/lib/product/components/CategorySection')); + +export default function CategoryDetail() { + const router = useRouter(); + const { slug = '', page = 1 } = router.query; + const [dataLob, setDataLob] = useState([]); + const [finalQuery, setFinalQuery] = useState({}); + + const categoryName = getNameFromSlug(slug); + const lobId = getIdFromSlug(slug); + + useEffect(() => { + const fetchCategoryData = async () => { + try { + const lobData = await odooApi('GET', `/api/v1/lob_homepage?lob_id=${lobId}`); + setDataLob(lobData); + } catch (error) { + console.error("Error fetching category data:", error); + } + }; + + fetchCategoryData(); + }, [lobId]); + + console.log("dataLob",dataLob) + + useEffect(() => { + const collectIds = (categories) => { + return categories?.categoryIds?.map(data => data.id) || []; + }; + + const ids = collectIds(dataLob[0]); + const newQuery = { + fq: `category_id_ids:(${ids.join(' OR ')})`, + page: 1, + brand: router.query.brand || '', + }; + setFinalQuery(newQuery); + console.log("finalQuery",finalQuery) + }, [dataLob, router.query.brand]); + + return ( + + + + + + {!_.isEmpty(router.query) && ( + + )} + + ); +} -- cgit v1.2.3 From f1910544cf6df50bcb175b66b604f5903f6ae3fa Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 27 Jul 2024 13:34:00 +0700 Subject: update category management for lob --- src/lib/home/components/CategoryPilihan.jsx | 1 - src/lib/lob/components/Breadcrumb.jsx | 55 ++++++++++++++++ src/lib/product/components/ProductSearch.jsx | 98 +++++++++++++++++++++------- src/pages/api/shop/search.js | 2 +- src/pages/shop/lob/[slug].jsx | 71 +++++++++++++++----- 5 files changed, 186 insertions(+), 41 deletions(-) create mode 100644 src/lib/lob/components/Breadcrumb.jsx diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 9f184709..5548fc1b 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -10,7 +10,6 @@ import useCategoryPilihan from '../hooks/useCategoryPilihan'; const CategoryPilihan = ({ id, categories }) => { const { categoryPilihan } = useCategoryPilihan(); - console.log("categoryPilihan",categoryPilihan) const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); return (
diff --git a/src/lib/lob/components/Breadcrumb.jsx b/src/lib/lob/components/Breadcrumb.jsx new file mode 100644 index 00000000..04d9a691 --- /dev/null +++ b/src/lib/lob/components/Breadcrumb.jsx @@ -0,0 +1,55 @@ +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( + `lob-breadcrumbs/${categoryId}`, + async () => await odooApi('GET', `/api/v1/lob_homepage?lob_id=${categoryId}`) + ) + return ( +
+ + + + + Home + + + + {breadcrumbs.data?.map((category, index) => ( + + {index === breadcrumbs.data.length - 1 ? ( + {category.industries} + ) : ( + + {category.industries} + + )} + + ))} + + +
+ ) +} + +export default Breadcrumb diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 735ef58e..2da84d63 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -37,6 +37,7 @@ const ProductSearch = ({ brand = null, }) => { const router = useRouter(); + const { page = 1 } = query; const [q, setQ] = useState(query?.q || '*'); const [search, setSearch] = useState(query?.q || '*'); @@ -45,18 +46,35 @@ const ProductSearch = ({ const [finalQuery, setFinalQuery] = useState({}); const [queryFinal, setQueryFinal] = useState({}); const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const [dataCategoriesLob, setDataCategoriesLob] = useState([]) const categoryId = getIdFromSlug(prefixUrl) + console.log("categoryId",categoryId ) + const [data, setData] = useState([]) + const [dataLob, setDataLob] = useState([]); if (defaultBrand) query.brand = defaultBrand.toLowerCase(); + const dataIdCategories = [] useEffect(() => { - const loadProduct = async () => { - const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`); - if (getCategoriesId) { - setDataCategoriesProduct(getCategoriesId); - } - }; - loadProduct(); + if(prefixUrl.includes('category')){ + const loadProduct = async () => { + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`); + if (getCategoriesId) { + setDataCategoriesProduct(getCategoriesId); + } + }; + loadProduct(); + }else if(prefixUrl.includes('lob')){ + const loadProduct = async () => { + const lobData = await odooApi('GET', `/api/v1/lob_homepage?lob_id=${categoryId}`); + console.log("lobData",lobData ) + if (lobData) { + setDataLob(lobData); + } + }; + loadProduct(); + console.log("dataLob",dataLob ) + } }, [categoryId]); - + const collectIds = (category) => { const ids = []; function recurse(cat) { @@ -70,26 +88,61 @@ const ProductSearch = ({ recurse(category); return ids; }; - + useEffect(() => { - const ids = collectIds(dataCategoriesProduct); - const newQuery = { - fq: `category_id_ids:(${ids.join(' OR ')})`, - page: 1, - brand : router.query.brand? router.query.brand : '', - }; - console.log("newQuery",newQuery) - setFinalQuery(newQuery); - }, [dataCategoriesProduct, prefixUrl, prefixUrl, finalQuery, q, limit, orderBy]); + if(prefixUrl.includes('category')){ + const ids = collectIds(dataCategoriesProduct); + const newQuery = { + fq: `category_id_ids:(${ids.join(' OR ')})`, + page, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + }; + setFinalQuery(newQuery); + } else if (prefixUrl.includes('lob')){ + console.log("prefixUrl",prefixUrl) + const fetchCategoryData = async () => { + if (dataLob[0]?.categoryIds) { + console.log("dataLob[0]?.categoryIds",dataLob[0]?.categoryIds) + for (const cate of dataLob[0].categoryIds) { + console.log("cate",cate) + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${cate.id}`); + console.log("getCategoriesId",getCategoriesId) + if (getCategoriesId) { + const ids = collectIds(getCategoriesId); + console.log("ids",ids) + dataIdCategories.push(ids) + console.log("dataIdCategories",dataIdCategories) + } + } + + console.log("dataIdCategories2",dataIdCategories) + // setData(dataIdCategories) + // console.log("data",data) + const mergedArray = dataIdCategories.flat(); + console.log("mergedArray",mergedArray) + const newQuery = { + fq: `category_id_ids:(${mergedArray.join(' OR ')})`, + page, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + }; + console.log("newQuery",newQuery) + setFinalQuery(newQuery); + console.log("final query",finalQuery) + } + }; + fetchCategoryData(); + } + }, [dataCategoriesProduct, dataLob]); useEffect(() => { - if (prefixUrl.includes('category')) { + if (prefixUrl.includes('category') || prefixUrl.includes('lob')) { setQueryFinal({ ...finalQuery, q, limit, orderBy }); - // setQueryFinal({ ...query, q, limit, orderBy }); } else { setQueryFinal({ ...query, q, limit, orderBy }); } - }, [prefixUrl, finalQuery, q, limit, orderBy]); + }, [prefixUrl,dataCategoriesProduct, query, finalQuery]); const { productSearch } = useProductSearch({ query: queryFinal, @@ -179,7 +232,8 @@ const ProductSearch = ({ loadCategories() }, []) - console.log("queryFinal", queryFinal) + // console.log("query asal ", query) + // console.log("queryFinal", queryFinal) const brands = []; diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index 66f517ae..b6b8c795 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -56,7 +56,7 @@ export default async function handler(req, res) { `start=${parseInt(offset)}`, `rows=${limit}`, `sort=${paramOrderBy}`, - // `fq=-publish_b:false`, + `fq=-publish_b:false`, ]; if (priceFrom > 0 || priceTo > 0) { diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx index be8db639..d02ec8ac 100644 --- a/src/pages/shop/lob/[slug].jsx +++ b/src/pages/shop/lob/[slug].jsx @@ -3,9 +3,10 @@ import dynamic from 'next/dynamic'; import { useRouter } from 'next/router'; import Seo from '@/core/components/Seo'; import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'; -import Breadcrumb from '@/lib/category/components/Breadcrumb'; +import Breadcrumb from '../../../lib/lob/components/Breadcrumb'; import { useEffect, useState } from 'react'; import odooApi from '@/core/api/odooApi'; +import { div } from 'lodash-contrib'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')); const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch')); @@ -16,9 +17,20 @@ export default function CategoryDetail() { const { slug = '', page = 1 } = router.query; const [dataLob, setDataLob] = useState([]); const [finalQuery, setFinalQuery] = useState({}); + const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const [data, setData] = useState([]) + const dataIdCategories = [] const categoryName = getNameFromSlug(slug); const lobId = getIdFromSlug(slug); + const q = router?.query.q || null; + const query = { + fq: `id:${lobId}`, + page, + }; + if (q) { + query.q = q; + } useEffect(() => { const fetchCategoryData = async () => { @@ -33,22 +45,40 @@ export default function CategoryDetail() { fetchCategoryData(); }, [lobId]); - console.log("dataLob",dataLob) - + const collectIdsCategory = (category) => { + const ids = []; + function recurse(cat) { + if (cat && cat.id) { + ids.push(cat.id); + } + if (Array.isArray(cat.children)) { + cat.children.forEach(recurse); + } + } + recurse(category); + return ids; + }; useEffect(() => { - const collectIds = (categories) => { - return categories?.categoryIds?.map(data => data.id) || []; - }; - - const ids = collectIds(dataLob[0]); - const newQuery = { - fq: `category_id_ids:(${ids.join(' OR ')})`, - page: 1, - brand: router.query.brand || '', - }; - setFinalQuery(newQuery); - console.log("finalQuery",finalQuery) - }, [dataLob, router.query.brand]); + const fetchCategoryData = async () => { + if (dataLob[0]?.categoryIds) { + for (const category of dataLob[0].categoryIds) { + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.id}`); + if (getCategoriesId) { + setDataCategoriesProduct(getCategoriesId); + const ids = collectIdsCategory(getCategoriesId); + dataIdCategories.push(ids) + } + } + setData(dataIdCategories) + } + }; + fetchCategoryData(); + const mergedArray = data.flat(); + const newQuery = { + fq: `category_id_ids:(${mergedArray.join(' OR ')})`, + }; + setFinalQuery(newQuery); + }, [dataLob, ]); return ( @@ -64,9 +94,16 @@ export default function CategoryDetail() { /> +
+ {dataLob[0]?.categoryIds && ( +
+ +
+ )} +
{!_.isEmpty(router.query) && ( - + )}
); -- cgit v1.2.3 From 556e7e226a2043d43bc55bf0ff2118294bb9f330 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 13:32:39 +0700 Subject: update lob category --- src/lib/lob/components/Breadcrumb.jsx | 4 +- src/lib/product/components/LobSectionCategory.jsx | 89 +++++++++++++++++++++++ src/lib/product/components/ProductSearch.jsx | 54 ++++++-------- src/pages/shop/lob/[slug].jsx | 48 ------------ 4 files changed, 115 insertions(+), 80 deletions(-) create mode 100644 src/lib/product/components/LobSectionCategory.jsx diff --git a/src/lib/lob/components/Breadcrumb.jsx b/src/lib/lob/components/Breadcrumb.jsx index 04d9a691..5722fd39 100644 --- a/src/lib/lob/components/Breadcrumb.jsx +++ b/src/lib/lob/components/Breadcrumb.jsx @@ -19,7 +19,7 @@ import { useQuery } from 'react-query' const Breadcrumb = ({ categoryId }) => { const breadcrumbs = useQuery( `lob-breadcrumbs/${categoryId}`, - async () => await odooApi('GET', `/api/v1/lob_homepage?lob_id=${categoryId}`) + async () => await odooApi('GET', `/api/v1/lob_homepage/${categoryId}/category_id`) ) return (
@@ -31,7 +31,7 @@ const Breadcrumb = ({ categoryId }) => { - {breadcrumbs.data?.map((category, index) => ( + {breadcrumbs?.data?.map((category, index) => ( {index === breadcrumbs.data.length - 1 ? ( {category.industries} diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx new file mode 100644 index 00000000..5e9934c3 --- /dev/null +++ b/src/lib/product/components/LobSectionCategory.jsx @@ -0,0 +1,89 @@ +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 { + ChevronDownIcon, + ChevronUpIcon, // Import ChevronUpIcon for toggling + DocumentCheckIcon, + HeartIcon, +} from '@heroicons/react/24/outline'; +import { useState } from 'react'; // Import useState +import { getIdFromSlug } from '@/core/utils/slug' + +const LobSectionCategory = ({ categories }) => { + const { isDesktop, isMobile } = useDevice(); + const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility + + const handleToggleCategories = () => { + setIsOpenCategory(!isOpenCategory); + }; + console.log("categories",categories[0]?.categoryIds) + + const displayedCategories = categories[0]?.categoryIds; + + return ( +
+ {isDesktop && ( +
+ {displayedCategories?.map((category) => ( + +
+
+
+ {category?.name} + {/*

{category?.name}

*/} +
+
+
+ + ))} +
+ )} + + {isMobile && ( +
+ + {displayedCategories.map((category) => ( + + +
+
+
+ {category?.name} +

+ {category?.name} +

+
+
+
+ +
+ ))} +
+ {categories.length > 10 && ( +
+ +
+ )} +
+ )} +
+ ) +} + +export default LobSectionCategory diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 2da84d63..12e3b358 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -27,6 +27,7 @@ import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton'; import SideBanner from '~/modules/side-banner'; import FooterBanner from '~/modules/footer-banner'; import CategorySection from './CategorySection'; +import LobSectionCategory from './LobSectionCategory'; import { getIdFromSlug } from '@/core/utils/slug' import { data } from 'autoprefixer'; @@ -48,7 +49,6 @@ const ProductSearch = ({ const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) const [dataCategoriesLob, setDataCategoriesLob] = useState([]) const categoryId = getIdFromSlug(prefixUrl) - console.log("categoryId",categoryId ) const [data, setData] = useState([]) const [dataLob, setDataLob] = useState([]); if (defaultBrand) query.brand = defaultBrand.toLowerCase(); @@ -64,14 +64,14 @@ const ProductSearch = ({ loadProduct(); }else if(prefixUrl.includes('lob')){ const loadProduct = async () => { - const lobData = await odooApi('GET', `/api/v1/lob_homepage?lob_id=${categoryId}`); - console.log("lobData",lobData ) + const lobData = await odooApi('GET', `/api/v1/lob_homepage/${categoryId}/category_id`); + if (lobData) { setDataLob(lobData); } }; loadProduct(); - console.log("dataLob",dataLob ) + } }, [categoryId]); @@ -100,36 +100,27 @@ const ProductSearch = ({ }; setFinalQuery(newQuery); } else if (prefixUrl.includes('lob')){ - console.log("prefixUrl",prefixUrl) + const fetchCategoryData = async () => { if (dataLob[0]?.categoryIds) { - console.log("dataLob[0]?.categoryIds",dataLob[0]?.categoryIds) + for (const cate of dataLob[0].categoryIds) { - console.log("cate",cate) - const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${cate.id}`); - console.log("getCategoriesId",getCategoriesId) - if (getCategoriesId) { - const ids = collectIds(getCategoriesId); - console.log("ids",ids) - dataIdCategories.push(ids) - console.log("dataIdCategories",dataIdCategories) - } + + dataIdCategories.push(cate.childId) } - console.log("dataIdCategories2",dataIdCategories) - // setData(dataIdCategories) - // console.log("data",data) + const mergedArray = dataIdCategories.flat(); - console.log("mergedArray",mergedArray) + const newQuery = { fq: `category_id_ids:(${mergedArray.join(' OR ')})`, page, brand : router.query.brand? router.query.brand : '', category : router.query.category? router.query.category : '', }; - console.log("newQuery",newQuery) + setFinalQuery(newQuery); - console.log("final query",finalQuery) + } }; fetchCategoryData(); @@ -223,17 +214,18 @@ const ProductSearch = ({ }, [q]); useEffect(() => { - const loadCategories = async () => { - const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) - if(getCategories){ - setDataCategories(getCategories) - } + if(prefixUrl.includes('category')){ + const loadCategories = async () => { + const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() } - loadCategories() }, []) - // console.log("query asal ", query) - // console.log("queryFinal", queryFinal) + const brands = []; @@ -381,7 +373,7 @@ const ProductSearch = ({ const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; - + console.log("finalQuery",finalQuery) return ( <> @@ -443,6 +435,7 @@ const ProductSearch = ({ SpellingComponent )}
+ {productFound > 0 && ( @@ -534,6 +527,7 @@ const ProductSearch = ({
+ {bannerPromotionHeader && bannerPromotionHeader?.image && (
diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx index d02ec8ac..2153b565 100644 --- a/src/pages/shop/lob/[slug].jsx +++ b/src/pages/shop/lob/[slug].jsx @@ -32,54 +32,6 @@ export default function CategoryDetail() { query.q = q; } - useEffect(() => { - const fetchCategoryData = async () => { - try { - const lobData = await odooApi('GET', `/api/v1/lob_homepage?lob_id=${lobId}`); - setDataLob(lobData); - } catch (error) { - console.error("Error fetching category data:", error); - } - }; - - fetchCategoryData(); - }, [lobId]); - - const collectIdsCategory = (category) => { - const ids = []; - function recurse(cat) { - if (cat && cat.id) { - ids.push(cat.id); - } - if (Array.isArray(cat.children)) { - cat.children.forEach(recurse); - } - } - recurse(category); - return ids; - }; - useEffect(() => { - const fetchCategoryData = async () => { - if (dataLob[0]?.categoryIds) { - for (const category of dataLob[0].categoryIds) { - const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.id}`); - if (getCategoriesId) { - setDataCategoriesProduct(getCategoriesId); - const ids = collectIdsCategory(getCategoriesId); - dataIdCategories.push(ids) - } - } - setData(dataIdCategories) - } - }; - fetchCategoryData(); - const mergedArray = data.flat(); - const newQuery = { - fq: `category_id_ids:(${mergedArray.join(' OR ')})`, - }; - setFinalQuery(newQuery); - }, [dataLob, ]); - return ( Date: Mon, 29 Jul 2024 14:15:41 +0700 Subject: update top banner --- src/core/components/elements/Navbar/TopBanner.jsx | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/core/components/elements/Navbar/TopBanner.jsx b/src/core/components/elements/Navbar/TopBanner.jsx index 722a7501..83ef8c7a 100644 --- a/src/core/components/elements/Navbar/TopBanner.jsx +++ b/src/core/components/elements/Navbar/TopBanner.jsx @@ -4,6 +4,7 @@ import { useQuery } from 'react-query'; import odooApi from '@/core/api/odooApi'; import SmoothRender from '~/components/ui/smooth-render'; import Link from '../Link/Link'; +import { background } from '@chakra-ui/react'; const TopBanner = () => { const topBanner = useQuery({ @@ -12,7 +13,7 @@ const TopBanner = () => { refetchOnWindowFocus: false, }); - const backgroundColor = topBanner.data?.[0]?.backgroundColor || 'transparent'; + // const backgroundColor = topBanner.data?.[0]?.backgroundColor || 'transparent'; const hasData = topBanner.data?.length > 0; const data = topBanner.data?.[0] || null; @@ -22,16 +23,17 @@ const TopBanner = () => { height='36px' duration='700ms' delay='300ms' - style={{ backgroundColor }} > - - {data?.name} + ); -- cgit v1.2.3 From 1a58c55e6415d78f5d155055071a649d1f56492a Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 14:52:57 +0700 Subject: update mobile view --- src/lib/product/components/LobSectionCategory.jsx | 51 ++++++++++------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx index 5e9934c3..34a09e46 100644 --- a/src/lib/product/components/LobSectionCategory.jsx +++ b/src/lib/product/components/LobSectionCategory.jsx @@ -29,43 +29,36 @@ const LobSectionCategory = ({ categories }) => { return (
{isDesktop && ( -
+
{displayedCategories?.map((category) => ( - -
-
-
- {category?.name} - {/*

{category?.name}

*/} -
-
-
- + + ))}
)} {isMobile && (
- - {displayedCategories.map((category) => ( + + {displayedCategories?.map((category) => ( - -
-
-
- {category?.name} -

- {category?.name} -

-
-
-
+
))} -- cgit v1.2.3 From 1f07818ba6718755684de5863e01636805b80867 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 15:16:00 +0700 Subject: update to avoid conflict --- src/pages/index.jsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 0e4ee5e6..30a7ac1f 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -13,6 +13,7 @@ import PagePopupIformation from '~/modules/popup-information'; import CategoryPilihan from '../lib/home/components/CategoryPilihan'; import odooApi from '@/core/api/odooApi'; import { getAuth } from '~/libs/auth'; +// import { getAuth } from '~/libs/auth'; const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout') @@ -44,6 +45,10 @@ const FlashSale = dynamic( } ); +const ProgramPromotion = dynamic(() => + import('@/lib/home/components/PromotionProgram') +); + const BannerSection = dynamic(() => import('@/lib/home/components/BannerSection') ); @@ -65,6 +70,7 @@ const CustomerReviews = dynamic(() => const ServiceList = dynamic(() => import('@/lib/home/components/ServiceList')); + export default function Home({categoryId}) { const bannerRef = useRef(null); const wrapperRef = useRef(null); @@ -132,7 +138,7 @@ export default function Home({categoryId}) {
{!auth?.feature?.soApproval && ( <> - + )} @@ -161,6 +167,9 @@ export default function Home({categoryId}) { {!auth?.feature?.soApproval && ( <> + + + -- cgit v1.2.3 From a59ed6e73a599a82d6ef248c57ad29f2ab9cb15d Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 15:23:01 +0700 Subject: Merge branch 'Feature/category-management' into development --- src/core/components/elements/Navbar/TopBanner.jsx | 22 ++-- src/lib/home/api/CategoryPilihanApi.js | 8 ++ src/lib/home/components/CategoryDynamic.jsx | 50 ++++++--- src/lib/home/components/CategoryPilihan.jsx | 14 +-- src/lib/home/hooks/useCategoryPilihan.js | 13 +++ src/lib/lob/components/Breadcrumb.jsx | 55 ++++++++++ src/lib/product/components/CategorySection.jsx | 11 +- src/lib/product/components/LobSectionCategory.jsx | 82 +++++++++++++++ src/lib/product/components/ProductSearch.jsx | 123 ++++++++++++++++++++-- src/pages/api/shop/product-homepage.js | 3 +- src/pages/shop/lob/[slug].jsx | 62 +++++++++++ 11 files changed, 390 insertions(+), 53 deletions(-) create mode 100644 src/lib/home/api/CategoryPilihanApi.js create mode 100644 src/lib/home/hooks/useCategoryPilihan.js create mode 100644 src/lib/lob/components/Breadcrumb.jsx create mode 100644 src/lib/product/components/LobSectionCategory.jsx create mode 100644 src/pages/shop/lob/[slug].jsx diff --git a/src/core/components/elements/Navbar/TopBanner.jsx b/src/core/components/elements/Navbar/TopBanner.jsx index 722a7501..83ef8c7a 100644 --- a/src/core/components/elements/Navbar/TopBanner.jsx +++ b/src/core/components/elements/Navbar/TopBanner.jsx @@ -4,6 +4,7 @@ import { useQuery } from 'react-query'; import odooApi from '@/core/api/odooApi'; import SmoothRender from '~/components/ui/smooth-render'; import Link from '../Link/Link'; +import { background } from '@chakra-ui/react'; const TopBanner = () => { const topBanner = useQuery({ @@ -12,7 +13,7 @@ const TopBanner = () => { refetchOnWindowFocus: false, }); - const backgroundColor = topBanner.data?.[0]?.backgroundColor || 'transparent'; + // const backgroundColor = topBanner.data?.[0]?.backgroundColor || 'transparent'; const hasData = topBanner.data?.length > 0; const data = topBanner.data?.[0] || null; @@ -22,16 +23,17 @@ const TopBanner = () => { height='36px' duration='700ms' delay='300ms' - style={{ backgroundColor }} > - - {data?.name} + ); diff --git a/src/lib/home/api/CategoryPilihanApi.js b/src/lib/home/api/CategoryPilihanApi.js new file mode 100644 index 00000000..8a0b38d3 --- /dev/null +++ b/src/lib/home/api/CategoryPilihanApi.js @@ -0,0 +1,8 @@ +import odooApi from '@/core/api/odooApi' + +const categoryPilihanApi = async () => { + const dataCategoryPilihan = await odooApi('GET', '/api/v1/lob_homepage') + return dataCategoryPilihan +} + +export default categoryPilihanApi diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index fa1df286..6ab03ec3 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -2,38 +2,58 @@ import React, { useEffect, useState } from 'react'; 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'; +import odooApi from '@/core/api/odooApi'; const CategoryDynamic = () => { const { categoryManagement } = useCategoryManagement(); + const [categoryData, setCategoryData] = useState({}); + const [subCategoryData, setSubCategoryData] = useState({}); + + useEffect(() => { + const fetchCategoryData = async () => { + if (categoryManagement && categoryManagement.data) { + const updatedCategoryData = {}; + const updatedSubCategoryData = {}; + + for (const category of categoryManagement.data) { + // Calculate level 1 products + const countLevel1 = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.categoryIdI}`); + // console.log("countLevel1.child",countLevel1) + + updatedCategoryData[category.categoryIdI] = countLevel1?.numFound; + + + // Calculate level 2 products for each sub-category + for (const subCategory of countLevel1.children) { + updatedSubCategoryData[subCategory.id] = subCategory.numFound; + } + } - const calculateLevel3Products = (category) => { - return category.childFrontendIdI.reduce((total, child) => total + (child.numFound || 0), 0); - }; + setCategoryData(updatedCategoryData); + setSubCategoryData(updatedSubCategoryData); + } + }; - const calculateLevel2Products = (category) => { - return category.categories.reduce((total, subCategory) => { - const level3Products = calculateLevel3Products(subCategory); - return total + (subCategory.numFound || 0) + level3Products; - }, 0); - }; + fetchCategoryData(); + }, [categoryManagement, categoryData]); + return (
{categoryManagement && categoryManagement.data?.map((category) => { - const countLevel2 = calculateLevel2Products(category); - + const countLevel1 = categoryData[category.categoryIdI] || 0; + return (
{category.name}
-

{countLevel2} Produk tersedia

+

{countLevel1} Produk tersedia

Lihat Semua
{category.categories.map((subCategory) => { - const countLevel3 = calculateLevel3Products(subCategory); + const countLevel2 = subCategoryData[subCategory.idLevel2] || 0; return (
@@ -48,7 +68,7 @@ const CategoryDynamic = () => { />
{subCategory.name}
-

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

+

{countLevel2} Produk tersedia

Lihat Semua
diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 5aa1fbcc..6efc1070 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -6,11 +6,11 @@ import { useEffect, useState } from 'react'; import { bannerApi } from '../../../api/bannerApi'; const { useQuery } = require('react-query') import { HeroBannerSkeleton } from '../../../components/skeleton/BannerSkeleton'; - +import useCategoryPilihan from '../hooks/useCategoryPilihan'; const CategoryPilihan = ({ id, categories }) => { + const { categoryPilihan } = useCategoryPilihan(); const heroBanner = useQuery('categoryPilihan', bannerApi({ type: 'banner-category-list' })); - return (
@@ -38,19 +38,19 @@ const CategoryPilihan = ({ id, categories }) => { )}
- {categories.map((category) => ( -
+ {categoryPilihan?.data?.map((category) => ( +
- {category?.name} + {category?.name}
-

{category?.name}

+

{category?.industries}

Lihat semua diff --git a/src/lib/home/hooks/useCategoryPilihan.js b/src/lib/home/hooks/useCategoryPilihan.js new file mode 100644 index 00000000..12a86f7e --- /dev/null +++ b/src/lib/home/hooks/useCategoryPilihan.js @@ -0,0 +1,13 @@ +import categoryPilihanApi from '../api/CategoryPilihanApi' +import { useQuery } from 'react-query' + +const useCategoryPilihan = () => { + const fetchCategoryPilihan = async () => await categoryPilihanApi() + const { isLoading, data } = useQuery('categoryPilihanApi', fetchCategoryPilihan) + + return { + categoryPilihan: { data, isLoading } + } +} + +export default useCategoryPilihan \ No newline at end of file diff --git a/src/lib/lob/components/Breadcrumb.jsx b/src/lib/lob/components/Breadcrumb.jsx new file mode 100644 index 00000000..5722fd39 --- /dev/null +++ b/src/lib/lob/components/Breadcrumb.jsx @@ -0,0 +1,55 @@ +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( + `lob-breadcrumbs/${categoryId}`, + async () => await odooApi('GET', `/api/v1/lob_homepage/${categoryId}/category_id`) + ) + return ( +
+ + + + + Home + + + + {breadcrumbs?.data?.map((category, index) => ( + + {index === breadcrumbs.data.length - 1 ? ( + {category.industries} + ) : ( + + {category.industries} + + )} + + ))} + + +
+ ) +} + +export default Breadcrumb diff --git a/src/lib/product/components/CategorySection.jsx b/src/lib/product/components/CategorySection.jsx index 14a39e7e..2af3db10 100644 --- a/src/lib/product/components/CategorySection.jsx +++ b/src/lib/product/components/CategorySection.jsx @@ -13,23 +13,16 @@ import { HeartIcon, } from '@heroicons/react/24/outline'; import { useState } from 'react'; // Import useState +import { getIdFromSlug } from '@/core/utils/slug' const CategorySection = ({ categories }) => { const { isDesktop, isMobile } = useDevice(); - const router = useRouter(); const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility - 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`) - ); - const handleToggleCategories = () => { setIsOpenCategory(!isOpenCategory); }; + const displayedCategories = isOpenCategory ? categories : categories.slice(0, 10); diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx new file mode 100644 index 00000000..34a09e46 --- /dev/null +++ b/src/lib/product/components/LobSectionCategory.jsx @@ -0,0 +1,82 @@ +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 { + ChevronDownIcon, + ChevronUpIcon, // Import ChevronUpIcon for toggling + DocumentCheckIcon, + HeartIcon, +} from '@heroicons/react/24/outline'; +import { useState } from 'react'; // Import useState +import { getIdFromSlug } from '@/core/utils/slug' + +const LobSectionCategory = ({ categories }) => { + const { isDesktop, isMobile } = useDevice(); + const [isOpenCategory, setIsOpenCategory] = useState(false); // State to manage category visibility + + const handleToggleCategories = () => { + setIsOpenCategory(!isOpenCategory); + }; + console.log("categories",categories[0]?.categoryIds) + + const displayedCategories = categories[0]?.categoryIds; + + return ( +
+ {isDesktop && ( +
+ {displayedCategories?.map((category) => ( + + + ))} +
+ )} + + {isMobile && ( +
+ + {displayedCategories?.map((category) => ( + + + + + ))} + + {categories.length > 10 && ( +
+ +
+ )} +
+ )} +
+ ) +} + +export default LobSectionCategory diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 34018ffe..4d510c5b 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -27,7 +27,9 @@ import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton'; import SideBanner from '~/modules/side-banner'; import FooterBanner from '~/modules/footer-banner'; import CategorySection from './CategorySection'; +import LobSectionCategory from './LobSectionCategory'; import { getIdFromSlug } from '@/core/utils/slug' +import { data } from 'autoprefixer'; const ProductSearch = ({ query, @@ -36,14 +38,105 @@ const ProductSearch = ({ brand = null, }) => { const router = useRouter(); + const { page = 1 } = query; const [q, setQ] = useState(query?.q || '*'); const [search, setSearch] = useState(query?.q || '*'); const [limit, setLimit] = useState(query?.limit || 30); const [orderBy, setOrderBy] = useState(router.query?.orderBy || 'popular'); + const [finalQuery, setFinalQuery] = useState({}); + const [queryFinal, setQueryFinal] = useState({}); + const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const [dataCategoriesLob, setDataCategoriesLob] = useState([]) + const categoryId = getIdFromSlug(prefixUrl) + const [data, setData] = useState([]) + const [dataLob, setDataLob] = useState([]); if (defaultBrand) query.brand = defaultBrand.toLowerCase(); + const dataIdCategories = [] + useEffect(() => { + if(prefixUrl.includes('category')){ + const loadProduct = async () => { + const getCategoriesId = await odooApi('GET', `/api/v1/category/numFound?parent_id=${categoryId}`); + if (getCategoriesId) { + setDataCategoriesProduct(getCategoriesId); + } + }; + loadProduct(); + }else if(prefixUrl.includes('lob')){ + const loadProduct = async () => { + const lobData = await odooApi('GET', `/api/v1/lob_homepage/${categoryId}/category_id`); + + if (lobData) { + setDataLob(lobData); + } + }; + loadProduct(); + + } + }, [categoryId]); + + const collectIds = (category) => { + const ids = []; + function recurse(cat) { + if (cat && cat.id) { + ids.push(cat.id); + } + if (Array.isArray(cat.children)) { + cat.children.forEach(recurse); + } + } + recurse(category); + return ids; + }; + + useEffect(() => { + if(prefixUrl.includes('category')){ + const ids = collectIds(dataCategoriesProduct); + const newQuery = { + fq: `category_id_ids:(${ids.join(' OR ')})`, + page, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + }; + setFinalQuery(newQuery); + } else if (prefixUrl.includes('lob')){ + + const fetchCategoryData = async () => { + if (dataLob[0]?.categoryIds) { + + for (const cate of dataLob[0].categoryIds) { + + dataIdCategories.push(cate.childId) + } + + + const mergedArray = dataIdCategories.flat(); + + const newQuery = { + fq: `category_id_ids:(${mergedArray.join(' OR ')})`, + page, + brand : router.query.brand? router.query.brand : '', + category : router.query.category? router.query.category : '', + }; + + setFinalQuery(newQuery); + + } + }; + fetchCategoryData(); + } + }, [dataCategoriesProduct, dataLob]); + + useEffect(() => { + if (prefixUrl.includes('category') || prefixUrl.includes('lob')) { + setQueryFinal({ ...finalQuery, q, limit, orderBy }); + } else { + setQueryFinal({ ...query, q, limit, orderBy }); + } + }, [prefixUrl,dataCategoriesProduct, query, finalQuery]); + const { productSearch } = useProductSearch({ - query: { ...query, q, limit, orderBy }, + query: queryFinal, operation: 'AND', }); const [products, setProducts] = useState(null); @@ -63,6 +156,7 @@ const ProductSearch = ({ const [categoryValues, setCategory] = useState( query?.category?.split(',') || [] ); + const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null); const [priceTo, setPriceTo] = useState(query?.priceTo || null); @@ -71,9 +165,7 @@ const ProductSearch = ({ const productRows = limit; const productFound = productSearch.data?.response.numFound; const [dataCategories, setDataCategories] = useState([]) - - const categoryId = getIdFromSlug(prefixUrl) - + useEffect(() => { if (productFound == 0 && query.q && !spellings) { searchSpellApi({ query: query.q }).then((response) => { @@ -103,7 +195,7 @@ const ProductSearch = ({ }); } }, [productFound, query, spellings]); - + let id = [] useEffect(() => { const checkIfBrand = async () => { const brand = await axios( @@ -122,15 +214,20 @@ const ProductSearch = ({ }, [q]); useEffect(() => { - const loadCategories = async () => { - const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) - if(getCategories){ - setDataCategories(getCategories) - } + if(prefixUrl.includes('category')){ + const loadCategories = async () => { + const getCategories = await odooApi('GET', `/api/v1/category/child?parent_id=${categoryId}`) + if(getCategories){ + setDataCategories(getCategories) + } + } + loadCategories() } - loadCategories() }, []) + + + const brands = []; for ( let i = 0; @@ -277,6 +374,8 @@ const ProductSearch = ({ }; const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; + + console.log("finalQuery",finalQuery) return ( <> @@ -338,6 +437,7 @@ const ProductSearch = ({ SpellingComponent )}
+ {productFound > 0 && ( @@ -429,6 +529,7 @@ const ProductSearch = ({
+ {bannerPromotionHeader && bannerPromotionHeader?.image && (
diff --git a/src/pages/api/shop/product-homepage.js b/src/pages/api/shop/product-homepage.js index 02c01ee0..61732c77 100644 --- a/src/pages/api/shop/product-homepage.js +++ b/src/pages/api/shop/product-homepage.js @@ -36,7 +36,8 @@ const respoonseMap = (productHomepage, products) => { name: productHomepage.name_s, image: productHomepage.image_s, url: productHomepage.url_s, - products: products + products: products, + categoryIds: productHomepage.category_id_ids, } return productMapped diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx new file mode 100644 index 00000000..2153b565 --- /dev/null +++ b/src/pages/shop/lob/[slug].jsx @@ -0,0 +1,62 @@ +import _ from 'lodash'; +import dynamic from 'next/dynamic'; +import { useRouter } from 'next/router'; +import Seo from '@/core/components/Seo'; +import { getIdFromSlug, getNameFromSlug } from '@/core/utils/slug'; +import Breadcrumb from '../../../lib/lob/components/Breadcrumb'; +import { useEffect, useState } from 'react'; +import odooApi from '@/core/api/odooApi'; +import { div } from 'lodash-contrib'; + +const BasicLayout = dynamic(() => import('@/core/components/layouts/BasicLayout')); +const ProductSearch = dynamic(() => import('@/lib/product/components/ProductSearch')); +const CategorySection = dynamic(() => import('@/lib/product/components/CategorySection')); + +export default function CategoryDetail() { + const router = useRouter(); + const { slug = '', page = 1 } = router.query; + const [dataLob, setDataLob] = useState([]); + const [finalQuery, setFinalQuery] = useState({}); + const [dataCategoriesProduct, setDataCategoriesProduct] = useState([]) + const [data, setData] = useState([]) + const dataIdCategories = [] + + const categoryName = getNameFromSlug(slug); + const lobId = getIdFromSlug(slug); + const q = router?.query.q || null; + const query = { + fq: `id:${lobId}`, + page, + }; + if (q) { + query.q = q; + } + + return ( + + + + +
+ {dataLob[0]?.categoryIds && ( +
+ +
+ )} +
+ + {!_.isEmpty(router.query) && ( + + )} +
+ ); +} -- cgit v1.2.3 From e79b956cd190419100e52a5468f91eefb7933387 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 15:25:59 +0700 Subject: update category management --- src/pages/index.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 30a7ac1f..64c880c7 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -45,9 +45,9 @@ const FlashSale = dynamic( } ); -const ProgramPromotion = dynamic(() => - import('@/lib/home/components/PromotionProgram') -); +// const ProgramPromotion = dynamic(() => +// import('@/lib/home/components/PromotionProgram') +// ); const BannerSection = dynamic(() => import('@/lib/home/components/BannerSection') @@ -138,7 +138,7 @@ export default function Home({categoryId}) {
{!auth?.feature?.soApproval && ( <> - + {/* */} )} @@ -168,7 +168,7 @@ export default function Home({categoryId}) { {!auth?.feature?.soApproval && ( <> - + {/* */} -- cgit v1.2.3 From 7c2a69c9b48c1930dc3f7cbef20d6479b3047ca2 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 17:13:30 +0700 Subject: update category lob --- src/lib/product/components/ProductSearch.jsx | 35 ++++++++++++-------- src/pages/shop/lob/[slug].jsx | 49 +++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 12e3b358..7ab6b8af 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -38,11 +38,10 @@ const ProductSearch = ({ brand = null, }) => { const router = useRouter(); - const { page = 1 } = query; const [q, setQ] = useState(query?.q || '*'); const [search, setSearch] = useState(query?.q || '*'); - const [limit, setLimit] = useState(query?.limit || 30); + const [limit, setLimit] = useState(router.query?.limit || 30); const [orderBy, setOrderBy] = useState(router.query?.orderBy || 'popular'); const [finalQuery, setFinalQuery] = useState({}); const [queryFinal, setQueryFinal] = useState({}); @@ -94,9 +93,13 @@ const ProductSearch = ({ const ids = collectIds(dataCategoriesProduct); const newQuery = { fq: `category_id_ids:(${ids.join(' OR ')})`, - page, + page : router.query.page? router.query.page : 1, brand : router.query.brand? router.query.brand : '', category : router.query.category? router.query.category : '', + priceFrom : router.query.priceFrom? router.query.priceFrom : '', + priceTo : router.query.priceTo? router.query.priceTo : '', + limit : router.query.limit? router.query.limit : '', + orderBy : router.query.orderBy? router.query.orderBy : '' }; setFinalQuery(newQuery); } else if (prefixUrl.includes('lob')){ @@ -114,9 +117,13 @@ const ProductSearch = ({ const newQuery = { fq: `category_id_ids:(${mergedArray.join(' OR ')})`, - page, - brand : router.query.brand? router.query.brand : '', category : router.query.category? router.query.category : '', + page : router.query.page? router.query.page : 1, + brand : router.query.brand? router.query.brand : '', + priceFrom : router.query.priceFrom? router.query.priceFrom : '', + priceTo : router.query.priceTo? router.query.priceTo : '', + limit : router.query.limit? router.query.limit : '', + orderBy : router.query.orderBy? router.query.orderBy : '' }; setFinalQuery(newQuery); @@ -148,17 +155,17 @@ const ProductSearch = ({ const numRows = [30, 50, 80, 100]; const [brandValues, setBrand] = useState( !router.pathname.includes('brands') - ? query.brand - ? query.brand.split(',') + ? router.query.brand + ? router.query.brand.split(',') : [] : [] ); const [categoryValues, setCategory] = useState( - query?.category?.split(',') || [] + router.query?.category?.split(',') || router.query?.category?.split(',') ); - const [priceFrom, setPriceFrom] = useState(query?.priceFrom || null); - const [priceTo, setPriceTo] = useState(query?.priceTo || null); + const [priceFrom, setPriceFrom] = useState(router.query?.priceFrom || null); + const [priceTo, setPriceTo] = useState(router.query?.priceTo || null); const pageCount = Math.ceil(productSearch.data?.response.numFound / limit); const productStart = productSearch.data?.responseHeader.params.start; @@ -373,8 +380,6 @@ const ProductSearch = ({ const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; - console.log("finalQuery",finalQuery) - return ( <> @@ -476,7 +481,8 @@ const ProductSearch = ({ @@ -665,7 +671,8 @@ const ProductSearch = ({
diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx index 2153b565..cdaf3c91 100644 --- a/src/pages/shop/lob/[slug].jsx +++ b/src/pages/shop/lob/[slug].jsx @@ -24,8 +24,55 @@ export default function CategoryDetail() { const categoryName = getNameFromSlug(slug); const lobId = getIdFromSlug(slug); const q = router?.query.q || null; + + useEffect(() => { + if(router.pathname.includes('lob')){ + const loadProduct = async () => { + const lobData = await odooApi('GET', `/api/v1/lob_homepage/${lobId}/category_id`); + + if (lobData) { + setDataLob(lobData); + } + }; + loadProduct(); + + } + }, [lobId]); + + useEffect(() => { + if (router.pathname.includes('lob')){ + + const fetchCategoryData = async () => { + if (dataLob[0]?.categoryIds) { + + for (const cate of dataLob[0].categoryIds) { + + dataIdCategories.push(cate.childId) + } + + + setData(dataIdCategories.flat()) + + // const newQuery = { + // fq: `category_id_ids:(${mergedArray.join(' OR ')})`, + // category : router.query.category? router.query.category : '', + // page : router.query.page? router.query.page : 1, + // brand : router.query.brand? router.query.brand : '', + // priceFrom, + // priceTo, + // limit, + // orderBy + // }; + + // setFinalQuery(newQuery); + + } + }; + fetchCategoryData(); + } + }, [dataCategoriesProduct, dataLob]); const query = { - fq: `id:${lobId}`, + fq: `category_id_ids:(${data.join(' OR ')})`, page, }; if (q) { -- cgit v1.2.3 From 7f060ad3f3d938a462292721b9c54d1cb9140ad3 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 29 Jul 2024 17:17:17 +0700 Subject: update category managemrnt --- src/lib/home/components/CategoryPilihan.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 5548fc1b..183c123a 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -39,7 +39,7 @@ const CategoryPilihan = ({ id, categories }) => {
{categoryPilihan?.data?.map((category) => ( -
+
-- cgit v1.2.3 From 593c508bb87451a985a5aec7e9d7bde45b18074b Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 09:53:35 +0700 Subject: update category lob --- src/lib/product/components/LobSectionCategory.jsx | 1 - src/lib/product/components/ProductSearch.jsx | 9 ++-- src/pages/shop/lob/[slug].jsx | 63 +---------------------- 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/src/lib/product/components/LobSectionCategory.jsx b/src/lib/product/components/LobSectionCategory.jsx index 34a09e46..03d6e8c0 100644 --- a/src/lib/product/components/LobSectionCategory.jsx +++ b/src/lib/product/components/LobSectionCategory.jsx @@ -22,7 +22,6 @@ const LobSectionCategory = ({ categories }) => { const handleToggleCategories = () => { setIsOpenCategory(!isOpenCategory); }; - console.log("categories",categories[0]?.categoryIds) const displayedCategories = categories[0]?.categoryIds; diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 7ab6b8af..d4c5a308 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -379,7 +379,6 @@ const ProductSearch = ({ }; const isNotReadyStockPage = router.asPath !== '/shop/search?orderBy=stock'; - return ( <> @@ -481,8 +480,8 @@ const ProductSearch = ({ @@ -671,8 +670,8 @@ const ProductSearch = ({
diff --git a/src/pages/shop/lob/[slug].jsx b/src/pages/shop/lob/[slug].jsx index cdaf3c91..d939c25c 100644 --- a/src/pages/shop/lob/[slug].jsx +++ b/src/pages/shop/lob/[slug].jsx @@ -25,60 +25,6 @@ export default function CategoryDetail() { const lobId = getIdFromSlug(slug); const q = router?.query.q || null; - useEffect(() => { - if(router.pathname.includes('lob')){ - const loadProduct = async () => { - const lobData = await odooApi('GET', `/api/v1/lob_homepage/${lobId}/category_id`); - - if (lobData) { - setDataLob(lobData); - } - }; - loadProduct(); - - } - }, [lobId]); - - useEffect(() => { - if (router.pathname.includes('lob')){ - - const fetchCategoryData = async () => { - if (dataLob[0]?.categoryIds) { - - for (const cate of dataLob[0].categoryIds) { - - dataIdCategories.push(cate.childId) - } - - - setData(dataIdCategories.flat()) - - // const newQuery = { - // fq: `category_id_ids:(${mergedArray.join(' OR ')})`, - // category : router.query.category? router.query.category : '', - // page : router.query.page? router.query.page : 1, - // brand : router.query.brand? router.query.brand : '', - // priceFrom, - // priceTo, - // limit, - // orderBy - // }; - - // setFinalQuery(newQuery); - - } - }; - fetchCategoryData(); - } - }, [dataCategoriesProduct, dataLob]); - const query = { - fq: `category_id_ids:(${data.join(' OR ')})`, - page, - }; - if (q) { - query.q = q; - } - return ( -
- {dataLob[0]?.categoryIds && ( -
- -
- )} -
{!_.isEmpty(router.query) && ( - + )}
); -- cgit v1.2.3 From de27df05af1f23d70099d36d11e07f35faff26c6 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 13:25:14 +0700 Subject: update mobile view --- .../components/elements/Navbar/NavbarMobile.jsx | 4 +- src/core/components/elements/Navbar/TopBanner.jsx | 29 ++-- src/lib/home/components/CategoryPilihan.jsx | 147 +++++++++++++++------ 3 files changed, 119 insertions(+), 61 deletions(-) diff --git a/src/core/components/elements/Navbar/NavbarMobile.jsx b/src/core/components/elements/Navbar/NavbarMobile.jsx index bcf45e0a..90314671 100644 --- a/src/core/components/elements/Navbar/NavbarMobile.jsx +++ b/src/core/components/elements/Navbar/NavbarMobile.jsx @@ -11,7 +11,7 @@ import Image from 'next/image'; import { useEffect, useState } from 'react'; import MobileView from '../../views/MobileView'; import Link from '../Link/Link'; -// import TopBanner from './TopBanner'; +import TopBanner from './TopBanner'; const Search = dynamic(() => import('./Search')); @@ -39,7 +39,7 @@ const NavbarMobile = () => { return ( - {/* */} +
) } -- cgit v1.2.3 From a3875b3e803d7075fa8788286fb478bb0c825d26 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 14:06:55 +0700 Subject: update category management banner --- src/lib/home/components/CategoryPilihan.jsx | 17 ++++++----------- src/pages/index.jsx | 2 +- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index e47524aa..72e6f6a8 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -23,25 +23,21 @@ const CategoryPilihan = ({ id, categories }) => {
LOB Kategori Pilihan

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

-
{heroBanner.data && heroBanner.data?.length > 0 && ( -
- +
+ {heroBanner.data[0].name} -
- +
)} -
{categoryPilihan?.data?.map((category) => (
@@ -72,7 +68,7 @@ const CategoryPilihan = ({ id, categories }) => {
LOB Kategori Pilihan
{/*

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

*/}
-
+
{heroBanner.data && heroBanner.data?.length > 0 && (
@@ -87,7 +83,6 @@ const CategoryPilihan = ({ id, categories }) => { />
- )}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 64c880c7..9d9d5dc0 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -156,7 +156,7 @@ export default function Home({categoryId}) { -
+
-- cgit v1.2.3 From d14f51d91cfb8851ae2c335628737d2f516dbf6a Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 14:25:53 +0700 Subject: update category management --- src/lib/home/components/CategoryPilihan.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/home/components/CategoryPilihan.jsx b/src/lib/home/components/CategoryPilihan.jsx index 72e6f6a8..6568621c 100644 --- a/src/lib/home/components/CategoryPilihan.jsx +++ b/src/lib/home/components/CategoryPilihan.jsx @@ -88,7 +88,7 @@ const CategoryPilihan = ({ id, categories }) => { {categoryPilihan?.data?.map((category) => ( -
+
-- cgit v1.2.3 From 53d214ef3222bcc4169b188bff3dadf6c43f6b7e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 14:27:23 +0700 Subject: git aMerge branch 'Feature/category-management' into development --- .../components/elements/Navbar/NavbarMobile.jsx | 4 +- src/core/components/elements/Navbar/TopBanner.jsx | 29 ++--- src/lib/home/components/CategoryPilihan.jsx | 142 ++++++++++++++------- src/pages/index.jsx | 4 +- 4 files changed, 116 insertions(+), 63 deletions(-) diff --git a/src/core/components/elements/Navbar/NavbarMobile.jsx b/src/core/components/elements/Navbar/NavbarMobile.jsx index bcf45e0a..90314671 100644 --- a/src/core/components/elements/Navbar/NavbarMobile.jsx +++ b/src/core/components/elements/Navbar/NavbarMobile.jsx @@ -11,7 +11,7 @@ import Image from 'next/image'; import { useEffect, useState } from 'react'; import MobileView from '../../views/MobileView'; import Link from '../Link/Link'; -// import TopBanner from './TopBanner'; +import TopBanner from './TopBanner'; const Search = dynamic(() => import('./Search')); @@ -39,7 +39,7 @@ const NavbarMobile = () => { return ( - {/* */} +
) } diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 64c880c7..d649ee17 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -61,7 +61,7 @@ const CategoryDynamic = dynamic(() => ); const CategoryDynamicMobile = dynamic(() => - import('@/lib/home/components/CategoryDynamicMobile') +import('@/lib/home/components/CategoryDynamicMobile') ); const CustomerReviews = dynamic(() => @@ -156,7 +156,7 @@ export default function Home({categoryId}) { -
+
-- cgit v1.2.3 From c92b47f81b4ea90f799810555395af7afcfa5a4d Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 14:47:28 +0700 Subject: update category management --- src/lib/product/components/ProductSearch.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index d4c5a308..09534a5d 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -249,6 +249,7 @@ const ProductSearch = ({ brands.push({ brand, qty }); } } + const categories = []; for ( @@ -263,6 +264,7 @@ const ProductSearch = ({ categories.push({ name, qty }); } } + const orderOptions = [ { value: 'price-asc', label: 'Harga Terendah' }, @@ -340,7 +342,7 @@ const ProductSearch = ({ q: router.query.q, orderBy: orderBy, brand: brandValues.join(','), - category: categoryValues.join(','), + category: categoryValues?.join(','), priceFrom, priceTo, }; -- cgit v1.2.3 From 5296ce7dba6cf674b4942113a7716a89f05b64e0 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 15:06:02 +0700 Subject: update category management search product --- src/lib/product/components/ProductFilterDesktop.jsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx index e4a62abb..384f2daa 100644 --- a/src/lib/product/components/ProductFilterDesktop.jsx +++ b/src/lib/product/components/ProductFilterDesktop.jsx @@ -102,7 +102,19 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu } params = _.pickBy(params, _.identity) params = toQuery(params) - router.push(`${prefixUrl}?${params}`) + + const slug = Array.isArray(router.query.slug) ? router.query.slug[0] : router.query.slug; + + if (slug) { + if(prefixUrl.includes('category') || prefixUrl.includes('lob')){ + router.push(`${prefixUrl}?${params}`) + }else{ + router.push(`${prefixUrl}/${slug}?${params}`) + } + } else { + router.push(`${prefixUrl}?${params}`) + } + } -- cgit v1.2.3 From 09e2fd0ec1e2a1d8438ec1c630a08bc349400ecb Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 15:08:00 +0700 Subject: update error code --- src/lib/product/components/ProductFilterDesktop.jsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx index 384f2daa..a8073036 100644 --- a/src/lib/product/components/ProductFilterDesktop.jsx +++ b/src/lib/product/components/ProductFilterDesktop.jsx @@ -21,6 +21,7 @@ import Image from '@/core/components/elements/Image/Image' import { formatCurrency } from '@/core/utils/formatValue' const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = null }) => { + const router = useRouter() const { query } = router const [order, setOrder] = useState(query?.orderBy) @@ -102,19 +103,14 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu } params = _.pickBy(params, _.identity) params = toQuery(params) - + const slug = Array.isArray(router.query.slug) ? router.query.slug[0] : router.query.slug; if (slug) { - if(prefixUrl.includes('category') || prefixUrl.includes('lob')){ - router.push(`${prefixUrl}?${params}`) - }else{ - router.push(`${prefixUrl}/${slug}?${params}`) - } + router.push(`${prefixUrl}/${slug}?${params}`) } else { router.push(`${prefixUrl}?${params}`) } - } -- cgit v1.2.3 From 7dc18df04a6cf75e696f53ca578e4c36cfce9748 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 15:12:00 +0700 Subject: update category management filter search --- src/lib/product/components/ProductFilterDesktop.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/product/components/ProductFilterDesktop.jsx b/src/lib/product/components/ProductFilterDesktop.jsx index a8073036..1933c5f0 100644 --- a/src/lib/product/components/ProductFilterDesktop.jsx +++ b/src/lib/product/components/ProductFilterDesktop.jsx @@ -107,7 +107,11 @@ const ProductFilterDesktop = ({ brands, categories, prefixUrl, defaultBrand = nu const slug = Array.isArray(router.query.slug) ? router.query.slug[0] : router.query.slug; if (slug) { - router.push(`${prefixUrl}/${slug}?${params}`) + if(prefixUrl.includes('category') || prefixUrl.includes('lob')){ + router.push(`${prefixUrl}?${params}`) + }else{ + router.push(`${prefixUrl}/${slug}?${params}`) + } } else { router.push(`${prefixUrl}?${params}`) } -- cgit v1.2.3 From 067b536d7ea507575bd5bc3c12815927bd40d103 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 16:06:13 +0700 Subject: add skeleton --- src/lib/home/components/CategoryDynamic.jsx | 114 +++++++++++++++------------- 1 file changed, 63 insertions(+), 51 deletions(-) diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index 6ab03ec3..dda7cdc4 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -4,6 +4,7 @@ import NextImage from 'next/image'; import Link from "next/link"; import { createSlug } from '@/core/utils/slug'; import odooApi from '@/core/api/odooApi'; +import { Skeleton} from '@chakra-ui/react' const CategoryDynamic = () => { const { categoryManagement } = useCategoryManagement(); @@ -41,62 +42,73 @@ const CategoryDynamic = () => { return (
- {categoryManagement && categoryManagement.data?.map((category) => { - const countLevel1 = categoryData[category.categoryIdI] || 0; - - return ( -
-
-
{category.name}
-

{countLevel1} Produk tersedia

- Lihat Semua -
-
- {category.categories.map((subCategory) => { - const countLevel2 = subCategoryData[subCategory.idLevel2] || 0; + {categoryManagement && categoryManagement.data?.map((category) => { + const countLevel1 = categoryData[category.categoryIdI] || 0; + + return ( + +
+
+
{category.name}
+

+ {countLevel1 === 0 ? 'Menghitung jumlah produk...' : `${countLevel1} Produk tersedia`} +

+ Lihat Semua +
+
+ {category.categories.map((subCategory) => { + const countLevel2 = subCategoryData[subCategory.idLevel2] || 0; - return ( -
-
-
- -
-
{subCategory.name}
-

{countLevel2} Produk tersedia

- Lihat Semua -
-
-
- {subCategory.childFrontendIdI.map((childCategory) => ( -
- - -
-
{childCategory.name}
-
- + return ( +
+
+
+ +
+
{subCategory.name}
+ {/*

+ {countLevel2 === 0 ? 'Menghitung jumlah produk...' : `${countLevel2} Produk tersedia`} +

*/} + +

+ {countLevel2} Produk tersedia +

+
+ Lihat Semua
- ))} +
+
+ {subCategory.childFrontendIdI.map((childCategory) => ( +
+ + +
+
{childCategory.name}
+
+ +
+ ))} +
-
- ); - })} + ); + })} +
-
- ); - })} + + ); + })}
); }; -- cgit v1.2.3 From c62a5dd32e961f06a01d0a535d2fbf37118ff2e7 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 30 Jul 2024 16:09:07 +0700 Subject: add key missing --- src/lib/home/components/CategoryDynamic.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index dda7cdc4..60e01df0 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -46,7 +46,7 @@ const CategoryDynamic = () => { const countLevel1 = categoryData[category.categoryIdI] || 0; return ( - +
{category.name}
-- cgit v1.2.3 From 8fe0cdf1f457148eb39d5438b13bbec7bc912976 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 31 Jul 2024 08:59:17 +0700 Subject: update category management --- src/lib/home/components/CategoryDynamic.jsx | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index 60e01df0..f2d1a16f 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -18,14 +18,10 @@ const CategoryDynamic = () => { const updatedSubCategoryData = {}; for (const category of categoryManagement.data) { - // Calculate level 1 products const countLevel1 = await odooApi('GET', `/api/v1/category/numFound?parent_id=${category.categoryIdI}`); - // console.log("countLevel1.child",countLevel1) updatedCategoryData[category.categoryIdI] = countLevel1?.numFound; - - // Calculate level 2 products for each sub-category for (const subCategory of countLevel1.children) { updatedSubCategoryData[subCategory.id] = subCategory.numFound; } @@ -50,9 +46,9 @@ const CategoryDynamic = () => {
{category.name}
-

- {countLevel1 === 0 ? 'Menghitung jumlah produk...' : `${countLevel1} Produk tersedia`} -

+ +

{countLevel1} Produk tersedia

+
Lihat Semua
@@ -72,9 +68,6 @@ const CategoryDynamic = () => { />
{subCategory.name}
- {/*

- {countLevel2 === 0 ? 'Menghitung jumlah produk...' : `${countLevel2} Produk tersedia`} -

*/}

{countLevel2} Produk tersedia -- cgit v1.2.3 From 7cac694f5a78f01e7e8185f7d37b758e9b7dab34 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 31 Jul 2024 14:01:48 +0700 Subject: add pop up cart --- src/lib/cart/components/Cartheader.jsx | 250 +++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index 19f79bc9..a7dd621d 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -1,14 +1,21 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { getCartApi } from '../api/CartApi' +import currencyFormat from '@/core/utils/currencyFormat' +import Image from '@/core/components/elements/Image/Image' +import { createSlug } from '@/core/utils/slug' import useAuth from '@/core/hooks/useAuth' import { useRouter } from 'next/router' import odooApi from '@/core/api/odooApi' import { useProductCartContext } from '@/contexts/ProductCartContext' +import whatsappUrl from '@/core/utils/whatsappUrl' +import { AnimatePresence, motion } from 'framer-motion' +import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css' const { ShoppingCartIcon, PhotoIcon } = require('@heroicons/react/24/outline') const { default: Link } = require('next/link') const Cardheader = (cartCount) => { + const router = useRouter() const [subTotal, setSubTotal] = useState(null) const [buttonLoading, SetButtonTerapkan] = useState(false) @@ -109,6 +116,249 @@ const Cardheader = (cartCount) => {

+ + {isHovered && ( + <> + + + + +
+
Keranjang Belanja
+ + Lihat Semua + +
+
+
+ {!auth && ( +
+

+ Silahkan{' '} + + Login + {' '} + Untuk Melihat Daftar Keranjang Belanja Anda +

+
+ )} + {isLoading && + itemLoading.map((item) => ( +
+
+
+ +
+
+
+
+
+
+
+
+ ))} + {auth && products.length === 0 && !isLoading && ( +
+

+ Tidak Ada Produk di Keranjang Belanja Anda +

+
+ )} + {auth && products.length > 0 && !isLoading && ( + <> +
    + {products && + products?.map((product, index) => ( + <> +
  • +
    +
    + {product.cartType === 'promotion' && ( + {product.name} + )} + {product.cartType === 'product' && ( + + {product?.name} + + )} +
    +
    + {product.cartType === 'promotion' && ( +

    + {product.name} +

    + )} + {product.cartType === 'product' && ( + + {' '} +

    + {product.parent.name} +

    + + )} + + {product?.hasFlashsale && ( +
    +
    + {product?.price?.discountPercentage}% +
    +
    + {currencyFormat(product?.price?.price)} +
    +
    + )} + +
    +
    + {product?.price?.priceDiscount > 0 ? ( + currencyFormat(product?.price?.priceDiscount) + ) : ( + + + Call For Price + + + )} +
    +
    +
    +
    +
    + {product.products?.map((product) => +
    + + {product?.image && {product.name}} + + +
    + + {product.displayName} + + +
    +
    + {/*
    {product.code}
    */} +
    + Berat Barang: + {product.packageWeight} Kg +
    +
    +
    +
    + +
    + )} + {product.freeProducts?.map((product) => +
    + + {product?.image && {product.name}} + + +
    + + {product.displayName} + + +
    +
    + {/*
    {product.code}
    */} +
    + Berat Barang: + {product.packageWeight} Kg +
    +
    +
    +
    + +
    + )} +
    +
  • + + ))} +
+
+ + )} +
+ {auth && products.length > 0 && !isLoading && ( + <> +
+ Subtotal Sebelum PPN : + {currencyFormat(subTotal)} +
+
+ +
+ + )} +
+
+ + )} +
+
) } -- cgit v1.2.3 From 12f581a4c0c4a3316385015622823c9e5935bb05 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 31 Jul 2024 14:13:10 +0700 Subject: update pop up cart --- src/lib/cart/components/Cartheader.jsx | 19 ++++++++++++++++--- src/lib/home/components/CategoryDynamic.jsx | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index a7dd621d..c8aa7cc3 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -26,6 +26,7 @@ const Cardheader = (cartCount) => { useProductCartContext() const [isHovered, setIsHovered] = useState(false) + const [isTop, setIsTop] = useState(true) const products = useMemo(() => { return productCart?.products || [] @@ -84,12 +85,24 @@ const Cardheader = (cartCount) => { setCountCart(cartCount.cartCount) }, [cartCount]) + useEffect(() => { + const handleScroll = () => { + setIsTop(window.scrollY === 0) + } + + window.addEventListener('scroll', handleScroll) + return () => { + window.removeEventListener('scroll', handleScroll) + } + }, []) + const handleCheckout = async () => { SetButtonTerapkan(true) let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`) router.push('/shop/checkout') } + return (
@@ -121,10 +134,10 @@ const Cardheader = (cartCount) => { <> { // Calculate level 2 products for each sub-category - for (const subCategory of countLevel1.children) { + for (const subCategory of countLevel1?.children) { updatedSubCategoryData[subCategory.id] = subCategory.numFound; } } -- cgit v1.2.3 From 6e5766739b0684919c8630580403ed279cc3a71e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 31 Jul 2024 14:14:27 +0700 Subject: back log --- src/lib/home/components/CategoryDynamic.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index dae17c94..6ab03ec3 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -25,7 +25,7 @@ const CategoryDynamic = () => { // Calculate level 2 products for each sub-category - for (const subCategory of countLevel1?.children) { + for (const subCategory of countLevel1.children) { updatedSubCategoryData[subCategory.id] = subCategory.numFound; } } -- cgit v1.2.3 From 8a03b5a325692fd39c193f2a12b1a9aa4af1553e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 31 Jul 2024 14:31:34 +0700 Subject: update cart pop up --- src/lib/cart/components/Cartheader.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index c8aa7cc3..7d43a4da 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -290,7 +290,7 @@ const Cardheader = (cartCount) => {
-
+
{product.products?.map((product) =>
-- cgit v1.2.3 From 4339c49be8f30dbb47b6882e61e909837dc91e81 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 31 Jul 2024 15:39:21 +0700 Subject: update auto reload add cart --- src-migrate/modules/product-detail/components/AddToCart.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index 097db98a..c4df555b 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -51,6 +51,9 @@ const AddToCart = ({ error: { title: 'Menambahkan ke keranjang', description: 'Gagal menambahkan ke keranjang belanja' }, } ) + setTimeout(() => { + window.location.reload(); + }, 1500); if (source === 'buy') { router.push('/shop/checkout?source=buy') -- cgit v1.2.3 From 0abd42f8b528b3166169fef7093d4d8b22f3fb79 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 1 Aug 2024 08:48:48 +0700 Subject: add pop up when hit keranjang button --- .../product-detail/components/AddToCart.tsx | 83 +++++++++++++++++++--- .../product-detail/components/PriceAction.tsx | 2 + .../product-detail/components/ProductDetail.tsx | 2 +- .../modules/product-promo/components/AddToCart.tsx | 65 ++++++++++++++++- .../modules/product-promo/components/Card.tsx | 9 +-- .../modules/product-promo/components/Section.tsx | 8 ++- src-migrate/types/promotion.ts | 3 + 7 files changed, 152 insertions(+), 20 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index c4df555b..b2fed55d 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -1,19 +1,28 @@ -import { Button, useToast } from '@chakra-ui/react' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import { Button, Link, useToast } from '@chakra-ui/react' +import product from 'next-seo/lib/jsonld/product' import { useRouter } from 'next/router' - +import { useState } from 'react' +import Image from '~/components/ui/image' import { getAuth } from '~/libs/auth' import { upsertUserCart } from '~/services/cart' +import LazyLoad from 'react-lazy-load'; +import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar'; +import { IProductDetail } from '~/types/product'; +import ImageNext from 'next/image'; type Props = { variantId: number | null, quantity?: number; source?: 'buy' | 'add_to_cart'; + products : IProductDetail } const AddToCart = ({ variantId, quantity = 1, - source = 'add_to_cart' + source = 'add_to_cart', + products }: Props) => { const auth = getAuth() const router = useRouter() @@ -21,6 +30,15 @@ const AddToCart = ({ position: 'top', isClosable: true }) + const [product, setProducts] = useState(products); + + const productSimilarQuery = [ + product?.name, + `fq=-product_id_i:${product.id}`, + `fq=-manufacture_id_i:${product.manufacture?.id || 0}`, + ].join('&'); + + const [addCartAlert, setAddCartAlert] = useState(false); const handleClick = async () => { if (typeof auth !== 'object') { @@ -34,6 +52,7 @@ const AddToCart = ({ isNaN(quantity) || typeof auth !== 'object' ) return; + setAddCartAlert(true); toast.promise( upsertUserCart({ @@ -51,9 +70,8 @@ const AddToCart = ({ error: { title: 'Menambahkan ke keranjang', description: 'Gagal menambahkan ke keranjang belanja' }, } ) - setTimeout(() => { - window.location.reload(); - }, 1500); + + if (source === 'buy') { router.push('/shop/checkout?source=buy') @@ -72,10 +90,55 @@ const AddToCart = ({ } return ( - +
+ + { + setAddCartAlert(false); + setTimeout(() => { + window.location.reload(); + }, 1500); + }} + > +
+
+ +
+
+ {product.name} +
+
+ + Lihat Keranjang + +
+
+ +
+
+ Kamu Mungkin Juga Suka +
+ + + +
+
+
) } -export default AddToCart \ No newline at end of file +export default AddToCart \ No newline at end of file diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx index 81271f6e..9021264e 100644 --- a/src-migrate/modules/product-detail/components/PriceAction.tsx +++ b/src-migrate/modules/product-detail/components/PriceAction.tsx @@ -97,12 +97,14 @@ const PriceAction = ({ product }: Props) => { className={style['quantity-input']} /> {!isApproval && ( diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index fad35a7d..e4555913 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -129,7 +129,7 @@ const ProductDetail = ({ product }: Props) => { )}
- {!!activeVariantId && !isApproval && } + {!!activeVariantId && !isApproval && }

diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx index 87017c14..488f3f98 100644 --- a/src-migrate/modules/product-promo/components/AddToCart.tsx +++ b/src-migrate/modules/product-promo/components/AddToCart.tsx @@ -9,19 +9,34 @@ import { IPromotion } from '~/types/promotion' import DesktopView from '../../../../src/core/components/views/DesktopView'; import MobileView from '../../../../src/core/components/views/MobileView'; +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import ImageNext from 'next/image'; +import Link from 'next/link' +import LazyLoad from 'react-lazy-load' +import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar'; +import { IProductDetail } from '~/types/product'; type Props = { promotion: IPromotion + product: IProductDetail } type Status = 'idle' | 'loading' | 'success' -const ProductPromoAddToCart = ({ promotion }: Props) => { +const ProductPromoAddToCart = ({product, promotion }: Props) => { + console.log("promotion",promotion) const auth = getAuth() const toast = useToast() const router = useRouter() const [status, setStatus] = useState('idle') + + const productSimilarQuery = [ + promotion?.name, + `fq=-product_id_i:${promotion.products[0].product_id}`, + ].join('&'); + + const [addCartAlert, setAddCartAlert] = useState(false); const handleButton = async () => { if (typeof auth !== 'object') { @@ -42,7 +57,7 @@ const ProductPromoAddToCart = ({ promotion }: Props) => { qtyAppend: true }) setStatus('idle') - + setAddCartAlert(true); toast({ title: 'Tambah ke keranjang', description: 'Berhasil menambahkan barang ke keranjang belanja', @@ -51,6 +66,9 @@ const ProductPromoAddToCart = ({ promotion }: Props) => { isClosable: true, position: 'top', }) + // setTimeout(() => { + // window.location.reload(); + // }, 1500); } useEffect(() => { @@ -92,6 +110,49 @@ const ProductPromoAddToCart = ({ promotion }: Props) => { {status === 'success' && Berhasil} {status !== 'success' && Keranjang} + { + setAddCartAlert(false); + setTimeout(() => { + window.location.reload(); + }, 1500); + }} + > +
+
+ +
+
+ {product.name} +
+
+ + Lihat Keranjang + +
+
+ +
+
+ Kamu Mungkin Juga Suka +
+ + + +
+

) diff --git a/src-migrate/modules/product-promo/components/Card.tsx b/src-migrate/modules/product-promo/components/Card.tsx index 728d23ca..b286aa5b 100644 --- a/src-migrate/modules/product-promo/components/Card.tsx +++ b/src-migrate/modules/product-promo/components/Card.tsx @@ -15,16 +15,17 @@ import clsxm from '~/libs/clsxm' import ProductPromoItem from './Item' import ProductPromoAddToCart from "./AddToCart" import ProductPromoCardCountdown from "./CardCountdown" +import { IProductDetail } from '~/types/product'; import MobileView from '../../../../src/core/components/views/MobileView'; import DesktopView from '../../../../src/core/components/views/DesktopView'; type Props = { promotion: IPromotion - + product: IProductDetail } -const ProductPromoCard = ({ promotion}: Props) => { +const ProductPromoCard = ({product, promotion}: Props) => { const [products, setProducts] = useState([]) const [freeProducts, setFreeProducts] = useState([]) const [error, setError] = useState(null) @@ -132,7 +133,7 @@ const ProductPromoCard = ({ promotion}: Props) => {
- +
@@ -189,7 +190,7 @@ const ProductPromoCard = ({ promotion}: Props) => {
- +
diff --git a/src-migrate/modules/product-promo/components/Section.tsx b/src-migrate/modules/product-promo/components/Section.tsx index 4e8a7dd5..ff565539 100644 --- a/src-migrate/modules/product-promo/components/Section.tsx +++ b/src-migrate/modules/product-promo/components/Section.tsx @@ -9,12 +9,14 @@ import { IPromotion } from '~/types/promotion' import { useModalStore } from "../stores/useModalStore" import ProductPromoCard from './Card' import ProductPromoModal from "./Modal" +import { IProductDetail } from '~/types/product'; type Props = { productId: number; + product: IProductDetail } -const ProductPromoSection = ({ productId }: Props) => { +const ProductPromoSection = ({product, productId }: Props) => { const promotionsQuery = useQuery({ queryKey: [`promotions.highlight`, productId], queryFn: async () => await fetch(`/api/product-variant/${productId}/promotion/highlight`).then((res) => res.json()) as { data: IPromotion[] } @@ -23,7 +25,7 @@ const ProductPromoSection = ({ productId }: Props) => { const promotions = promotionsQuery.data const { openModal } = useModalStore() - + console.log("productId",productId) return ( 0) || false} @@ -50,7 +52,7 @@ const ProductPromoSection = ({ productId }: Props) => { > {promotions?.data.map((promotion) => (
- +
))} diff --git a/src-migrate/types/promotion.ts b/src-migrate/types/promotion.ts index 85190aad..217bba33 100644 --- a/src-migrate/types/promotion.ts +++ b/src-migrate/types/promotion.ts @@ -10,15 +10,18 @@ export interface IPromotion { limit_user: number; limit_trx: number; price: number; + image: string; total_qty: number; products: { product_id: number; qty: number; + name: string; }[]; free_products: { product_id: number; qty: number; }[]; + } export interface IProductVariantPromo { -- cgit v1.2.3 From 7dbca25dede6cf213831f45321f5c7a28b4a6122 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 1 Aug 2024 09:07:41 +0700 Subject: add parameter product --- src-migrate/modules/product-promo/components/Modal.tsx | 8 ++++++-- src-migrate/modules/product-promo/components/ModalContent.tsx | 9 ++++++--- src-migrate/modules/product-promo/components/Section.tsx | 2 +- src-migrate/modules/promo/components/PromoList.tsx | 4 ++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src-migrate/modules/product-promo/components/Modal.tsx b/src-migrate/modules/product-promo/components/Modal.tsx index 0de672c2..1722b9df 100644 --- a/src-migrate/modules/product-promo/components/Modal.tsx +++ b/src-migrate/modules/product-promo/components/Modal.tsx @@ -3,8 +3,12 @@ import { Modal } from "~/components/ui/modal" import { useModalStore } from '../stores/useModalStore' import ProductPromoCategoryTab from './CategoryTab' import ProductPromoModalContent from './ModalContent' +import { IProductDetail } from '~/types/product'; -const ProductPromoModal = () => { +type Props = { + product: IProductDetail +} +const ProductPromoModal = ({product}:Props) => { const { active, closeModal } = useModalStore() return ( @@ -17,7 +21,7 @@ const ProductPromoModal = () => {
- + ) } diff --git a/src-migrate/modules/product-promo/components/ModalContent.tsx b/src-migrate/modules/product-promo/components/ModalContent.tsx index ab5129f8..44ad52d6 100644 --- a/src-migrate/modules/product-promo/components/ModalContent.tsx +++ b/src-migrate/modules/product-promo/components/ModalContent.tsx @@ -5,8 +5,11 @@ import { getVariantPromoByCategory } from "~/services/productVariant" import { useModalStore } from "../stores/useModalStore" import ProductPromoCard from "./Card" - -const ProductPromoModalContent = () => { +import { IProductDetail } from '~/types/product'; +type Props = { + product: IProductDetail +} +const ProductPromoModalContent = ({product}:Props) => { const { activeTab, variantId } = useModalStore() const promotionsQuery = useQuery( @@ -24,7 +27,7 @@ const ProductPromoModalContent = () => {
{promotions?.data.map((promo) => ( - + ))} {promotions?.data.length === 0 && (
Belum ada promo pada kategori ini
diff --git a/src-migrate/modules/product-promo/components/Section.tsx b/src-migrate/modules/product-promo/components/Section.tsx index ff565539..05b849c7 100644 --- a/src-migrate/modules/product-promo/components/Section.tsx +++ b/src-migrate/modules/product-promo/components/Section.tsx @@ -32,7 +32,7 @@ const ProductPromoSection = ({product, productId }: Props) => { height='450px' duration='700ms' > - + {promotions?.data && promotions?.data.length > 0 && (
diff --git a/src-migrate/modules/promo/components/PromoList.tsx b/src-migrate/modules/promo/components/PromoList.tsx index 42725034..4d0db3c2 100644 --- a/src-migrate/modules/promo/components/PromoList.tsx +++ b/src-migrate/modules/promo/components/PromoList.tsx @@ -114,7 +114,7 @@ const PromoList: React.FC = ({ selectedPromo }) => { {promoData?.map((promotion: IPromotion) => (
- +
))} @@ -122,7 +122,7 @@ const PromoList: React.FC = ({ selectedPromo }) => { )} {isMobile && (promoData?.map((promotion: IPromotion) => (
- +
)))} -- cgit v1.2.3 From 285e91d4b63ca8dbd0a9f55e9c7db8b833749c0a Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 1 Aug 2024 13:28:41 +0700 Subject: update popup cart --- .../modules/product-detail/components/AddToCart.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index b2fed55d..42586032 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -10,6 +10,7 @@ import LazyLoad from 'react-lazy-load'; import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar'; import { IProductDetail } from '~/types/product'; import ImageNext from 'next/image'; +import { useProductCartContext } from '@/contexts/ProductCartContext' type Props = { variantId: number | null, @@ -31,7 +32,9 @@ const AddToCart = ({ isClosable: true }) const [product, setProducts] = useState(products); - + const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = + useProductCartContext() + const productSimilarQuery = [ product?.name, `fq=-product_id_i:${product.id}`, @@ -53,7 +56,7 @@ const AddToCart = ({ typeof auth !== 'object' ) return; setAddCartAlert(true); - + setRefreshCart(true) toast.promise( upsertUserCart({ userId: auth.id, @@ -100,10 +103,11 @@ const AddToCart = ({ active={addCartAlert} close={() => { setAddCartAlert(false); - setTimeout(() => { - window.location.reload(); - }, 1500); - }} + // setTimeout(() => { + // window.location.reload(); + // }, 1500); + } + } >
-- cgit v1.2.3 From 42829a0907590139ecf4328a7a9ff9f6504a9113 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 1 Aug 2024 13:40:57 +0700 Subject: update pop up cart --- src-migrate/modules/product-detail/components/AddToCart.tsx | 5 +---- src-migrate/modules/product-promo/components/AddToCart.tsx | 12 ++++-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index 42586032..644d5b90 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -56,7 +56,7 @@ const AddToCart = ({ typeof auth !== 'object' ) return; setAddCartAlert(true); - setRefreshCart(true) + setRefreshCart(true); toast.promise( upsertUserCart({ userId: auth.id, @@ -103,9 +103,6 @@ const AddToCart = ({ active={addCartAlert} close={() => { setAddCartAlert(false); - // setTimeout(() => { - // window.location.reload(); - // }, 1500); } } > diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx index 488f3f98..aae5cfc0 100644 --- a/src-migrate/modules/product-promo/components/AddToCart.tsx +++ b/src-migrate/modules/product-promo/components/AddToCart.tsx @@ -15,6 +15,7 @@ import Link from 'next/link' import LazyLoad from 'react-lazy-load' import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar'; import { IProductDetail } from '~/types/product'; +import { useProductCartContext } from '@/contexts/ProductCartContext' type Props = { promotion: IPromotion @@ -24,13 +25,13 @@ type Props = { type Status = 'idle' | 'loading' | 'success' const ProductPromoAddToCart = ({product, promotion }: Props) => { - console.log("promotion",promotion) const auth = getAuth() const toast = useToast() const router = useRouter() const [status, setStatus] = useState('idle') - + const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = + useProductCartContext() const productSimilarQuery = [ promotion?.name, `fq=-product_id_i:${promotion.products[0].product_id}`, @@ -58,6 +59,7 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => { }) setStatus('idle') setAddCartAlert(true); + setRefreshCart(true); toast({ title: 'Tambah ke keranjang', description: 'Berhasil menambahkan barang ke keranjang belanja', @@ -66,9 +68,6 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => { isClosable: true, position: 'top', }) - // setTimeout(() => { - // window.location.reload(); - // }, 1500); } useEffect(() => { @@ -116,9 +115,6 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => { active={addCartAlert} close={() => { setAddCartAlert(false); - setTimeout(() => { - window.location.reload(); - }, 1500); }} >
-- cgit v1.2.3 From 3542d65853072df17355f47a6abc3622375807ab Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 1 Aug 2024 17:10:17 +0700 Subject: update setRefresh cart --- src-migrate/modules/product-detail/components/AddToCart.tsx | 2 +- src-migrate/modules/product-promo/components/AddToCart.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index 644d5b90..0ac8229e 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -55,8 +55,8 @@ const AddToCart = ({ isNaN(quantity) || typeof auth !== 'object' ) return; - setAddCartAlert(true); setRefreshCart(true); + setAddCartAlert(true); toast.promise( upsertUserCart({ userId: auth.id, diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx index aae5cfc0..f066a4c8 100644 --- a/src-migrate/modules/product-promo/components/AddToCart.tsx +++ b/src-migrate/modules/product-promo/components/AddToCart.tsx @@ -58,8 +58,8 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => { qtyAppend: true }) setStatus('idle') - setAddCartAlert(true); setRefreshCart(true); + setAddCartAlert(true); toast({ title: 'Tambah ke keranjang', description: 'Berhasil menambahkan barang ke keranjang belanja', -- cgit v1.2.3 From f86b2adc680a9c6fa0ac92c84bf6d14e2f866d9a Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 2 Aug 2024 14:48:51 +0700 Subject: update popup cart --- .../product-detail/components/AddToCart.tsx | 79 ++++++++++++++++++++-- .../product-detail/components/PriceAction.tsx | 2 + .../product-detail/components/ProductDetail.tsx | 2 +- .../modules/product-promo/components/AddToCart.tsx | 61 ++++++++++++++++- .../modules/product-promo/components/Card.tsx | 10 +-- .../modules/product-promo/components/Modal.tsx | 8 ++- .../product-promo/components/ModalContent.tsx | 8 ++- .../modules/product-promo/components/Section.tsx | 8 ++- src-migrate/modules/promo/components/PromoList.tsx | 4 +- src-migrate/types/promotion.ts | 2 + 10 files changed, 159 insertions(+), 25 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index 097db98a..320b7234 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -1,19 +1,28 @@ -import { Button, useToast } from '@chakra-ui/react' +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import { Button, Link, useToast } from '@chakra-ui/react' +import product from 'next-seo/lib/jsonld/product' import { useRouter } from 'next/router' - +import { useState } from 'react' +import Image from '~/components/ui/image' import { getAuth } from '~/libs/auth' import { upsertUserCart } from '~/services/cart' - +import LazyLoad from 'react-lazy-load'; +import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar'; +import { IProductDetail } from '~/types/product'; +import ImageNext from 'next/image'; +import { useProductCartContext } from '@/contexts/ProductCartContext' type Props = { variantId: number | null, quantity?: number; source?: 'buy' | 'add_to_cart'; + products : IProductDetail } const AddToCart = ({ variantId, quantity = 1, - source = 'add_to_cart' + source = 'add_to_cart', + products }: Props) => { const auth = getAuth() const router = useRouter() @@ -22,6 +31,18 @@ const AddToCart = ({ isClosable: true }) + const [product, setProducts] = useState(products); + + const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = + useProductCartContext() + + const productSimilarQuery = [ + product?.name, + `fq=-product_id_i:${product.id}`, + `fq=-manufacture_id_i:${product.manufacture?.id || 0}`, + ].join('&'); + const [addCartAlert, setAddCartAlert] = useState(false); + const handleClick = async () => { if (typeof auth !== 'object') { const currentUrl = encodeURIComponent(router.asPath) @@ -35,6 +56,9 @@ const AddToCart = ({ typeof auth !== 'object' ) return; + setRefreshCart(true); + setAddCartAlert(true); + toast.promise( upsertUserCart({ userId: auth.id, @@ -69,9 +93,50 @@ const AddToCart = ({ } return ( - +
+ + { + setAddCartAlert(false); + }} + > +
+
+ +
+
+ {product.name} +
+
+ + Lihat Keranjang + +
+
+
+
+ Kamu Mungkin Juga Suka +
+ + + +
+
+
) } diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx index 81271f6e..9021264e 100644 --- a/src-migrate/modules/product-detail/components/PriceAction.tsx +++ b/src-migrate/modules/product-detail/components/PriceAction.tsx @@ -97,12 +97,14 @@ const PriceAction = ({ product }: Props) => { className={style['quantity-input']} /> {!isApproval && ( diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index fad35a7d..e4555913 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -129,7 +129,7 @@ const ProductDetail = ({ product }: Props) => { )}
- {!!activeVariantId && !isApproval && } + {!!activeVariantId && !isApproval && }

diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx index 87017c14..10904f90 100644 --- a/src-migrate/modules/product-promo/components/AddToCart.tsx +++ b/src-migrate/modules/product-promo/components/AddToCart.tsx @@ -9,19 +9,34 @@ import { IPromotion } from '~/types/promotion' import DesktopView from '../../../../src/core/components/views/DesktopView'; import MobileView from '../../../../src/core/components/views/MobileView'; - +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import ImageNext from 'next/image'; +import Link from 'next/link' +import LazyLoad from 'react-lazy-load' +import ProductSimilar from '../../../../src/lib/product/components/ProductSimilar'; +import { IProductDetail } from '~/types/product'; +import { useProductCartContext } from '@/contexts/ProductCartContext' type Props = { promotion: IPromotion + product: IProductDetail } type Status = 'idle' | 'loading' | 'success' -const ProductPromoAddToCart = ({ promotion }: Props) => { +const ProductPromoAddToCart = ({product, promotion }: Props) => { const auth = getAuth() const toast = useToast() const router = useRouter() const [status, setStatus] = useState('idle') + const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = + useProductCartContext() + + const productSimilarQuery = [ + promotion?.name, + `fq=-product_id_i:${promotion.products[0].product_id}`, + ].join('&'); + const [addCartAlert, setAddCartAlert] = useState(false); const handleButton = async () => { if (typeof auth !== 'object') { @@ -42,7 +57,8 @@ const ProductPromoAddToCart = ({ promotion }: Props) => { qtyAppend: true }) setStatus('idle') - + setRefreshCart(true); + setAddCartAlert(true); toast({ title: 'Tambah ke keranjang', description: 'Berhasil menambahkan barang ke keranjang belanja', @@ -92,6 +108,45 @@ const ProductPromoAddToCart = ({ promotion }: Props) => { {status === 'success' && Berhasil} {status !== 'success' && Keranjang} + { + setAddCartAlert(false); + }} + > +
+
+ +
+
+ {product.name} +
+
+ + Lihat Keranjang + +
+
+
+
+ Kamu Mungkin Juga Suka +
+ + + +
+

) diff --git a/src-migrate/modules/product-promo/components/Card.tsx b/src-migrate/modules/product-promo/components/Card.tsx index 728d23ca..5c323276 100644 --- a/src-migrate/modules/product-promo/components/Card.tsx +++ b/src-migrate/modules/product-promo/components/Card.tsx @@ -15,16 +15,16 @@ import clsxm from '~/libs/clsxm' import ProductPromoItem from './Item' import ProductPromoAddToCart from "./AddToCart" import ProductPromoCardCountdown from "./CardCountdown" - +import { IProductDetail } from '~/types/product'; import MobileView from '../../../../src/core/components/views/MobileView'; import DesktopView from '../../../../src/core/components/views/DesktopView'; type Props = { promotion: IPromotion - + product: IProductDetail } -const ProductPromoCard = ({ promotion}: Props) => { +const ProductPromoCard = ({product, promotion}: Props) => { const [products, setProducts] = useState([]) const [freeProducts, setFreeProducts] = useState([]) const [error, setError] = useState(null) @@ -132,7 +132,7 @@ const ProductPromoCard = ({ promotion}: Props) => {
- +
@@ -189,7 +189,7 @@ const ProductPromoCard = ({ promotion}: Props) => {
- +
diff --git a/src-migrate/modules/product-promo/components/Modal.tsx b/src-migrate/modules/product-promo/components/Modal.tsx index 0de672c2..1722b9df 100644 --- a/src-migrate/modules/product-promo/components/Modal.tsx +++ b/src-migrate/modules/product-promo/components/Modal.tsx @@ -3,8 +3,12 @@ import { Modal } from "~/components/ui/modal" import { useModalStore } from '../stores/useModalStore' import ProductPromoCategoryTab from './CategoryTab' import ProductPromoModalContent from './ModalContent' +import { IProductDetail } from '~/types/product'; -const ProductPromoModal = () => { +type Props = { + product: IProductDetail +} +const ProductPromoModal = ({product}:Props) => { const { active, closeModal } = useModalStore() return ( @@ -17,7 +21,7 @@ const ProductPromoModal = () => {
- + ) } diff --git a/src-migrate/modules/product-promo/components/ModalContent.tsx b/src-migrate/modules/product-promo/components/ModalContent.tsx index ab5129f8..256ef61a 100644 --- a/src-migrate/modules/product-promo/components/ModalContent.tsx +++ b/src-migrate/modules/product-promo/components/ModalContent.tsx @@ -6,7 +6,11 @@ import { getVariantPromoByCategory } from "~/services/productVariant" import { useModalStore } from "../stores/useModalStore" import ProductPromoCard from "./Card" -const ProductPromoModalContent = () => { +import { IProductDetail } from '~/types/product'; +type Props = { + product: IProductDetail +} +const ProductPromoModalContent = ({product}:Props) => { const { activeTab, variantId } = useModalStore() const promotionsQuery = useQuery( @@ -24,7 +28,7 @@ const ProductPromoModalContent = () => {
{promotions?.data.map((promo) => ( - + ))} {promotions?.data.length === 0 && (
Belum ada promo pada kategori ini
diff --git a/src-migrate/modules/product-promo/components/Section.tsx b/src-migrate/modules/product-promo/components/Section.tsx index 4e8a7dd5..2c94c2bb 100644 --- a/src-migrate/modules/product-promo/components/Section.tsx +++ b/src-migrate/modules/product-promo/components/Section.tsx @@ -9,12 +9,14 @@ import { IPromotion } from '~/types/promotion' import { useModalStore } from "../stores/useModalStore" import ProductPromoCard from './Card' import ProductPromoModal from "./Modal" +import { IProductDetail } from '~/types/product'; type Props = { productId: number; + product: IProductDetail; } -const ProductPromoSection = ({ productId }: Props) => { +const ProductPromoSection = ({ product, productId }: Props) => { const promotionsQuery = useQuery({ queryKey: [`promotions.highlight`, productId], queryFn: async () => await fetch(`/api/product-variant/${productId}/promotion/highlight`).then((res) => res.json()) as { data: IPromotion[] } @@ -30,7 +32,7 @@ const ProductPromoSection = ({ productId }: Props) => { height='450px' duration='700ms' > - + {promotions?.data && promotions?.data.length > 0 && (
@@ -50,7 +52,7 @@ const ProductPromoSection = ({ productId }: Props) => { > {promotions?.data.map((promotion) => (
- +
))} diff --git a/src-migrate/modules/promo/components/PromoList.tsx b/src-migrate/modules/promo/components/PromoList.tsx index 42725034..4d0db3c2 100644 --- a/src-migrate/modules/promo/components/PromoList.tsx +++ b/src-migrate/modules/promo/components/PromoList.tsx @@ -114,7 +114,7 @@ const PromoList: React.FC = ({ selectedPromo }) => { {promoData?.map((promotion: IPromotion) => (
- +
))} @@ -122,7 +122,7 @@ const PromoList: React.FC = ({ selectedPromo }) => { )} {isMobile && (promoData?.map((promotion: IPromotion) => (
- +
)))} diff --git a/src-migrate/types/promotion.ts b/src-migrate/types/promotion.ts index 85190aad..10f6d8b0 100644 --- a/src-migrate/types/promotion.ts +++ b/src-migrate/types/promotion.ts @@ -10,10 +10,12 @@ export interface IPromotion { limit_user: number; limit_trx: number; price: number; + image: string; total_qty: number; products: { product_id: number; qty: number; + name: string; }[]; free_products: { product_id: number; -- cgit v1.2.3 From d57ca7be5e2de9c48f4229b20a49a94bf05e88d1 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 2 Aug 2024 14:55:16 +0700 Subject: update cart pop up --- src/lib/cart/components/Cartheader.jsx | 259 ++++++++++++++++++++++++++++++++- 1 file changed, 257 insertions(+), 2 deletions(-) diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index 19f79bc9..e3a5cc1f 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -4,7 +4,12 @@ import useAuth from '@/core/hooks/useAuth' import { useRouter } from 'next/router' import odooApi from '@/core/api/odooApi' import { useProductCartContext } from '@/contexts/ProductCartContext' - +import currencyFormat from '@/core/utils/currencyFormat' +import Image from '@/core/components/elements/Image/Image' +import { createSlug } from '@/core/utils/slug' +import whatsappUrl from '@/core/utils/whatsappUrl' +import { AnimatePresence, motion } from 'framer-motion' +import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css' const { ShoppingCartIcon, PhotoIcon } = require('@heroicons/react/24/outline') const { default: Link } = require('next/link') @@ -19,7 +24,7 @@ const Cardheader = (cartCount) => { useProductCartContext() const [isHovered, setIsHovered] = useState(false) - + const [isTop, setIsTop] = useState(true) const products = useMemo(() => { return productCart?.products || [] }, [productCart]) @@ -77,6 +82,16 @@ const Cardheader = (cartCount) => { setCountCart(cartCount.cartCount) }, [cartCount]) + useEffect(() => { + const handleScroll = () => { + setIsTop(window.scrollY === 0) + } + window.addEventListener('scroll', handleScroll) + return () => { + window.removeEventListener('scroll', handleScroll) + } + }, []) + const handleCheckout = async () => { SetButtonTerapkan(true) let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`) @@ -109,6 +124,246 @@ const Cardheader = (cartCount) => {
+ + {isHovered && ( + <> + + + +
+
Keranjang Belanja
+ + Lihat Semua + +
+
+
+ {!auth && ( +
+

+ Silahkan{' '} + + Login + {' '} + Untuk Melihat Daftar Keranjang Belanja Anda +

+
+ )} + {isLoading && + itemLoading.map((item) => ( +
+
+
+ +
+
+
+
+
+
+
+
+ ))} + {auth && products.length === 0 && !isLoading && ( +
+

+ Tidak Ada Produk di Keranjang Belanja Anda +

+
+ )} + {auth && products.length > 0 && !isLoading && ( + <> +
    + {products && + products?.map((product, index) => ( + <> +
  • +
    +
    + {product.cartType === 'promotion' && ( + {product.name} + )} + {product.cartType === 'product' && ( + + {product?.name} + + )} +
    +
    + {product.cartType === 'promotion' && ( +

    + {product.name} +

    + )} + {product.cartType === 'product' && ( + + {' '} +

    + {product.parent.name} +

    + + )} + {product?.hasFlashsale && ( +
    +
    + {product?.price?.discountPercentage}% +
    +
    + {currencyFormat(product?.price?.price)} +
    +
    + )} + +
    +
    + {product?.price?.priceDiscount > 0 ? ( + currencyFormat(product?.price?.priceDiscount) + ) : ( + + + Call For Price + + + )} +
    +
    +
    +
    +
    + {product.products?.map((product) => +
    + + {product?.image && {product.name}} + + +
    + + {product.displayName} + + +
    +
    + {/*
    {product.code}
    */} +
    + Berat Barang: + {product.packageWeight} Kg +
    +
    +
    +
    + +
    + )} + {product.freeProducts?.map((product) => +
    + + {product?.image && {product.name}} + + +
    + + {product.displayName} + + +
    +
    + {/*
    {product.code}
    */} +
    + Berat Barang: + {product.packageWeight} Kg +
    +
    +
    +
    + +
    + )} +
    +
  • + + ))} +
+
+ + )} +
+ {auth && products.length > 0 && !isLoading && ( + <> +
+ Subtotal Sebelum PPN : + {currencyFormat(subTotal)} +
+
+ +
+ + )} +
+
+ + )} +
) } -- cgit v1.2.3 From cf8a2c77f5a76a3b1dc10db6de56a4958de7b068 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 3 Aug 2024 08:41:51 +0700 Subject: update error code --- src/lib/cart/components/Cartheader.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index f76634ce..c7a8f0b8 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -1,15 +1,12 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { getCartApi } from '../api/CartApi' import currencyFormat from '@/core/utils/currencyFormat' -import Image from '@/core/components/elements/Image/Image' import { createSlug } from '@/core/utils/slug' import useAuth from '@/core/hooks/useAuth' import { useRouter } from 'next/router' import odooApi from '@/core/api/odooApi' import { useProductCartContext } from '@/contexts/ProductCartContext' -import currencyFormat from '@/core/utils/currencyFormat' import Image from '@/core/components/elements/Image/Image' -import { createSlug } from '@/core/utils/slug' import whatsappUrl from '@/core/utils/whatsappUrl' import { AnimatePresence, motion } from 'framer-motion' import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css' -- cgit v1.2.3 From 70ec90799154dab2da475e840d8277d85648483b Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 3 Aug 2024 13:41:39 +0700 Subject: update error code --- src/lib/cart/components/Cartheader.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index f76634ce..6915d4f6 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -7,9 +7,6 @@ import useAuth from '@/core/hooks/useAuth' import { useRouter } from 'next/router' import odooApi from '@/core/api/odooApi' import { useProductCartContext } from '@/contexts/ProductCartContext' -import currencyFormat from '@/core/utils/currencyFormat' -import Image from '@/core/components/elements/Image/Image' -import { createSlug } from '@/core/utils/slug' import whatsappUrl from '@/core/utils/whatsappUrl' import { AnimatePresence, motion } from 'framer-motion' import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css' -- cgit v1.2.3 From aaac6b72dddf8ef8460941797a1f6d88f289f726 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 5 Aug 2024 15:59:30 +0700 Subject: update category management --- src/lib/category/api/popularProduct.js | 36 +++++++++++ src/lib/category/components/Category.jsx | 35 ++-------- src/lib/category/components/PopularBrand.jsx | 96 ++++++++++++++++++++++++++++ src/lib/home/components/CategoryDynamic.jsx | 3 +- 4 files changed, 140 insertions(+), 30 deletions(-) create mode 100644 src/lib/category/api/popularProduct.js create mode 100644 src/lib/category/components/PopularBrand.jsx diff --git a/src/lib/category/api/popularProduct.js b/src/lib/category/api/popularProduct.js new file mode 100644 index 00000000..2298f6fa --- /dev/null +++ b/src/lib/category/api/popularProduct.js @@ -0,0 +1,36 @@ + +export const fetchPromoItemsSolr = async (category_id_ids) => { + let sort ='sort=qty_sold_f desc'; + try { + const queryParams = new URLSearchParams({ q: category_id_ids }); + // const response = await fetch(`/solr/product/select?${queryParams.toString()}&rows=2000&fl=manufacture_name_s&${sort}`); + console.log("queryParams",queryParams) + + // const response = await fetch(`/solr/product/select?${queryParams.toString()}`); + const response = await fetch(`/solr/promotion_program_lines/select?${queryParams.toString()}&rows=10&start=0&${sort}`); + console.log("response",response) + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + const promotions = await map(data.response.docs); + return promotions; + } 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, + name: promotion.display_name_s, + manufacture_name: promotion.manufacture_name_s, + manufacture_id: promotion.manufacture_id_i, + }; + result.push(data); + } + return result; + }; \ No newline at end of file diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx index c147a3b3..1f3d7a51 100644 --- a/src/lib/category/components/Category.jsx +++ b/src/lib/category/components/Category.jsx @@ -5,6 +5,7 @@ import { createSlug } from '@/core/utils/slug' import { ChevronRightIcon } from '@heroicons/react/24/outline' import Image from 'next/image' import { useEffect, useState } from 'react' +import PopularBrand from './PopularBrand' const Category = () => { const [categories, setCategories] = useState([]) @@ -30,6 +31,7 @@ const Category = () => { } loadCategories() }, []) + console.log("categories",categories) return ( @@ -38,8 +40,11 @@ const Category = () => {
+
+ +
{category.name}
@@ -80,33 +85,7 @@ const Category = () => { ))}
-
-
- {category.childs.map((brand, index) => ( - (index < 8 ) && ( -
- - - -
- ) - ))} -
- {category.childs.length > 8 && ( -
- -

Lihat Semua Brand

- - -
- )} -
+
diff --git a/src/lib/category/components/PopularBrand.jsx b/src/lib/category/components/PopularBrand.jsx new file mode 100644 index 00000000..32623f91 --- /dev/null +++ b/src/lib/category/components/PopularBrand.jsx @@ -0,0 +1,96 @@ +import odooApi from '@/core/api/odooApi' +import {React } from 'react' +import axios from 'axios'; +import { useQuery } from 'react-query' +import Link from '@/core/components/elements/Link/Link' +import { createSlug } from '@/core/utils/slug' +import Image from 'next/image' +import { ChevronRightIcon } from '@heroicons/react/24/outline' +import useProductSearch from '../../../lib/product/hooks/useProductSearch'; +import { SolrResponse } from "~/types/solr"; +import {fetchPromoItemsSolr} from '../api/popularProduct' +const SOLR_HOST = process.env.SOLR_HOST + +const PopularBrand = ({ category }) => { + + const queryFinal = { + fq: `category_id_ids:(${category.categoryDataIds.join(' OR ')})`, + fl: 'manufacture_name_s,qty_sold_f', + sort: 'qty_sold_f desc', + rows: '2000' + }; + + // Konversi objek queryFinal menjadi string query + // const queryString = new URLSearchParams(queryFinal).toString(); + + async function fetchTopBrands() { + try { + // const items = await fetchPromoItemsSolr(`category_id_ids:(${category.categoryDataIds.join(' OR ')})`); + const items = await fetchPromoItemsSolr(`type_value_s:discount_loading`); + + console.log("queryFinal", queryFinal); + console.log("items", items); + + // Fungsi untuk deduplikasi dan mengambil 12 nama brand teratas + function getTop12UniqueBrands(products) { + const brandSet = new Set(); + const topBrands = []; + + for (const product of products) { + if (!brandSet.has(product.manufacture_name_s)) { + brandSet.add(product.manufacture_name_s); + topBrands.push(product.manufacture_name_s); + } + if (topBrands.length === 12) break; + } + + return topBrands; + } + + // Menggunakan hasil pencarian produk + const products = items; + const top12UniqueBrands = getTop12UniqueBrands(products); + + console.log('top12UniqueBrands',top12UniqueBrands); + return top12UniqueBrands; + } catch (error) { + console.error("Error fetching data from Solr", error); + throw error; + } + } + + fetchTopBrands(); + + + return ( +
+
+ {category.childs.map((brand, index) => ( + (index < 8 ) && ( +
+ + + +
+ ) + ))} +
+ {category.childs.length > 8 && ( +
+ +

Lihat Semua Brand

+ + +
+ )} +
+ ) +} + +export default PopularBrand diff --git a/src/lib/home/components/CategoryDynamic.jsx b/src/lib/home/components/CategoryDynamic.jsx index f2d1a16f..0cc43d91 100644 --- a/src/lib/home/components/CategoryDynamic.jsx +++ b/src/lib/home/components/CategoryDynamic.jsx @@ -33,9 +33,8 @@ const CategoryDynamic = () => { }; fetchCategoryData(); - }, [categoryManagement, categoryData]); + }, [categoryManagement.isLoading]); - return (
{categoryManagement && categoryManagement.data?.map((category) => { -- cgit v1.2.3 From 54fca7062ee0963d6ea6a22a82fba7fa3fa516e5 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 5 Aug 2024 17:07:35 +0700 Subject: update category management --- src/lib/category/api/popularProduct.js | 7 +- src/lib/category/components/Category.jsx | 2 +- src/lib/category/components/PopularBrand.jsx | 105 ++++++++++++--------------- 3 files changed, 48 insertions(+), 66 deletions(-) diff --git a/src/lib/category/api/popularProduct.js b/src/lib/category/api/popularProduct.js index 2298f6fa..e17e0ae5 100644 --- a/src/lib/category/api/popularProduct.js +++ b/src/lib/category/api/popularProduct.js @@ -3,12 +3,7 @@ export const fetchPromoItemsSolr = async (category_id_ids) => { let sort ='sort=qty_sold_f desc'; try { const queryParams = new URLSearchParams({ q: category_id_ids }); - // const response = await fetch(`/solr/product/select?${queryParams.toString()}&rows=2000&fl=manufacture_name_s&${sort}`); - console.log("queryParams",queryParams) - - // const response = await fetch(`/solr/product/select?${queryParams.toString()}`); - const response = await fetch(`/solr/promotion_program_lines/select?${queryParams.toString()}&rows=10&start=0&${sort}`); - console.log("response",response) + const response = await fetch(`/solr/product/select?${queryParams.toString()}&rows=2000&fl=manufacture_name_s,manufacture_id_i,id,display_name_s&${sort}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx index 1f3d7a51..ff958378 100644 --- a/src/lib/category/components/Category.jsx +++ b/src/lib/category/components/Category.jsx @@ -31,7 +31,7 @@ const Category = () => { } loadCategories() }, []) - console.log("categories",categories) + // console.log("categories",categories) return ( diff --git a/src/lib/category/components/PopularBrand.jsx b/src/lib/category/components/PopularBrand.jsx index 32623f91..dca731e8 100644 --- a/src/lib/category/components/PopularBrand.jsx +++ b/src/lib/category/components/PopularBrand.jsx @@ -1,5 +1,5 @@ import odooApi from '@/core/api/odooApi' -import {React } from 'react' +import React, { useEffect, useState } from 'react' import axios from 'axios'; import { useQuery } from 'react-query' import Link from '@/core/components/elements/Link/Link' @@ -8,89 +8,76 @@ import Image from 'next/image' import { ChevronRightIcon } from '@heroicons/react/24/outline' import useProductSearch from '../../../lib/product/hooks/useProductSearch'; import { SolrResponse } from "~/types/solr"; -import {fetchPromoItemsSolr} from '../api/popularProduct' +import { fetchPromoItemsSolr } from '../api/popularProduct' + const SOLR_HOST = process.env.SOLR_HOST const PopularBrand = ({ category }) => { + const [topBrands, setTopBrands] = useState([]); - const queryFinal = { - fq: `category_id_ids:(${category.categoryDataIds.join(' OR ')})`, - fl: 'manufacture_name_s,qty_sold_f', - sort: 'qty_sold_f desc', - rows: '2000' - }; - - // Konversi objek queryFinal menjadi string query - // const queryString = new URLSearchParams(queryFinal).toString(); - - async function fetchTopBrands() { + const fetchTopBrands = async () => { try { - // const items = await fetchPromoItemsSolr(`category_id_ids:(${category.categoryDataIds.join(' OR ')})`); - const items = await fetchPromoItemsSolr(`type_value_s:discount_loading`); - - console.log("queryFinal", queryFinal); - console.log("items", items); - + const items = await fetchPromoItemsSolr(`category_id_ids:(${category.categoryDataIds.join(' OR ')})`); + // console.log("id",items) // Fungsi untuk deduplikasi dan mengambil 12 nama brand teratas - function getTop12UniqueBrands(products) { + const getTop12UniqueBrands = (prod) => { const brandSet = new Set(); const topBrands = []; - - for (const product of products) { - if (!brandSet.has(product.manufacture_name_s)) { - brandSet.add(product.manufacture_name_s); - topBrands.push(product.manufacture_name_s); + + for (const product of prod) { + if (!brandSet.has(product.manufacture_name)) { + brandSet.add(product.manufacture_name); + topBrands.push({ name: product.manufacture_name, id: product.manufacture_id }); + }else{ } - if (topBrands.length === 12) break; + if (topBrands.length === 18) break; } - return topBrands; } - + // Menggunakan hasil pencarian produk const products = items; const top12UniqueBrands = getTop12UniqueBrands(products); - - console.log('top12UniqueBrands',top12UniqueBrands); - return top12UniqueBrands; + + // console.log('top12UniqueBrands', top12UniqueBrands); + setTopBrands(top12UniqueBrands); } catch (error) { console.error("Error fetching data from Solr", error); throw error; } } - - fetchTopBrands(); + useEffect(() => { + fetchTopBrands(); + }, [category]); - return ( -
-
- {category.childs.map((brand, index) => ( - (index < 8 ) && ( -
- - - -
- ) - ))} -
- {category.childs.length > 8 && ( -
- +
+ {topBrands.map((brand, index) => ( +
+ + {`${brand.name}`} + +
+ ))} +
+ {/* {topBrands.length > 8 && ( +
+ + >

Lihat Semua Brand

- -
- )} -
- ) + +
+ )} */} +
+ ) } -export default PopularBrand +export default PopularBrand; -- cgit v1.2.3 From 0f4938c0f9ce12d60bac2eb012a98b818fcd5110 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 6 Aug 2024 08:59:31 +0700 Subject: update refresh cart --- src-migrate/modules/product-detail/components/AddToCart.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index 6c9aedf8..c73d7b36 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -34,8 +34,7 @@ const AddToCart = ({ const [product, setProducts] = useState(products); - const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = - useProductCartContext() + const {setRefreshCart} = useProductCartContext() const productSimilarQuery = [ product?.name, @@ -50,16 +49,17 @@ const AddToCart = ({ router.push(`/login?next=${currentUrl}`) return; } - + if ( !variantId || isNaN(quantity) || typeof auth !== 'object' ) return; - + setRefreshCart(true); + // console.log('Refresh cart triggered'); setAddCartAlert(true); - + toast.promise( upsertUserCart({ userId: auth.id, @@ -78,7 +78,7 @@ const AddToCart = ({ ) - + if (source === 'buy') { router.push('/shop/checkout?source=buy') } -- cgit v1.2.3 From 1ce47f63e967d32d8e6026c0f2e8da931d23fd4c Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 6 Aug 2024 10:21:43 +0700 Subject: update add to cart pop up --- .../product-detail/components/AddToCart.tsx | 59 +++++++++++++++++++++- .../modules/product-promo/components/AddToCart.tsx | 56 +++++++++++++++++++- 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index c73d7b36..bebc793f 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -1,4 +1,5 @@ import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import style from '../styles/price-action.module.css'; import { Button, Link, useToast } from '@chakra-ui/react' import product from 'next-seo/lib/jsonld/product' import { useRouter } from 'next/router' @@ -11,6 +12,9 @@ import ProductSimilar from '../../../../src/lib/product/components/ProductSimila import { IProductDetail } from '~/types/product'; import ImageNext from 'next/image'; import { useProductCartContext } from '@/contexts/ProductCartContext' +import { createSlug } from '~/libs/slug' +import formatCurrency from '~/libs/formatCurrency' +import { useProductDetail } from '../stores/useProductDetail'; type Props = { variantId: number | null, @@ -32,6 +36,10 @@ const AddToCart = ({ isClosable: true }) + const { + askAdminUrl, + } = useProductDetail(); + const [product, setProducts] = useState(products); const {setRefreshCart} = useProductCartContext() @@ -118,8 +126,55 @@ const AddToCart = ({ height={80} />
-
- {product.name} +
+ {!!product.manufacture.name ? ( + + {product.manufacture.name} + + ) : '-'} +

+ {product.name} +

+

+ {product.code} +

+ {!!product.lowest_price && product.lowest_price.price > 0 && ( + <> +
+ {product.lowest_price.discount_percentage > 0 && ( + <> +
+ {Math.floor(product.lowest_price.discount_percentage)}% +
+
+ Rp {formatCurrency(product.lowest_price.price || 0)} +
+ + )} +
+ Rp {formatCurrency(product.lowest_price.price_discount || 0)} +
+
+ + )} + + {!!product.lowest_price && product.lowest_price.price === 0 && ( + + Hubungi kami untuk dapatkan harga terbaik,{' '} + + klik disini + + + )}
{ + const auth = getAuth() const toast = useToast() const router = useRouter() + const {askAdminUrl} = useProductDetail(); const [status, setStatus] = useState('idle') const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = useProductCartContext() @@ -126,8 +131,55 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => { height={80} />
-
- {product.name} +
+ {!!product.manufacture.name ? ( + + {product.manufacture.name} + + ) : '-'} +

+ {product.name} +

+

+ {product.code} +

+ {!!product.lowest_price && product.lowest_price.price > 0 && ( + <> +
+ {product.lowest_price.discount_percentage > 0 && ( + <> +
+ {Math.floor(product.lowest_price.discount_percentage)}% +
+
+ Rp {formatCurrency(product.lowest_price.price || 0)} +
+ + )} +
+ Rp {formatCurrency(product.lowest_price.price_discount || 0)} +
+
+ + )} + + {!!product.lowest_price && product.lowest_price.price === 0 && ( + + Hubungi kami untuk dapatkan harga terbaik,{' '} + + klik disini + + + )}
Date: Tue, 6 Aug 2024 14:32:41 +0700 Subject: add quotation pop up --- src/contexts/ProductQuotationContext.js | 17 ++ .../components/elements/Navbar/NavbarDesktop.jsx | 58 +++++-- src/lib/quotation/components/Quotationheader.jsx | 189 +++++++++++++++++++++ 3 files changed, 249 insertions(+), 15 deletions(-) create mode 100644 src/contexts/ProductQuotationContext.js create mode 100644 src/lib/quotation/components/Quotationheader.jsx diff --git a/src/contexts/ProductQuotationContext.js b/src/contexts/ProductQuotationContext.js new file mode 100644 index 00000000..f9e17830 --- /dev/null +++ b/src/contexts/ProductQuotationContext.js @@ -0,0 +1,17 @@ +import React, { createContext, useContext, useState } from 'react'; + +const ProductQuotationContext = createContext(); + +export const useProductQuotationContext = () => useContext(ProductQuotationContext); + +export const ProductQuotationProvider = ({ children }) => { + const [productQuotation, setProductQuotation] = useState([]); + const [refreshQuotation, setRefreshQuotation] = useState(false); + const [isLoading, setIsloading] = useState(false); + + return ( + + {children} + + ); +}; diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx index 7d9e4264..49c4cd6e 100644 --- a/src/core/components/elements/Navbar/NavbarDesktop.jsx +++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx @@ -5,7 +5,9 @@ import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; import IndoteknikLogo from '@/images/logo.png'; import Cardheader from '@/lib/cart/components/Cartheader'; +import Quotationheader from '@/lib/quotation/components/QuotationHeader' import Category from '@/lib/category/components/Category'; +import { useProductQuotationContext } from '@/contexts/ProductQuotationContext' import { ChevronDownIcon, DocumentCheckIcon, @@ -28,6 +30,7 @@ import { useDisclosure, } from '@chakra-ui/react'; import style from "./style/NavbarDesktop.module.css"; +import useTransactions from '@/lib/transaction/hooks/useTransactions'; const Search = dynamic(() => import('./Search'), { ssr: false }); const TopBanner = dynamic(() => import('./TopBanner'), { ssr: false }); @@ -37,6 +40,8 @@ const NavbarDesktop = () => { const auth = useAuth(); const [cartCount, setCartCount] = useState(0); + const [quotationCount, setQuotationCount] = useState(0); + // const { setProductQuotation, refreshQuotation, setRefreshQuotation, isLoading, setIsloading } = useProductQuotationContext() const [templateWA, setTemplateWA] = useState(null); const [payloadWA, setPayloadWa] = useState(null); @@ -47,6 +52,16 @@ const NavbarDesktop = () => { const { product } = useProductContext(); const { isOpen, onOpen, onClose } = useDisclosure(); + const query = { + context: 'quotation', + site: + (auth?.webRole === null && auth?.site ? auth.site : null), + }; + + const { transactions } = useTransactions({query}); + const pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft'); + + useEffect(() => { if (router.pathname === '/shop/product/[slug]') { setPayloadWa({ @@ -55,11 +70,11 @@ const NavbarDesktop = () => { url: createSlug('/shop/product/', product?.name, product?.id, true), }); setTemplateWA('product'); - + setUrlPath(router.asPath); } }, [product, router]); - + useEffect(() => { const handleCartChange = () => { const cart = async () => { @@ -69,14 +84,36 @@ const NavbarDesktop = () => { cart(); }; handleCartChange(); - + window.addEventListener('localStorageChange', handleCartChange); - + return () => { window.removeEventListener('localStorageChange', handleCartChange); }; }, []); + + // useEffect(() => { + // setProductQuotation(pendingTransactions) + // }, [transactions, ]) + // console.log("Pending Transactions", pendingTransactions); + // console.log("pendingTransactions.length", pendingTransactions.length); + + useEffect(() => { + const handleQuotationChange = () => { + const quotation = async () => { + setQuotationCount(pendingTransactions?.length); + }; + quotation(); + }; + handleQuotationChange(); + window.addEventListener('localStorageChange', handleQuotationChange); + + return () => { + window.removeEventListener('localStorageChange', handleQuotationChange); + }; + }, []); + console.log("quotationCount",quotationCount) return ( @@ -139,17 +176,8 @@ const NavbarDesktop = () => {
- - - Daftar -
- Quotation - + + diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx new file mode 100644 index 00000000..141b731e --- /dev/null +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -0,0 +1,189 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { getQuotationApi } from '../api/QuotationApi'; +import currencyFormat from '@/core/utils/currencyFormat'; +import { createSlug } from '@/core/utils/slug'; +import useAuth from '@/core/hooks/useAuth'; +import { useRouter } from 'next/router'; +import odooApi from '@/core/api/odooApi'; +import { useProductQuotationContext } from '@/contexts/ProductQuotationContext'; +import Image from '@/core/components/elements/Image/Image'; +import whatsappUrl from '@/core/utils/whatsappUrl'; +import { AnimatePresence, motion } from 'framer-motion'; +import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css'; +import useTransactions from '../../transaction/hooks/useTransactions'; +const { DocumentCheckIcon, PhotoIcon } = require('@heroicons/react/24/outline'); +const { default: Link } = require('next/link'); + +const Quotationheader = (quotationCount) => { + const auth = useAuth(); + const query = { + context: 'quotation', + site: auth?.webRole === null && auth?.site ? auth.site : null, + }; + + const router = useRouter(); + const [subTotal, setSubTotal] = useState(null); + const [buttonLoading, SetButtonTerapkan] = useState(false); + const itemLoading = [1, 2, 3]; + const [countQuotation, setCountQuotation] = useState(null); + const { productQuotation, setProductQuotation, refreshQuotation, setRefreshQuotation, isLoading, setIsloading } = + useProductQuotationContext(); + + const [isHovered, setIsHovered] = useState(false); + const [isTop, setIsTop] = useState(true); + const qotation = useMemo(() => { + return productQuotation || []; + }, [productQuotation]); + + const handleMouseEnter = () => { + setIsHovered(true); + getCart(); + }; + + const handleMouseLeave = () => { + setIsHovered(false); + }; + + const getCart = () => { + if (!productQuotation && auth) { + refreshCartf(); + } + }; + const refreshCartf = useCallback(async () => { + setIsloading(true); + let { transactions } = await useTransactions({ query }); + let pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft'); + setProductQuotation(pendingTransactions); + setCountQuotation(pendingTransactions.length); + setIsloading(false); + }, [setProductQuotation, setIsloading]); + + useEffect(() => { + if (refreshQuotation) { + refreshCartf(); + } + setRefreshQuotation(false); + }, [refreshQuotation, refreshCartf, setRefreshQuotation]); + + useEffect(() => { + setCountQuotation(quotationCount.cartCount); + }, [quotationCount]); + + useEffect(() => { + const handleScroll = () => { + setIsTop(window.scrollY === 0); + }; + window.addEventListener('scroll', handleScroll); + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); + + const handleCheckout = async () => { + SetButtonTerapkan(true); + let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`); + router.push('/shop/quotation'); + }; + + return ( +
+
+ +
0 && 'mr-2'}`}> + + {countQuotation > 0 && ( + + {countQuotation} + + )} +
+ + Daftar +
+ Quotation +
+ +
+ + {isHovered && ( + <> + + + +
+
Daftar Quotation
+ + Lihat Semua + +
+
+
+ {!auth && ( +
+

+ Silahkan{' '} + + Login + {' '} + Untuk Melihat Daftar Keranjang Belanja Anda +

+
+ )} + {isLoading && + itemLoading.map((item) => ( +
+
+
+ +
+
+
+
+
+
+
+
+ ))} + {auth && qotation.length === 0 && !isLoading && ( +
+

+ Tidak Ada Quotation +

+
+ )} +
+
+
+ + )} +
+
+ ); +}; + +export default Quotationheader; -- cgit v1.2.3 From f3aa76b1810b3bc8b25bd02c76b50384893fc453 Mon Sep 17 00:00:00 2001 From: trisusilo48 Date: Tue, 6 Aug 2024 15:12:56 +0700 Subject: voucher --- src/lib/checkout/api/getVoucher.js | 1 + src/lib/checkout/components/Checkout.jsx | 118 ++++++++++++++++++++++--------- 2 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/lib/checkout/api/getVoucher.js b/src/lib/checkout/api/getVoucher.js index 779cef43..ead4ffbe 100644 --- a/src/lib/checkout/api/getVoucher.js +++ b/src/lib/checkout/api/getVoucher.js @@ -3,6 +3,7 @@ import { getAuth } from '@/core/utils/auth' export const getVoucher = async (id, query) => { const queryParam = new URLSearchParams(query); + console.log('ini params string',queryParam.toString()) const url = `/api/v1/user/${id}/voucher?${queryParam.toString()}`; const dataVoucher = await odooApi('GET', url); return dataVoucher; diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 09a791ee..84f68dab 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -131,6 +131,7 @@ const Checkout = () => { setLoadingVoucher(true); let dataVoucher = await getVoucher(auth?.id, { source: query, + type: 'all,brand', }); SetListVoucher(dataVoucher); @@ -146,40 +147,71 @@ const Checkout = () => { }; const VoucherCode = async (code) => { - const source = 'code=' + code + '&source=' + query; // let dataVoucher = await findVoucher(code, auth.id, query); - let dataVoucher = await getVoucherNew(source); + let dataVoucher = await getVoucher(auth?.id, { + source: query, + code: code + }); if (dataVoucher.length <= 0) { SetFindVoucher(1); return; } let addNewLine = dataVoucher[0]; - let checkList = listVouchers?.findIndex( - (voucher) => voucher.code == addNewLine.code - ); - if (checkList >= 0) { - if (listVouchers[checkList].canApply) { - ToggleSwitch(code); - SetCodeVoucher(null); - } else { - SetSelisihHargaCode(listVouchers[checkList].differenceToApply); + console.log('addNewLine', addNewLine); + if (addNewLine.applyType != 'shipping') { + let checkList = listVouchers?.findIndex( + (voucher) => voucher.code == addNewLine.code + ); + if (checkList >= 0) { + if (listVouchers[checkList].canApply) { + ToggleSwitch(code); + SetCodeVoucher(null); + } else { + SetSelisihHargaCode(listVouchers[checkList].differenceToApply); + SetFindVoucher(2); + } + return; + } + if (cartCheckout?.subtotal < addNewLine.minPurchaseAmount) { + SetSelisihHargaCode( + currencyFormat(addNewLine.minPurchaseAmount - cartCheckout?.subtotal) + ); SetFindVoucher(2); + return; + } else { + SetFindVoucher(3); + SetButtonTerapkan(true); } - return; - } - if (cartCheckout?.subtotal < addNewLine.minPurchaseAmount) { - SetSelisihHargaCode( - currencyFormat(addNewLine.minPurchaseAmount - cartCheckout?.subtotal) - ); - SetFindVoucher(2); - return; + SetListVoucher((prevList) => [addNewLine, ...prevList]); + SetActiveVoucher(addNewLine.code); } else { - SetFindVoucher(3); - SetButtonTerapkan(true); + let checkList = listVoucherShippings?.findIndex( + (voucher) => voucher.code == addNewLine.code + ); + if (checkList >= 0) { + if (listVoucherShippings[checkList].canApply) { + ToggleSwitch(code); + SetCodeVoucher(null); + } else { + SetSelisihHargaCode(listVoucherShippings[checkList].differenceToApply); + SetFindVoucher(2); + } + return; + } + if (cartCheckout?.subtotal < addNewLine.minPurchaseAmount) { + SetSelisihHargaCode( + currencyFormat(addNewLine.minPurchaseAmount - cartCheckout?.subtotal) + ); + SetFindVoucher(2); + return; + } else { + SetFindVoucher(3); + SetButtonTerapkan(true); + } + SetListVoucherShipping((prevList) => [addNewLine, ...prevList]); + setActiveVoucherShipping(addNewLine.code); } - SetListVoucher((prevList) => [addNewLine, ...prevList]); - SetActiveVoucher(addNewLine.code); }; useEffect(() => { @@ -187,7 +219,7 @@ const Checkout = () => { }, [bottomPopup]); useEffect(() => { - voucher(); + // voucher(); const loadExpedisi = async () => { let dataExpedisi = await ExpedisiList(); dataExpedisi = dataExpedisi.map((expedisi) => ({ @@ -210,13 +242,24 @@ const Checkout = () => { }; }, []); - const hitungDiscountVoucher = (code) => { - let dataVoucherIndex = listVouchers.findIndex( - (voucher) => voucher.code == code - ); - let dataActiveVoucher = listVouchers[dataVoucherIndex]; - - let countDiscount = dataActiveVoucher.discountVoucher; + const hitungDiscountVoucher = (code, source) => { + let countDiscount = 0; + if(source === 'voucher'){ + let dataVoucherIndex = listVouchers.findIndex( + (voucher) => voucher.code == code + ); + let dataActiveVoucher = listVouchers[dataVoucherIndex]; + + countDiscount = dataActiveVoucher.discountVoucher; + }else{ + let dataVoucherIndex = listVoucherShippings.findIndex( + (voucher) => voucher.code == code + ); + let dataActiveVoucher = listVoucherShippings[dataVoucherIndex]; + + countDiscount = dataActiveVoucher.discountVoucher; + } + /*if (dataActiveVoucher.discountType === 'percentage') { countDiscount = cartCheckout?.subtotal * (dataActiveVoucher.discountAmount / 100) @@ -237,11 +280,22 @@ const Checkout = () => { if (!listVouchers) return; if (!activeVoucher) return; - const countDiscount = hitungDiscountVoucher(activeVoucher); + console.log('voucher') + const countDiscount = hitungDiscountVoucher(activeVoucher, 'voucher'); SetDiscountVoucher(countDiscount); }, [activeVoucher, listVouchers]); + useEffect(() => { + if (!listVoucherShippings) return; + if (!activeVoucherShipping) return; + + console.log('voucher shipping') + const countDiscount = hitungDiscountVoucher(activeVoucherShipping, 'voucher_shipping'); + + SetDiscountVoucher(countDiscount); + }, [activeVoucherShipping, listVoucherShippings]); + useEffect(() => { if (qVoucher === 'PASTIHEMAT' && listVouchers) { let code = qVoucher; -- cgit v1.2.3 From a63b03fffdf46ecddecf356d1d00d6582add75cf Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 6 Aug 2024 17:05:01 +0700 Subject: update cart pop up --- src/contexts/ProductCartContext.js | 4 +- src/contexts/ProductQuotationContext.js | 17 ------ .../components/elements/Navbar/NavbarDesktop.jsx | 35 +++++------ src/lib/quotation/components/Quotationheader.jsx | 67 ++++++++++++++++++---- 4 files changed, 76 insertions(+), 47 deletions(-) delete mode 100644 src/contexts/ProductQuotationContext.js diff --git a/src/contexts/ProductCartContext.js b/src/contexts/ProductCartContext.js index 06e97563..19889e07 100644 --- a/src/contexts/ProductCartContext.js +++ b/src/contexts/ProductCartContext.js @@ -4,12 +4,14 @@ const ProductCartContext = createContext() export const ProductCartProvider = ({ children }) => { const [productCart, setProductCart] = useState(null) + const [productQuotation, setProductQuotation] = useState(null) + const [refreshQuotation, setRefreshQuotation] = useState(false) const [refreshCart, setRefreshCart] = useState(false) const [isLoading, setIsloading] = useState(false) return ( {children} diff --git a/src/contexts/ProductQuotationContext.js b/src/contexts/ProductQuotationContext.js deleted file mode 100644 index f9e17830..00000000 --- a/src/contexts/ProductQuotationContext.js +++ /dev/null @@ -1,17 +0,0 @@ -import React, { createContext, useContext, useState } from 'react'; - -const ProductQuotationContext = createContext(); - -export const useProductQuotationContext = () => useContext(ProductQuotationContext); - -export const ProductQuotationProvider = ({ children }) => { - const [productQuotation, setProductQuotation] = useState([]); - const [refreshQuotation, setRefreshQuotation] = useState(false); - const [isLoading, setIsloading] = useState(false); - - return ( - - {children} - - ); -}; diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx index 49c4cd6e..c0e9b383 100644 --- a/src/core/components/elements/Navbar/NavbarDesktop.jsx +++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx @@ -7,7 +7,7 @@ import IndoteknikLogo from '@/images/logo.png'; import Cardheader from '@/lib/cart/components/Cartheader'; import Quotationheader from '@/lib/quotation/components/QuotationHeader' import Category from '@/lib/category/components/Category'; -import { useProductQuotationContext } from '@/contexts/ProductQuotationContext' +import { useProductCartContext } from '@/contexts/ProductCartContext'; import { ChevronDownIcon, DocumentCheckIcon, @@ -41,8 +41,9 @@ const NavbarDesktop = () => { const [cartCount, setCartCount] = useState(0); const [quotationCount, setQuotationCount] = useState(0); - // const { setProductQuotation, refreshQuotation, setRefreshQuotation, isLoading, setIsloading } = useProductQuotationContext() - + const { productCart, setProductCart, refreshCart, setRefreshCart, isLoading, setIsloading, productQuotation, setProductQuotation, refreshQuotation, setRefreshQuotation } = + useProductCartContext(); + const [pendingTransactions, setPendingTransactions] = useState([]) const [templateWA, setTemplateWA] = useState(null); const [payloadWA, setPayloadWa] = useState(null); const [urlPath, setUrlPath] = useState(null); @@ -51,15 +52,22 @@ const NavbarDesktop = () => { const { product } = useProductContext(); const { isOpen, onOpen, onClose } = useDisclosure(); - + const query = { context: 'quotation', site: - (auth?.webRole === null && auth?.site ? auth.site : null), + (auth?.webRole === null && auth?.site ? auth.site : null), }; - const { transactions } = useTransactions({query}); - const pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft'); + const { transactions } = useTransactions({ query }); + const data = transactions?.data?.saleOrders.filter( + (transaction) => transaction.status === 'draft' + ); + + useEffect(() => { + setProductQuotation(data); + setPendingTransactions(data); + }, [transactions.data]); useEffect(() => { @@ -83,7 +91,7 @@ const NavbarDesktop = () => { }; cart(); }; - handleCartChange(); + handleCartChange(); window.addEventListener('localStorageChange', handleCartChange); @@ -91,12 +99,6 @@ const NavbarDesktop = () => { window.removeEventListener('localStorageChange', handleCartChange); }; }, []); - - // useEffect(() => { - // setProductQuotation(pendingTransactions) - // }, [transactions, ]) - // console.log("Pending Transactions", pendingTransactions); - // console.log("pendingTransactions.length", pendingTransactions.length); useEffect(() => { const handleQuotationChange = () => { @@ -112,8 +114,8 @@ const NavbarDesktop = () => { return () => { window.removeEventListener('localStorageChange', handleQuotationChange); }; - }, []); - console.log("quotationCount",quotationCount) + }, [pendingTransactions]); + return ( @@ -176,7 +178,6 @@ const NavbarDesktop = () => {
- diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx index 141b731e..9f0f17a6 100644 --- a/src/lib/quotation/components/Quotationheader.jsx +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -1,16 +1,15 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; -import { getQuotationApi } from '../api/QuotationApi'; -import currencyFormat from '@/core/utils/currencyFormat'; import { createSlug } from '@/core/utils/slug'; import useAuth from '@/core/hooks/useAuth'; import { useRouter } from 'next/router'; import odooApi from '@/core/api/odooApi'; -import { useProductQuotationContext } from '@/contexts/ProductQuotationContext'; +import { useProductCartContext } from '@/contexts/ProductCartContext'; import Image from '@/core/components/elements/Image/Image'; import whatsappUrl from '@/core/utils/whatsappUrl'; import { AnimatePresence, motion } from 'framer-motion'; import style from '../../../../src-migrate/modules/cart/styles/item-promo.module.css'; import useTransactions from '../../transaction/hooks/useTransactions'; +import currencyFormat from '@/core/utils/currencyFormat'; const { DocumentCheckIcon, PhotoIcon } = require('@heroicons/react/24/outline'); const { default: Link } = require('next/link'); @@ -20,14 +19,14 @@ const Quotationheader = (quotationCount) => { context: 'quotation', site: auth?.webRole === null && auth?.site ? auth.site : null, }; - + const router = useRouter(); const [subTotal, setSubTotal] = useState(null); const [buttonLoading, SetButtonTerapkan] = useState(false); const itemLoading = [1, 2, 3]; const [countQuotation, setCountQuotation] = useState(null); - const { productQuotation, setProductQuotation, refreshQuotation, setRefreshQuotation, isLoading, setIsloading } = - useProductQuotationContext(); + const { productCart, setProductCart, refreshCart, setRefreshCart, isLoading, setIsloading, productQuotation, setProductQuotation, refreshQuotation, setRefreshQuotation } = + useProductCartContext(); const [isHovered, setIsHovered] = useState(false); const [isTop, setIsTop] = useState(true); @@ -49,12 +48,12 @@ const Quotationheader = (quotationCount) => { refreshCartf(); } }; + let { transactions } = useTransactions({ query }); const refreshCartf = useCallback(async () => { setIsloading(true); - let { transactions } = await useTransactions({ query }); let pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft'); setProductQuotation(pendingTransactions); - setCountQuotation(pendingTransactions.length); + setCountQuotation(pendingTransactions?.length ? pendingTransactions?.length : pendingTransactions?.length); setIsloading(false); }, [setProductQuotation, setIsloading]); @@ -66,7 +65,7 @@ const Quotationheader = (quotationCount) => { }, [refreshQuotation, refreshCartf, setRefreshQuotation]); useEffect(() => { - setCountQuotation(quotationCount.cartCount); + setCountQuotation(quotationCount.quotationCount); }, [quotationCount]); useEffect(() => { @@ -85,6 +84,8 @@ const Quotationheader = (quotationCount) => { router.push('/shop/quotation'); }; + console.log("quotation",qotation) + return (
@@ -105,7 +106,7 @@ const Quotationheader = (quotationCount) => { )}
- Daftar + List
Quotation
@@ -137,7 +138,7 @@ const Quotationheader = (quotationCount) => { >
Daftar Quotation
- + Lihat Semua
@@ -150,7 +151,7 @@ const Quotationheader = (quotationCount) => { Login {' '} - Untuk Melihat Daftar Keranjang Belanja Anda + Untuk Melihat Daftar Quotation Anda

)} @@ -176,6 +177,48 @@ const Quotationheader = (quotationCount) => {

)} + {auth && qotation.length > 0 && !isLoading && ( + <> +
    + {qotation && + qotation?.map((product, index) => ( + <> +
  • +
    +
    +

    {product.dateOrder}

    +

    Pending Quotation

    +
    +
    +
    +

    + No. Transaksi +

    +

    + {product.name} +

    +
    +
    +

    + No. Purchase Order +

    +

    + {product.purchaseOrderFile} +

    +
    +
    +
    +

    Total

    +

    {currencyFormat(product.amountTotal)}

    +
    +
    +
  • + + ))} +
+
+ + )}
-- cgit v1.2.3 From a1ed8969b451acc7867622fc302b0fd2b3c970a2 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 7 Aug 2024 12:10:50 +0700 Subject: update quotation pop up --- src/lib/quotation/components/Quotationheader.jsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx index 9f0f17a6..c9686b5a 100644 --- a/src/lib/quotation/components/Quotationheader.jsx +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -184,26 +184,26 @@ const Quotationheader = (quotationCount) => { qotation?.map((product, index) => ( <>
  • -
    +
    -

    {product.dateOrder}

    -

    Pending Quotation

    +

    {product.dateOrder}

    +

    Pending Quotation

    -

    +

    No. Transaksi

    -

    + {product.name} -

    +
    -

    +

    No. Purchase Order

    - {product.purchaseOrderFile} + {product.purchaseOrderFile ? product.purchaseOrderFile : '-'}

    -- cgit v1.2.3 From 86c880442fc0abbc4c356da4fa8a20bc5759aff3 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 7 Aug 2024 14:00:07 +0700 Subject: quotation update popup --- src/lib/quotation/components/Quotationheader.jsx | 54 +++++++++++++----------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx index c9686b5a..79011682 100644 --- a/src/lib/quotation/components/Quotationheader.jsx +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -184,33 +184,37 @@ const Quotationheader = (quotationCount) => { qotation?.map((product, index) => ( <>
  • -
    -
    -

    {product.dateOrder}

    -

    Pending Quotation

    -
    -
    -
    -

    - No. Transaksi -

    - - {product.name} - +
    + +
    +
    +

    Sales :

    +

    {product.sales}

    +
    +
    +

    Status :

    +

    Pending Quotation

    +
    -
    -

    - No. Purchase Order -

    -

    - {product.purchaseOrderFile ? product.purchaseOrderFile : '-'} -

    +
    +
    +

    No. Transaksi

    +

    {product.name}

    +
    +
    +

    No. Purchase Order

    +

    {product.purchaseOrderName ? product.purchaseOrderName : '-'}

    +
    -
    -
    -

    Total

    -

    {currencyFormat(product.amountTotal)}

    -
    +
    +
    +

    Total

    +

    {currencyFormat(product.amountTotal)}

    +
    +
  • -- cgit v1.2.3 From bad8abd263bd43c59dad8e61e2f5f35bfe5b7746 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 11:37:58 +0700 Subject: update quotation pop up --- .../product-detail/components/AddToCart.tsx | 1 - src/lib/quotation/components/Quotation.jsx | 7 ++-- src/lib/quotation/components/Quotationheader.jsx | 38 +++++++++++++++++++--- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index bebc793f..2f87311f 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -65,7 +65,6 @@ const AddToCart = ({ ) return; setRefreshCart(true); - // console.log('Refresh cart triggered'); setAddCartAlert(true); toast.promise( diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx index df234dc2..3fac6f29 100644 --- a/src/lib/quotation/components/Quotation.jsx +++ b/src/lib/quotation/components/Quotation.jsx @@ -9,6 +9,7 @@ import _ from 'lodash'; import { deleteItemCart, getCart, getItemCart } from '@/core/utils/cart'; import currencyFormat from '@/core/utils/currencyFormat'; import { toast } from 'react-hot-toast'; +import { useProductCartContext } from '@/contexts/ProductCartContext'; // import checkoutApi from '@/lib/checkout/api/checkoutApi' import { useRouter } from 'next/router'; import VariantGroupCard from '@/lib/variant/components/VariantGroupCard'; @@ -38,11 +39,12 @@ const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi'); const Quotation = () => { const router = useRouter(); const auth = useAuth(); - + const { data: cartCheckout } = useQuery('cartCheckout', () => getProductsCheckout() - ); +); +const { setRefreshQuotation } = useProductCartContext(); const SELF_PICKUP_ID = 32; const [products, setProducts] = useState(null); @@ -293,6 +295,7 @@ const Quotation = () => { if (isSuccess?.id) { for (const product of products) deleteItemCart({ productId: product.id }); router.push(`/shop/quotation/finish?id=${isSuccess.id}`); + setRefreshQuotation(true); return; } diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx index 79011682..14743fd6 100644 --- a/src/lib/quotation/components/Quotationheader.jsx +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -30,6 +30,7 @@ const Quotationheader = (quotationCount) => { const [isHovered, setIsHovered] = useState(false); const [isTop, setIsTop] = useState(true); + const qotation = useMemo(() => { return productQuotation || []; }, [productQuotation]); @@ -49,6 +50,7 @@ const Quotationheader = (quotationCount) => { } }; let { transactions } = useTransactions({ query }); + const refreshCartf = useCallback(async () => { setIsloading(true); let pendingTransactions = transactions?.data?.saleOrders.filter(transaction => transaction.status === 'draft'); @@ -57,6 +59,18 @@ const Quotationheader = (quotationCount) => { setIsloading(false); }, [setProductQuotation, setIsloading]); + useEffect(() => { + if (!qotation) return + + let calculateTotalDiscountAmount = 0 + for (const product of qotation) { + // if (qotation.quantity == '') continue + calculateTotalDiscountAmount += product.amountUntaxed + } + let subTotal = calculateTotalDiscountAmount + setSubTotal(subTotal) + }, [qotation]) + useEffect(() => { if (refreshQuotation) { refreshCartf(); @@ -84,8 +98,6 @@ const Quotationheader = (quotationCount) => { router.push('/shop/quotation'); }; - console.log("quotation",qotation) - return (
    @@ -211,8 +223,8 @@ const Quotationheader = (quotationCount) => {
    -

    Total

    -

    {currencyFormat(product.amountTotal)}

    +

    Total

    +

    {currencyFormat(product.amountUntaxed)}

    @@ -224,6 +236,24 @@ const Quotationheader = (quotationCount) => { )}
    + {auth && qotation.length > 0 && !isLoading && ( + <> +
    + Subtotal Sebelum PPN : + {currencyFormat(subTotal)} +
    +
    + +
    + + )} -- cgit v1.2.3 From 29662765048f561af5ab0dc586a37bd80068b633 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 11:45:59 +0700 Subject: update location quotationHeader --- src/core/components/elements/Navbar/NavbarDesktop.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx index c0e9b383..85e77b2d 100644 --- a/src/core/components/elements/Navbar/NavbarDesktop.jsx +++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx @@ -5,7 +5,7 @@ import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; import IndoteknikLogo from '@/images/logo.png'; import Cardheader from '@/lib/cart/components/Cartheader'; -import Quotationheader from '@/lib/quotation/components/QuotationHeader' +import Quotationheader from '../../../../../src/lib/quotation/components/QuotationHeader' import Category from '@/lib/category/components/Category'; import { useProductCartContext } from '@/contexts/ProductCartContext'; import { -- cgit v1.2.3 From 6e36b0e78c7ac56c8b7d2f27a19838e9aaa9da98 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 12:03:04 +0700 Subject: add import quotationHeader --- src/core/components/elements/Navbar/NavbarDesktop.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx index 85e77b2d..03335df6 100644 --- a/src/core/components/elements/Navbar/NavbarDesktop.jsx +++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx @@ -5,7 +5,7 @@ import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; import IndoteknikLogo from '@/images/logo.png'; import Cardheader from '@/lib/cart/components/Cartheader'; -import Quotationheader from '../../../../../src/lib/quotation/components/QuotationHeader' +import Quotationheader from "../../../../../src/lib/quotation/components/Quotationheader.jsx" import Category from '@/lib/category/components/Category'; import { useProductCartContext } from '@/contexts/ProductCartContext'; import { -- cgit v1.2.3 From 079f8029445fdd243e267a4af7c7a4d5780afa24 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 14:11:32 +0700 Subject: update pop up quotation & cart --- .../product-detail/components/AddToCart.tsx | 47 +++++++++++++--------- src/contexts/ProductCartContext.js | 5 +-- .../components/elements/Navbar/NavbarDesktop.jsx | 3 -- src/lib/cart/components/Cartheader.jsx | 1 + src/lib/quotation/components/Quotation.jsx | 4 +- src/lib/quotation/components/Quotationheader.jsx | 20 +++++---- 6 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src-migrate/modules/product-detail/components/AddToCart.tsx b/src-migrate/modules/product-detail/components/AddToCart.tsx index 2f87311f..a5284637 100644 --- a/src-migrate/modules/product-detail/components/AddToCart.tsx +++ b/src-migrate/modules/product-detail/components/AddToCart.tsx @@ -3,7 +3,7 @@ import style from '../styles/price-action.module.css'; import { Button, Link, useToast } from '@chakra-ui/react' import product from 'next-seo/lib/jsonld/product' import { useRouter } from 'next/router' -import { useState } from 'react' +import { useEffect, useState } from 'react' import Image from '~/components/ui/image' import { getAuth } from '~/libs/auth' import { upsertUserCart } from '~/services/cart' @@ -23,6 +23,8 @@ type Props = { products : IProductDetail } +type Status = 'idle' | 'loading' | 'success' + const AddToCart = ({ variantId, quantity = 1, @@ -41,8 +43,9 @@ const AddToCart = ({ } = useProductDetail(); const [product, setProducts] = useState(products); - - const {setRefreshCart} = useProductCartContext() + const [status, setStatus] = useState('idle') + const { productCart, setRefreshCart, setProductCart, refreshCart, isLoading, setIsloading } = + useProductCartContext() const productSimilarQuery = [ product?.name, @@ -51,7 +54,7 @@ const AddToCart = ({ ].join('&'); const [addCartAlert, setAddCartAlert] = useState(false); - const handleClick = async () => { + const handleButton = async () => { if (typeof auth !== 'object') { const currentUrl = encodeURIComponent(router.asPath) router.push(`/login?next=${currentUrl}`) @@ -63,33 +66,37 @@ const AddToCart = ({ isNaN(quantity) || typeof auth !== 'object' ) return; - - setRefreshCart(true); - setAddCartAlert(true); - - toast.promise( - upsertUserCart({ - userId: auth.id, + if (status === 'success') return + setStatus('loading') + await upsertUserCart({ + userId: auth.id, type: 'product', id: variantId, qty: quantity, selected: true, source: source, qtyAppend: true - }), - { - loading: { title: 'Menambahkan ke keranjang', description: 'Mohon tunggu...' }, - success: { title: 'Menambahkan ke keranjang', description: 'Berhasil menambahkan ke keranjang belanja' }, - error: { title: 'Menambahkan ke keranjang', description: 'Gagal menambahkan ke keranjang belanja' }, - } - ) - + }) + setStatus('idle') + setRefreshCart(true); + setAddCartAlert(true); + toast({ + title: 'Tambah ke keranjang', + description: 'Berhasil menambahkan barang ke keranjang belanja', + status: 'success', + duration: 3000, + isClosable: true, + position: 'top', + }) if (source === 'buy') { router.push('/shop/checkout?source=buy') } } + useEffect(() => { + if (status === 'success') setTimeout(() => { setStatus('idle') }, 3000) + }, [status]) const btnConfig = { 'add_to_cart': { @@ -104,7 +111,7 @@ const AddToCart = ({ return (
    - { const [productCart, setProductCart] = useState(null) - const [productQuotation, setProductQuotation] = useState(null) - const [refreshQuotation, setRefreshQuotation] = useState(false) const [refreshCart, setRefreshCart] = useState(false) const [isLoading, setIsloading] = useState(false) + const [productQuotation, setProductQuotation] = useState(null) return ( {children} diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx index 03335df6..2e8c982e 100644 --- a/src/core/components/elements/Navbar/NavbarDesktop.jsx +++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx @@ -41,8 +41,6 @@ const NavbarDesktop = () => { const [cartCount, setCartCount] = useState(0); const [quotationCount, setQuotationCount] = useState(0); - const { productCart, setProductCart, refreshCart, setRefreshCart, isLoading, setIsloading, productQuotation, setProductQuotation, refreshQuotation, setRefreshQuotation } = - useProductCartContext(); const [pendingTransactions, setPendingTransactions] = useState([]) const [templateWA, setTemplateWA] = useState(null); const [payloadWA, setPayloadWa] = useState(null); @@ -65,7 +63,6 @@ const NavbarDesktop = () => { ); useEffect(() => { - setProductQuotation(data); setPendingTransactions(data); }, [transactions.data]); diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx index c7a8f0b8..6967d180 100644 --- a/src/lib/cart/components/Cartheader.jsx +++ b/src/lib/cart/components/Cartheader.jsx @@ -81,6 +81,7 @@ const Cardheader = (cartCount) => { useEffect(() => { setCountCart(cartCount.cartCount) + setRefreshCart(false) }, [cartCount]) useEffect(() => { diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx index 3fac6f29..0ad042de 100644 --- a/src/lib/quotation/components/Quotation.jsx +++ b/src/lib/quotation/components/Quotation.jsx @@ -44,7 +44,7 @@ const Quotation = () => { getProductsCheckout() ); -const { setRefreshQuotation } = useProductCartContext(); +const { setRefreshCart } = useProductCartContext(); const SELF_PICKUP_ID = 32; const [products, setProducts] = useState(null); @@ -295,7 +295,7 @@ const { setRefreshQuotation } = useProductCartContext(); if (isSuccess?.id) { for (const product of products) deleteItemCart({ productId: product.id }); router.push(`/shop/quotation/finish?id=${isSuccess.id}`); - setRefreshQuotation(true); + setRefreshCart(true); return; } diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx index 14743fd6..10e3e147 100644 --- a/src/lib/quotation/components/Quotationheader.jsx +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -25,7 +25,7 @@ const Quotationheader = (quotationCount) => { const [buttonLoading, SetButtonTerapkan] = useState(false); const itemLoading = [1, 2, 3]; const [countQuotation, setCountQuotation] = useState(null); - const { productCart, setProductCart, refreshCart, setRefreshCart, isLoading, setIsloading, productQuotation, setProductQuotation, refreshQuotation, setRefreshQuotation } = + const { productCart, setProductCart, refreshCart, setRefreshCart, isLoading, setIsloading, productQuotation, setProductQuotation } = useProductCartContext(); const [isHovered, setIsHovered] = useState(false); @@ -72,11 +72,11 @@ const Quotationheader = (quotationCount) => { }, [qotation]) useEffect(() => { - if (refreshQuotation) { + if (refreshCart) { refreshCartf(); } - setRefreshQuotation(false); - }, [refreshQuotation, refreshCartf, setRefreshQuotation]); + setRefreshCart(false); + }, [ refreshCartf, setRefreshCart]); useEffect(() => { setCountQuotation(quotationCount.quotationCount); @@ -150,9 +150,6 @@ const Quotationheader = (quotationCount) => { >
    Daftar Quotation
    - - Lihat Semua -

    @@ -221,7 +218,8 @@ const Quotationheader = (quotationCount) => {

    {product.purchaseOrderName ? product.purchaseOrderName : '-'}

    -
    + {/*
    */} +

    Total

    {currencyFormat(product.amountUntaxed)}

    @@ -238,18 +236,18 @@ const Quotationheader = (quotationCount) => {
    {auth && qotation.length > 0 && !isLoading && ( <> -
    +
    Subtotal Sebelum PPN : {currencyFormat(subTotal)}
    -- cgit v1.2.3 From 64489b794a80b381d86ea226f0fe36457d5836be Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 15:06:37 +0700 Subject: update quotation pop up bug --- src/core/components/elements/Navbar/NavbarDesktop.jsx | 2 +- src/lib/quotation/components/Quotationheader.jsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/components/elements/Navbar/NavbarDesktop.jsx b/src/core/components/elements/Navbar/NavbarDesktop.jsx index 2e8c982e..1163aff3 100644 --- a/src/core/components/elements/Navbar/NavbarDesktop.jsx +++ b/src/core/components/elements/Navbar/NavbarDesktop.jsx @@ -175,7 +175,7 @@ const NavbarDesktop = () => {
    - + diff --git a/src/lib/quotation/components/Quotationheader.jsx b/src/lib/quotation/components/Quotationheader.jsx index 10e3e147..0bb4dfe0 100644 --- a/src/lib/quotation/components/Quotationheader.jsx +++ b/src/lib/quotation/components/Quotationheader.jsx @@ -80,6 +80,7 @@ const Quotationheader = (quotationCount) => { useEffect(() => { setCountQuotation(quotationCount.quotationCount); + setProductQuotation(quotationCount.data); }, [quotationCount]); useEffect(() => { -- cgit v1.2.3 From 3de1a412bba31b19b8b443dd91df8aff8d6eda07 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 16:22:00 +0700 Subject: update link button --- src-migrate/modules/product-promo/components/AddToCart.tsx | 2 +- src/lib/quotation/components/Quotationheader.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-migrate/modules/product-promo/components/AddToCart.tsx b/src-migrate/modules/product-promo/components/AddToCart.tsx index 8567dad8..3d0955e3 100644 --- a/src-migrate/modules/product-promo/components/AddToCart.tsx +++ b/src-migrate/modules/product-promo/components/AddToCart.tsx @@ -132,7 +132,7 @@ const ProductPromoAddToCart = ({product, promotion }: Props) => { />
    - {!!product.manufacture.name ? ( + {!!product?.manufacture?.name ? ( { const handleCheckout = async () => { SetButtonTerapkan(true); let checkoutAll = await odooApi('POST', `/api/v1/user/${auth.id}/cart/select-all`); - router.push('/shop/quotation'); + router.push('/my/quotations'); }; return ( -- cgit v1.2.3 From 8a4d7247dd4163050f95055f13391b709bb29e66 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 10 Aug 2024 13:22:42 +0700 Subject: add feature tracking order --- src/lib/tracking-order/component/TrackingOrder.jsx | 94 ++++++++++++++++++++++ src/pages/tracking-order.jsx | 26 ++++++ 2 files changed, 120 insertions(+) create mode 100644 src/lib/tracking-order/component/TrackingOrder.jsx create mode 100644 src/pages/tracking-order.jsx diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx new file mode 100644 index 00000000..476e6507 --- /dev/null +++ b/src/lib/tracking-order/component/TrackingOrder.jsx @@ -0,0 +1,94 @@ +import odooApi from '@/core/api/odooApi' +import HookFormSelect from '@/core/components/elements/Select/HookFormSelect' +import cityApi from '@/lib/address/api/cityApi' +import { yupResolver } from '@hookform/resolvers/yup' +import React, { useEffect, useRef, useState } from 'react' +import ReCAPTCHA from 'react-google-recaptcha' +import { Controller, useForm } from 'react-hook-form' +import { toast } from 'react-hot-toast' +import * as Yup from 'yup' +import { useRouter } from 'next/router' +import Manifest from '@/lib/treckingAwb/component/Manifest' +const TrackingOrder = () => { + const [idAWB, setIdAWB] = useState(null) + const closePopup = () => { + setIdAWB(null) + } + const { + register, + handleSubmit, + formState: { errors }, + control, + reset + } = useForm({ + resolver: yupResolver(validationSchema), + defaultValues + }) + + const onSubmitHandler = async (values) => { + console.log('values',values) + // setIdAWB(shipment.id) + // setIdAWB(20623) + setIdAWB(25085) + } + return ( +
    +

    Tracking Order

    +
    + Untuk melacak pesanan Anda, masukkan ID Pesanan Anda di kotak di bawah ini dan tekan tombol "Lacak". ID ini diberikan kepada Anda pada tanda terima dan dalam email konfirmasi yang seharusnya Anda terima. +
    +
    +
    +
    +
    + + + {console.log("errors",errors)} +
    {errors.id?.message}
    +
    +
    + + +
    {errors.email?.message}
    +
    +
    +
    + + +
    +
    + +
    +
    + ) +} + +const validationSchema = Yup.object().shape({ + email: Yup.string().email('Format harus seperti contoh@email.com'), + id: Yup.string().required('Harus di-isi'), + }) + + const defaultValues = { + email: '', + id: '' + } + + +export default TrackingOrder diff --git a/src/pages/tracking-order.jsx b/src/pages/tracking-order.jsx new file mode 100644 index 00000000..18e1a78a --- /dev/null +++ b/src/pages/tracking-order.jsx @@ -0,0 +1,26 @@ +import Seo from '@/core/components/Seo' +import dynamic from 'next/dynamic' +import SimpleFooter from '@/core/components/elements/Footer/SimpleFooter'; +import BasicLayout from '@/core/components/layouts/BasicLayout'; +import DesktopView from '@/core/components/views/DesktopView'; +import MobileView from '@/core/components/views/MobileView'; +const PageTrackingOrder = dynamic(() => import('@/lib/tracking-order/component/TrackingOrder')) + +export default function TrackingOrder() { + return ( + <> + + + + + + + + + + + + + + ); +} -- cgit v1.2.3 From 9ee852f139aed0f1034798b6a22b76eb9bd03aa4 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 12 Aug 2024 16:35:23 +0700 Subject: update tracking order --- src/lib/tracking-order/api/trackingOrder.js | 8 + src/lib/tracking-order/component/TrackingOrder.jsx | 164 +++++++++++++-------- 2 files changed, 107 insertions(+), 65 deletions(-) create mode 100644 src/lib/tracking-order/api/trackingOrder.js diff --git a/src/lib/tracking-order/api/trackingOrder.js b/src/lib/tracking-order/api/trackingOrder.js new file mode 100644 index 00000000..cc48c40c --- /dev/null +++ b/src/lib/tracking-order/api/trackingOrder.js @@ -0,0 +1,8 @@ +import odooApi from "@/core/api/odooApi"; + +export const trackingOrder = async ({query}) => { + const params = new URLSearchParams(query).toString(); + const list = await odooApi('GET', `/api/v1/tracking_order?${params}`) + + return list; +} diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx index 476e6507..c9f739b3 100644 --- a/src/lib/tracking-order/component/TrackingOrder.jsx +++ b/src/lib/tracking-order/component/TrackingOrder.jsx @@ -1,94 +1,128 @@ -import odooApi from '@/core/api/odooApi' -import HookFormSelect from '@/core/components/elements/Select/HookFormSelect' -import cityApi from '@/lib/address/api/cityApi' import { yupResolver } from '@hookform/resolvers/yup' -import React, { useEffect, useRef, useState } from 'react' -import ReCAPTCHA from 'react-google-recaptcha' -import { Controller, useForm } from 'react-hook-form' -import { toast } from 'react-hot-toast' +import React, { useEffect, useState } from 'react' +import { useForm } from 'react-hook-form' import * as Yup from 'yup' -import { useRouter } from 'next/router' import Manifest from '@/lib/treckingAwb/component/Manifest' +import { trackingOrder } from '../api/trackingOrder' +import { useQuery } from 'react-query' +import { Spinner } from '@chakra-ui/react'; +import { Search } from 'lucide-react'; +import odooApi from '@/core/api/odooApi' + const TrackingOrder = () => { const [idAWB, setIdAWB] = useState(null) + const [inputQuery, setInputQuery] = useState(null) + const [buttonClick, setButtonClick] = useState(false) + const [apiError, setApiError] = useState(null) // State to store API error message + const closePopup = () => { setIdAWB(null) - } + setButtonClick(false) + setInputQuery(null) + setApiError(null) // Reset error message on close + } + const { register, handleSubmit, formState: { errors }, control, reset - } = useForm({ + } = useForm({ resolver: yupResolver(validationSchema), defaultValues - }) + }) + + const query = { + email: inputQuery?.email, + so: inputQuery?.id + } + + const { data: tracking, isLoading, isError, error } = useQuery( + ['tracking', query], + () => trackingOrder({ query: query }), + { + enabled: !!query.email && !!query.so, + onSuccess: (data) => { + if (buttonClick) { + if (data?.code === 403 || data?.code === 400 || data?.code === 404) { + setApiError(data?.description); + } else if (data?.pickings?.length > 0) { + setIdAWB(data.pickings[0]?.id); + } else { + setApiError('No pickings data available'); + } + setButtonClick(false); + setInputQuery(null); + } + }, + } + ); const onSubmitHandler = async (values) => { - console.log('values',values) - // setIdAWB(shipment.id) - // setIdAWB(20623) - setIdAWB(25085) - } - return ( -
    -

    Tracking Order

    -
    - Untuk melacak pesanan Anda, masukkan ID Pesanan Anda di kotak di bawah ini dan tekan tombol "Lacak". ID ini diberikan kepada Anda pada tanda terima dan dalam email konfirmasi yang seharusnya Anda terima. -
    -
    -
    -
    -
    - - +

    Tracking Order

    +
    + Untuk melacak pesanan Anda, masukkan ID Pesanan Anda di kotak di bawah ini dan tekan tombol "Lacak". ID ini diberikan kepada Anda pada tanda terima dan dalam email konfirmasi yang seharusnya Anda terima. +
    +
    + +
    +
    + + - {console.log("errors",errors)} -
    {errors.id?.message}
    +
    {errors.id?.message}
    +
    +
    + + +
    {errors.email?.message}
    +
    -
    - - -
    {errors.email?.message}
    +
    +
    -
    -
    - - -
    - - + + {/* Display the API error message */} + {apiError &&
    {apiError}
    } + +
    -
    - ) + ) } const validationSchema = Yup.object().shape({ - email: Yup.string().email('Format harus seperti contoh@email.com'), + email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'), id: Yup.string().required('Harus di-isi'), - }) - - const defaultValues = { +}) + +const defaultValues = { email: '', id: '' - } - +} export default TrackingOrder -- cgit v1.2.3 From 4dc62bbe5262be23b2622853973e803f63214a60 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 12 Aug 2024 17:09:13 +0700 Subject: update category management --- src/lib/category/components/Category.jsx | 32 ++++++++++++++++++++++++++-- src/lib/category/components/PopularBrand.jsx | 2 +- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx index ff958378..b10cb661 100644 --- a/src/lib/category/components/Category.jsx +++ b/src/lib/category/components/Category.jsx @@ -6,11 +6,36 @@ import { ChevronRightIcon } from '@heroicons/react/24/outline' import Image from 'next/image' import { useEffect, useState } from 'react' import PopularBrand from './PopularBrand' +import { bannerApi } from '@/api/bannerApi'; +const { useQuery } = require('react-query') const Category = () => { const [categories, setCategories] = useState([]) const [openCategories, setOpenCategory] = useState([]); + const [banner, setBanner] = useState([]); + + const promotionProgram = useQuery('banner-promo-category-card', bannerApi({ type: 'banner-promo-category-card' })); + // const promotionProgram = useQuery('promotionProgram', bannerApi({ type: 'banner-promotion' })); + useEffect(() => { + const loadCategories = async () => { + let dataCategories = await odooApi('GET', '/api/v1/category/tree') + dataCategories = dataCategories?.map((category) => { + category.childs = category.childs.map((child1Category) => { + return { + ...child1Category, + isOpen: false + } + }) + return { + ...category, + isOpen: false + } + }) + setCategories(dataCategories) + } + loadCategories() + }, []) useEffect(() => { const loadCategories = async () => { @@ -86,9 +111,12 @@ const Category = () => {
    -
    - + {promotionProgram?.data[0]?.map((banner, index)=>( +
    + {/* */} + {`${banner.name}`}
    + ))}
    diff --git a/src/lib/category/components/PopularBrand.jsx b/src/lib/category/components/PopularBrand.jsx index dca731e8..7c297d39 100644 --- a/src/lib/category/components/PopularBrand.jsx +++ b/src/lib/category/components/PopularBrand.jsx @@ -17,7 +17,7 @@ const PopularBrand = ({ category }) => { const fetchTopBrands = async () => { try { - const items = await fetchPromoItemsSolr(`category_id_ids:(${category.categoryDataIds.join(' OR ')})`); + const items = await fetchPromoItemsSolr(`category_id_ids:(${category?.categoryDataIds.join(' OR ')})`); // console.log("id",items) // Fungsi untuk deduplikasi dan mengambil 12 nama brand teratas const getTop12UniqueBrands = (prod) => { -- cgit v1.2.3 From 3e11fce63de4b0d99a1e48c9998d6fcfcec13d98 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 12 Aug 2024 17:11:07 +0700 Subject: update error code --- src/lib/category/components/PopularBrand.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/category/components/PopularBrand.jsx b/src/lib/category/components/PopularBrand.jsx index 7c297d39..09c0f8a1 100644 --- a/src/lib/category/components/PopularBrand.jsx +++ b/src/lib/category/components/PopularBrand.jsx @@ -17,7 +17,7 @@ const PopularBrand = ({ category }) => { const fetchTopBrands = async () => { try { - const items = await fetchPromoItemsSolr(`category_id_ids:(${category?.categoryDataIds.join(' OR ')})`); + const items = await fetchPromoItemsSolr(`category_id_ids:(${category?.categoryDataIds?.join(' OR ')})`); // console.log("id",items) // Fungsi untuk deduplikasi dan mengambil 12 nama brand teratas const getTop12UniqueBrands = (prod) => { -- cgit v1.2.3 From 0a889a2acb147ffe3fe0ad1ca205683c7bf3fe82 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 13 Aug 2024 09:12:51 +0700 Subject: add tracking order to footer --- src/core/components/elements/Footer/BasicFooter.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/components/elements/Footer/BasicFooter.jsx b/src/core/components/elements/Footer/BasicFooter.jsx index 4beea604..8f024d86 100644 --- a/src/core/components/elements/Footer/BasicFooter.jsx +++ b/src/core/components/elements/Footer/BasicFooter.jsx @@ -175,7 +175,7 @@ const CustomerGuide = () => (
    Bantuan & Panduan
      -
    • +
    • Metode Pembayaran @@ -210,6 +210,11 @@ const CustomerGuide = () => ( Panduan Pick Up Service
    • +
    • + + Tracking Order + +
    ); -- cgit v1.2.3 From 004a9a644aed65d5c02263f19cce8b7c3000f354 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 13 Aug 2024 10:19:38 +0700 Subject: update category --- src/lib/category/api/popularProduct.js | 5 ++-- src/lib/category/components/Category.jsx | 38 ++++++++++++++-------------- src/lib/category/components/PopularBrand.jsx | 4 +-- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/lib/category/api/popularProduct.js b/src/lib/category/api/popularProduct.js index e17e0ae5..146c9449 100644 --- a/src/lib/category/api/popularProduct.js +++ b/src/lib/category/api/popularProduct.js @@ -1,9 +1,10 @@ -export const fetchPromoItemsSolr = async (category_id_ids) => { +export const fetchPopulerProductSolr = async (category_id_ids) => { let sort ='sort=qty_sold_f desc'; try { const queryParams = new URLSearchParams({ q: category_id_ids }); - const response = await fetch(`/solr/product/select?${queryParams.toString()}&rows=2000&fl=manufacture_name_s,manufacture_id_i,id,display_name_s&${sort}`); + const response = await fetch(`/solr/product/select?${queryParams.toString()}&rows=2000&fl=manufacture_name_s,manufacture_id_i,id,display_name_s,qty_sold_f&${sort}`); + console.log("response",response) if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } diff --git a/src/lib/category/components/Category.jsx b/src/lib/category/components/Category.jsx index b10cb661..374cdf78 100644 --- a/src/lib/category/components/Category.jsx +++ b/src/lib/category/components/Category.jsx @@ -37,25 +37,25 @@ const Category = () => { loadCategories() }, []) - useEffect(() => { - const loadCategories = async () => { - let dataCategories = await odooApi('GET', '/api/v1/category/tree') - dataCategories = dataCategories?.map((category) => { - category.childs = category.childs.map((child1Category) => { - return { - ...child1Category, - isOpen: false - } - }) - return { - ...category, - isOpen: false - } - }) - setCategories(dataCategories) - } - loadCategories() - }, []) + // useEffect(() => { + // const loadCategories = async () => { + // let dataCategories = await odooApi('GET', '/api/v1/category/tree') + // dataCategories = dataCategories?.map((category) => { + // category.childs = category.childs.map((child1Category) => { + // return { + // ...child1Category, + // isOpen: false + // } + // }) + // return { + // ...category, + // isOpen: false + // } + // }) + // setCategories(dataCategories) + // } + // loadCategories() + // }, []) // console.log("categories",categories) return ( diff --git a/src/lib/category/components/PopularBrand.jsx b/src/lib/category/components/PopularBrand.jsx index 09c0f8a1..f0b12e2c 100644 --- a/src/lib/category/components/PopularBrand.jsx +++ b/src/lib/category/components/PopularBrand.jsx @@ -8,7 +8,7 @@ import Image from 'next/image' import { ChevronRightIcon } from '@heroicons/react/24/outline' import useProductSearch from '../../../lib/product/hooks/useProductSearch'; import { SolrResponse } from "~/types/solr"; -import { fetchPromoItemsSolr } from '../api/popularProduct' +import { fetchPopulerProductSolr } from '../api/popularProduct' const SOLR_HOST = process.env.SOLR_HOST @@ -17,7 +17,7 @@ const PopularBrand = ({ category }) => { const fetchTopBrands = async () => { try { - const items = await fetchPromoItemsSolr(`category_id_ids:(${category?.categoryDataIds?.join(' OR ')})`); + const items = await fetchPopulerProductSolr(`category_id_ids:(${category?.categoryDataIds?.join(' OR ')})`); // console.log("id",items) // Fungsi untuk deduplikasi dan mengambil 12 nama brand teratas const getTop12UniqueBrands = (prod) => { -- cgit v1.2.3 From 4fa3d1026ebabeb75dafc3bb9c630ea300859959 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 13 Aug 2024 11:23:19 +0700 Subject: update tracking order --- src/lib/tracking-order/component/TrackingOrder.jsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx index c9f739b3..03b21b3e 100644 --- a/src/lib/tracking-order/component/TrackingOrder.jsx +++ b/src/lib/tracking-order/component/TrackingOrder.jsx @@ -7,7 +7,7 @@ import { trackingOrder } from '../api/trackingOrder' import { useQuery } from 'react-query' import { Spinner } from '@chakra-ui/react'; import { Search } from 'lucide-react'; -import odooApi from '@/core/api/odooApi' +import whatsappUrl from '@/core/utils/whatsappUrl'; const TrackingOrder = () => { const [idAWB, setIdAWB] = useState(null) @@ -68,7 +68,17 @@ const TrackingOrder = () => {

    Tracking Order

    - Untuk melacak pesanan Anda, masukkan ID Pesanan Anda di kotak di bawah ini dan tekan tombol "Lacak". ID ini diberikan kepada Anda pada tanda terima dan dalam email konfirmasi yang seharusnya Anda terima. + + {`Untuk melacak pesanan Anda, masukkan Nomor Transaksi di kotak bawah ini dan masukkan Email login anda lalu tekan tombol "Lacak". Nomor Transaksi ini dapat Anda lihat dalam menu `} + + Daftar Transaksi + + {`. Jika mengalami kesulitan `} + + hubungi kami + + {`.`} +
    -- cgit v1.2.3 From f97e2c348e3c4b3984eb598ac34de98e35fdde28 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 13 Aug 2024 12:00:17 +0700 Subject: update number wa --- src/lib/tracking-order/component/TrackingOrder.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx index 03b21b3e..cf790832 100644 --- a/src/lib/tracking-order/component/TrackingOrder.jsx +++ b/src/lib/tracking-order/component/TrackingOrder.jsx @@ -74,7 +74,7 @@ const TrackingOrder = () => { Daftar Transaksi {`. Jika mengalami kesulitan `} - + hubungi kami {`.`} -- cgit v1.2.3 From e8745f729cb48a2cab96f8f216617240326f2018 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 13 Aug 2024 14:39:08 +0700 Subject: add feature pickup service --- src-migrate/modules/cart/components/Item.tsx | 5 +++-- src/lib/checkout/components/Checkout.jsx | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx index 47893498..44ec4fd5 100644 --- a/src-migrate/modules/cart/components/Item.tsx +++ b/src-migrate/modules/cart/components/Item.tsx @@ -17,11 +17,11 @@ import CartItemSelect from './ItemSelect' type Props = { item: CartItemProps editable?: boolean + selfPicking?: boolean pilihSemuaCart?: boolean } -const CartItem = ({ item, editable = true,}: Props) => { - +const CartItem = ({ item, editable = true, selfPicking}: Props) => { return (
    {item.cart_type === 'promotion' && ( @@ -53,6 +53,7 @@ const CartItem = ({ item, editable = true,}: Props) => {
    + {/* disini */}
    diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 09a791ee..5f771f41 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -1295,7 +1295,7 @@ const Checkout = () => {
    {!!products && snakecaseKeys(products).map((item, index) => ( - + ))}
    -- cgit v1.2.3 From a72f9273664715e9708523ca1a6a4554bd22c917 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 13 Aug 2024 15:37:29 +0700 Subject: update pickup service add field --- src-migrate/modules/cart/components/Item.tsx | 1 + src-migrate/types/cart.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx index 44ec4fd5..25df62fe 100644 --- a/src-migrate/modules/cart/components/Item.tsx +++ b/src-migrate/modules/cart/components/Item.tsx @@ -54,6 +54,7 @@ const CartItem = ({ item, editable = true, selfPicking}: Props) => {
    {/* disini */} + {/* {selfPicking && (item.is_in_bu) && (item.on_hand_qty > item.quantity)} */}
    diff --git a/src-migrate/types/cart.ts b/src-migrate/types/cart.ts index 4e3c8b99..a3115103 100644 --- a/src-migrate/types/cart.ts +++ b/src-migrate/types/cart.ts @@ -32,6 +32,8 @@ export type CartItem = { id: number; name: string; stock: number; + is_in_bu: boolean; + on_hand_qty: number; weight: number; attributes: string[]; parent: { -- cgit v1.2.3 From 62704c101d17afb7f71389ef23d6183b2cd16dfa Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 14 Aug 2024 15:11:33 +0700 Subject: update self picking di product card --- src-migrate/modules/cart/components/Item.tsx | 6 +++++- src-migrate/types/product.ts | 1 + src/lib/product/components/ProductCard.jsx | 28 ++++++++++++++++++++++++---- src/utils/solrMapping.js | 1 + 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx index 25df62fe..ce4c5bff 100644 --- a/src-migrate/modules/cart/components/Item.tsx +++ b/src-migrate/modules/cart/components/Item.tsx @@ -54,7 +54,11 @@ const CartItem = ({ item, editable = true, selfPicking}: Props) => {
    {/* disini */} - {/* {selfPicking && (item.is_in_bu) && (item.on_hand_qty > item.quantity)} */} + {selfPicking && (item.is_in_bu) && (item.on_hand_qty > item.quantity) && ( +
    + Barang ini bisa di pickup maksimal pukul 16.00 +
    + )}
    diff --git a/src-migrate/types/product.ts b/src-migrate/types/product.ts index 681cdc8e..31ea0ce1 100644 --- a/src-migrate/types/product.ts +++ b/src-migrate/types/product.ts @@ -12,6 +12,7 @@ export interface IProduct { variant_total: number; description: string; isSni: boolean; + is_in_bu: boolean; isTkdn: boolean; categories: { id: string; diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 35e2a665..4b3f693c 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -147,9 +147,20 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
    {product?.manufacture?.name ? ( - - {product.manufacture.name} - +
    + +
    + {product.manufacture.name} +
    + + {product?.is_in_bu && ( +
    + + Click & Pickup + +
    + )} +
    ) : (
    -
    )} @@ -292,9 +303,18 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => {
    )} {product?.manufacture?.name ? ( - +
    + {product.manufacture.name} + {/* {product?.is_in_bu && ( +
    + + Click & Pickup + +
    + )} */} +
    ) : (
    -
    )} diff --git a/src/utils/solrMapping.js b/src/utils/solrMapping.js index d4694eb2..fee474be 100644 --- a/src/utils/solrMapping.js +++ b/src/utils/solrMapping.js @@ -38,6 +38,7 @@ export const productMappingSolr = (products, pricelist) => { qtySold: product?.qty_sold_f || 0, isTkdn:product?.tkdn_b || false, isSni:product?.sni_b || false, + is_in_bu:product?.is_in_bu_b || false, voucherPastiHemat:product?.voucher_pastihemat || [] }; -- cgit v1.2.3 From c324065cf2270c4e489749f0281eb45a5f120b08 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 14 Aug 2024 15:20:16 +0700 Subject: change to --- src/lib/tracking-order/component/TrackingOrder.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/tracking-order/component/TrackingOrder.jsx b/src/lib/tracking-order/component/TrackingOrder.jsx index cf790832..394979c1 100644 --- a/src/lib/tracking-order/component/TrackingOrder.jsx +++ b/src/lib/tracking-order/component/TrackingOrder.jsx @@ -8,6 +8,7 @@ import { useQuery } from 'react-query' import { Spinner } from '@chakra-ui/react'; import { Search } from 'lucide-react'; import whatsappUrl from '@/core/utils/whatsappUrl'; +import Link from 'next/link' const TrackingOrder = () => { const [idAWB, setIdAWB] = useState(null) @@ -70,13 +71,13 @@ const TrackingOrder = () => { -- cgit v1.2.3 From 08e5b76ba58645929ddeda1830f85f3eaf43969e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 14 Aug 2024 17:01:44 +0700 Subject: update pickup service logic --- src-migrate/modules/cart/components/Item.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx index ce4c5bff..272fa622 100644 --- a/src-migrate/modules/cart/components/Item.tsx +++ b/src-migrate/modules/cart/components/Item.tsx @@ -54,7 +54,7 @@ const CartItem = ({ item, editable = true, selfPicking}: Props) => {
    {/* disini */} - {selfPicking && (item.is_in_bu) && (item.on_hand_qty > item.quantity) && ( + {selfPicking && (item.is_in_bu) && (item.on_hand_qty >= item.quantity) && (
    Barang ini bisa di pickup maksimal pukul 16.00
    -- cgit v1.2.3 From ad82ceb618565eec7b1e955c8ba12243d26253f1 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 15 Aug 2024 11:27:35 +0700 Subject: update view --- src-migrate/modules/cart/components/Item.tsx | 6 ++++-- src/lib/checkout/components/Checkout.jsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx index 272fa622..a9b2d968 100644 --- a/src-migrate/modules/cart/components/Item.tsx +++ b/src-migrate/modules/cart/components/Item.tsx @@ -22,6 +22,8 @@ type Props = { } const CartItem = ({ item, editable = true, selfPicking}: Props) => { + console.log("item",item) + console.log("selfPicking",selfPicking) return (
    {item.cart_type === 'promotion' && ( @@ -55,8 +57,8 @@ const CartItem = ({ item, editable = true, selfPicking}: Props) => {
    {/* disini */} {selfPicking && (item.is_in_bu) && (item.on_hand_qty >= item.quantity) && ( -
    - Barang ini bisa di pickup maksimal pukul 16.00 +
    + *Barang ini bisa di pickup maksimal pukul 16.00
    )} diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx index 5f771f41..6deba693 100644 --- a/src/lib/checkout/components/Checkout.jsx +++ b/src/lib/checkout/components/Checkout.jsx @@ -1004,7 +1004,7 @@ const Checkout = () => {
    {!!products && snakecaseKeys(products).map((item, index) => ( - + ))}
    -- cgit v1.2.3 From 33363a1a8dc7f4641b7b054dc72339bf53495102 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 15 Aug 2024 16:55:28 +0700 Subject: update pickup image on product card --- public/images/PICKUP-NOW.png | Bin 0 -> 1926 bytes src-migrate/modules/cart/components/Item.tsx | 2 -- src/lib/product/components/ProductCard.jsx | 26 +++++++++++--------------- 3 files changed, 11 insertions(+), 17 deletions(-) create mode 100644 public/images/PICKUP-NOW.png diff --git a/public/images/PICKUP-NOW.png b/public/images/PICKUP-NOW.png new file mode 100644 index 00000000..d7c01f44 Binary files /dev/null and b/public/images/PICKUP-NOW.png differ diff --git a/src-migrate/modules/cart/components/Item.tsx b/src-migrate/modules/cart/components/Item.tsx index a9b2d968..a54d4648 100644 --- a/src-migrate/modules/cart/components/Item.tsx +++ b/src-migrate/modules/cart/components/Item.tsx @@ -22,8 +22,6 @@ type Props = { } const CartItem = ({ item, editable = true, selfPicking}: Props) => { - console.log("item",item) - console.log("selfPicking",selfPicking) return (
    {item.cart_type === 'promotion' && ( diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 4b3f693c..a1491c7f 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -146,24 +146,20 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { )}
    - {product?.manufacture?.name ? ( -
    - -
    - {product.manufacture.name} -
    - +
    + {product?.manufacture?.name ? ( + + {product.manufacture.name} + + ) : ( +
    -
    + )} {product?.is_in_bu && ( -
    - - Click & Pickup - +
    + pickup now
    )} -
    - ) : ( -
    -
    - )} +
    Date: Tue, 20 Aug 2024 10:27:32 +0700 Subject: add new register --- src-migrate/modules/register/components/Form.tsx | 89 ++++---- .../modules/register/components/FormBisnis.tsx | 230 +++++++++++++++++++++ .../register/components/RegistrasiBisnis.tsx | 105 ++++++++++ .../register/components/RegistrasiIndividu.tsx | 11 + src-migrate/modules/register/index.tsx | 126 ++++++++--- .../modules/register/stores/useRegisterStore.ts | 1 + 6 files changed, 481 insertions(+), 81 deletions(-) create mode 100644 src-migrate/modules/register/components/FormBisnis.tsx create mode 100644 src-migrate/modules/register/components/RegistrasiBisnis.tsx create mode 100644 src-migrate/modules/register/components/RegistrasiIndividu.tsx diff --git a/src-migrate/modules/register/components/Form.tsx b/src-migrate/modules/register/components/Form.tsx index b834f97a..7d18f4ee 100644 --- a/src-migrate/modules/register/components/Form.tsx +++ b/src-migrate/modules/register/components/Form.tsx @@ -9,7 +9,12 @@ import { useRouter } from "next/router"; import { UseToastOptions, useToast } from "@chakra-ui/react"; import Link from "next/link"; -const Form = () => { +interface FormProps { + type: string; + required: boolean; +} + +const Form: React.FC = ({ type, required }) => { const { form, isCheckedTNC, @@ -75,25 +80,9 @@ const Form = () => { return ( -
    - - - -
    - + {
    - - - - - {!!errors.phone && {errors.phone}} -
    - -
    - + { {!!errors.email && {errors.email}}
    - +
    - + { {!!errors.password && {errors.password}}
    - +
    + + + + + {!!errors.phone && {errors.phone}} +
    + + {type==='individu' && ( + <> + + + + + + + )} - - ) } diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx new file mode 100644 index 00000000..85e37875 --- /dev/null +++ b/src-migrate/modules/register/components/FormBisnis.tsx @@ -0,0 +1,230 @@ +import { ChangeEvent, useMemo } from "react"; +import { useMutation } from "react-query"; +import { useRegisterStore } from "../stores/useRegisterStore"; +import { RegisterProps } from "~/types/auth"; +import { registerUser } from "~/services/auth"; +import { useRouter } from "next/router"; +import { UseToastOptions, useToast } from "@chakra-ui/react"; +import Link from "next/link"; +import getFileBase64 from '@/core/utils/getFileBase64' + +interface FormProps { + type: string; + required: boolean; +} + +const Form: React.FC = ({ type, required }) => { + const { + form, + isCheckedTNC, + isValidCaptcha, + errors, + updateForm, + validate, + } = useRegisterStore() + + const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) + + const router = useRouter() + const toast = useToast() + + const handleInputChange = (event: ChangeEvent) => { + const { name, value } = event.target; + updateForm(name, value) + validate() + } + + const handleFileChange = async (event: ChangeEvent) => { + let fileBase64 = '' + const file = event.target.files?.[0]; + if (file) { + if (typeof file !== 'undefined') { + if (file.size > 5000000) { + // toast.error('Maksimal ukuran file adalah 5MB') + return + } + fileBase64 = await getFileBase64(file) + } + updateForm("document", fileBase64); // Menyimpan file ke dalam form state + validate(); + } + } + + const mutation = useMutation({ + mutationFn: (data: RegisterProps) => registerUser(data) + }) + + const handleSubmit = async (e: ChangeEvent) => { + e.preventDefault() + + const response = await mutation.mutateAsync(form) + + if (response?.register === true) { + const urlParams = new URLSearchParams({ + activation: 'otp', + email: form.email, + redirect: (router.query?.next || '/') as string + }) + router.push(`${router.route}?${urlParams}`) + } + + const toastProps: UseToastOptions = { + duration: 5000, + isClosable: true + } + + switch (response?.reason) { + case 'EMAIL_USED': + toast({ + ...toastProps, + title: 'Email sudah digunakan', + status: 'warning' + }) + break; + case 'NOT_ACTIVE': + const activationUrl = `${router.route}?activation=email` + toast({ + ...toastProps, + title: 'Akun belum aktif', + description: <>Akun sudah terdaftar namun belum aktif. Klik untuk aktivasi akun, + status: 'warning' + }) + break + } + } + + + return ( +
    +
    + + + + + {!!errors.email && {errors.email}} +
    + +
    + +
    + + + +
    +
    + +
    + +
    + +
    + Kategori: Industri Otomotif, Bengkel, Car Wash +
    + +
    + + + + + {!!errors.name && {errors.name}} +
    + +
    + + + + + {!!errors.phone && {errors.phone}} +
    + +
    + + + + + {/* {!!errors.document && {errors.document}} */} +
    + +
    + + + + + {/* {!!errors.document && {errors.document}} */} +
    + + +
    + ) +} + +export default Form \ No newline at end of file diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx new file mode 100644 index 00000000..217b4c79 --- /dev/null +++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx @@ -0,0 +1,105 @@ +import { useState } from "react"; +import FormBisnis from "./FormBisnis"; +import Form from "./Form"; +import TermCondition from "./TermCondition"; +import FormCaptcha from "./FormCaptcha"; +import { Radio, RadioGroup, Stack, Divider } from '@chakra-ui/react' +import React from "react"; +import { + ChevronDownIcon, + ChevronRightIcon +} from '@heroicons/react/24/outline'; + +const RegistrasiBisnis = () => { + const [isPKP, setIsPKP] = useState(false); + const [isTerdaftar, setIsTerdaftar] = useState(false); + const [isIndividuRequired, setIsIndividuRequired] = useState(true); + const [isBisnisRequired, setIsBisnisRequired] = useState(true); + const [selectedValue, setSelectedValue] = useState('PKP'); + + const handleChange = (value: string) => { + setSelectedValue(value); + if (value === "PKP") { + setIsPKP(true); + setIsIndividuRequired(true); // Show and require Individu form + } else { + setIsPKP(false); + setIsIndividuRequired(false); // Hide and make optional the Individu form + } + }; + + const handleClick = () => { + setIsIndividuRequired(!isIndividuRequired) + }; + + const handleClickBisnis = () => { + setIsBisnisRequired(!isBisnisRequired) + }; + + return ( + <> +
    +

    Tipe Bisnis

    + + + PKP + Non-PKP + + +
    +
    +
    +
    +

    Data Akun

    + {isIndividuRequired ? ( +
    + +
    + ) : ( + + )} +
    + {isIndividuRequired && ( +
    + +
    +
    + )} +
    +
    +
    +
    +
    +

    Data Bisnis

    + {isBisnisRequired ? ( +
    + +
    + ) : ( + + )} +
    + {isBisnisRequired && ( +
    + +
    +

    Bisnis Terdaftar di Indoteknik?

    + + + Sudah Terdaftar + Belum Terdaftar + + +
    + +
    + )} +
    +
    + + + + ); +}; + +export default RegistrasiBisnis; diff --git a/src-migrate/modules/register/components/RegistrasiIndividu.tsx b/src-migrate/modules/register/components/RegistrasiIndividu.tsx new file mode 100644 index 00000000..eff86124 --- /dev/null +++ b/src-migrate/modules/register/components/RegistrasiIndividu.tsx @@ -0,0 +1,11 @@ +import Form from "./Form"; +const RegistrasiIndividu = () => { + + return ( + <> + + + ); +}; + +export default RegistrasiIndividu; diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx index 00931284..9b3f5509 100644 --- a/src-migrate/modules/register/index.tsx +++ b/src-migrate/modules/register/index.tsx @@ -1,43 +1,101 @@ -import PageContent from "~/modules/page-content" -import Form from "./components/Form" -import Link from "next/link" -import Image from "next/image" -import IndoteknikLogo from "~/images/logo.png" -import AccountActivation from "../account-activation" +import PageContent from "~/modules/page-content"; +import Form from "./components/Form"; +import RegistrasiIndividu from "./components/RegistrasiIndividu"; +import RegistrasiBisnis from "./components/RegistrasiBisnis"; +import FormBisnis from "./components/FormBisnis"; +import Link from "next/link"; +import Image from "next/image"; +import IndoteknikLogo from "~/images/logo.png"; +import AccountActivation from "../account-activation"; +import { useState } from "react"; const LOGO_WIDTH = 150; const LOGO_HEIGHT = LOGO_WIDTH / 3; const Register = () => { + const [isIndividuClicked, setIsIndividuClicked] = useState(true); + const [isBisnisClicked, setIsBisnisClicked] = useState(false); + + const handleIndividuClick = () => { + setIsIndividuClicked(true); + setIsBisnisClicked(false); + }; + + const handleBisnisClick = () => { + setIsIndividuClicked(false); + setIsBisnisClicked(true); + }; + return (
    -
    -
    - - Logo Indoteknik - - -

    - Daftar Akun Indoteknik -

    -

    - Buat akun sekarang lebih mudah dan terverifikasi -

    - - - -
    - Sudah punya akun Indoteknik?{' '} - - Masuk +
    +
    +
    + + Logo Indoteknik -
    -
    - Akun anda belum aktif?{' '} - - Aktivasi - +

    + Daftar Akun Indoteknik +

    +

    + Buat akun sekarang lebih mudah dan terverifikasi +

    + + +
    +
    +

    Individu

    +
    +
    +

    Bisnis

    +
    +
    +
    + {isIndividuClicked && ( +
    + +
    + )} + {isBisnisClicked && ( +
    + +
    + )} +
    +
    +
    + Sudah punya akun Indoteknik?{" "} + + Masuk + +
    +
    + Akun anda belum aktif?{" "} + + Aktivasi + +
    +
    @@ -48,7 +106,7 @@ const Register = () => {
    - ) -} + ); +}; -export default Register \ No newline at end of file +export default Register; diff --git a/src-migrate/modules/register/stores/useRegisterStore.ts b/src-migrate/modules/register/stores/useRegisterStore.ts index d8abf52b..1438ccc2 100644 --- a/src-migrate/modules/register/stores/useRegisterStore.ts +++ b/src-migrate/modules/register/stores/useRegisterStore.ts @@ -29,6 +29,7 @@ export const useRegisterStore = create((set, get) => ({ email: '', password: '', phone: '', + document: File, }, updateForm: (name, value) => set((state) => ({ form: { ...state.form, [name]: value } })), -- cgit v1.2.3 From cf0f7a934bcf256d1daeee98e9f66397fb64b1ee Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 20 Aug 2024 11:47:29 +0700 Subject: update new register --- .../modules/register/components/FormBisnis.tsx | 98 +++++++++++++++------- .../register/components/RegistrasiBisnis.tsx | 29 ++++++- src-migrate/modules/register/index.tsx | 4 +- 3 files changed, 96 insertions(+), 35 deletions(-) diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx index 85e37875..6f94748b 100644 --- a/src-migrate/modules/register/components/FormBisnis.tsx +++ b/src-migrate/modules/register/components/FormBisnis.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, useMemo } from "react"; +import { ChangeEvent, useEffect, useMemo, useState } from "react"; import { useMutation } from "react-query"; import { useRegisterStore } from "../stores/useRegisterStore"; import { RegisterProps } from "~/types/auth"; @@ -7,12 +7,21 @@ import { useRouter } from "next/router"; import { UseToastOptions, useToast } from "@chakra-ui/react"; import Link from "next/link"; import getFileBase64 from '@/core/utils/getFileBase64' +import { Controller, useForm } from 'react-hook-form' +import HookFormSelect from '@/core/components/elements/Select/HookFormSelect' +import odooApi from "~/libs/odooApi"; interface FormProps { type: string; required: boolean; } +interface Industry { + label: string; + value: string; + category: string; +} + const Form: React.FC = ({ type, required }) => { const { form, @@ -23,11 +32,42 @@ const Form: React.FC = ({ type, required }) => { validate, } = useRegisterStore() + const { control, watch, setValue } = useForm(); + const [selectedCategory, setSelectedCategory] = useState(''); + + const [industries, setIndustries] = useState([]); + const [companyTypes, setCompanyTypes] = useState([]) const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) const router = useRouter() const toast = useToast() + useEffect(() => { + const loadCompanyTypes = async () => { + const dataCompanyTypes = await odooApi('GET', '/api/v1/partner/company_type') + setCompanyTypes(dataCompanyTypes?.map((o: { id: any; name: any; }) => ({ value: o.id, label: o.name }))) + } + loadCompanyTypes() + }, []) + + useEffect(() => { + const loadIndustries = async () => { + const dataIndustries = await odooApi('GET', '/api/v1/partner/industry') + setIndustries(dataIndustries?.map((o: { id: any; name: any; category:any; }) => ({ value: o.id, label: o.name, category:o.category }))) + } + loadIndustries() + }, []) + + const selectedIndustry = watch('industry'); + + useEffect(() => { + const selected = industries.find(industry => industry.value === selectedIndustry); + if (selected) { + setSelectedCategory(selected.category); + } + }, [selectedIndustry, industries]); + + const handleInputChange = (event: ChangeEvent) => { const { name, value } = event.target; updateForm(name, value) @@ -93,7 +133,6 @@ const Form: React.FC = ({ type, required }) => { } } - return (
    @@ -119,37 +158,36 @@ const Form: React.FC = ({ type, required }) => { Nama Bisnis (opsional)
    - - - -
    +
    + } + /> +
    + +
    -
    +
    -
    - -
    - Kategori: Industri Otomotif, Bengkel, Car Wash + } + /> + Kategori : {selectedCategory}
    @@ -216,13 +254,13 @@ const Form: React.FC = ({ type, required }) => { {/* {!!errors.document && {errors.document}} */}
    - + */} ) } diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx index 217b4c79..c093d556 100644 --- a/src-migrate/modules/register/components/RegistrasiBisnis.tsx +++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useMemo, useState } from "react"; import FormBisnis from "./FormBisnis"; import Form from "./Form"; import TermCondition from "./TermCondition"; @@ -9,6 +9,10 @@ import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/24/outline'; +import { useRegisterStore } from "../stores/useRegisterStore"; +import { useMutation } from "react-query"; +import { RegisterProps } from "~/types/auth"; +import { registerUser } from "~/services/auth"; const RegistrasiBisnis = () => { const [isPKP, setIsPKP] = useState(false); @@ -16,6 +20,18 @@ const RegistrasiBisnis = () => { const [isIndividuRequired, setIsIndividuRequired] = useState(true); const [isBisnisRequired, setIsBisnisRequired] = useState(true); const [selectedValue, setSelectedValue] = useState('PKP'); + const { + form, + isCheckedTNC, + isValidCaptcha, + errors, + updateForm, + validate, + } = useRegisterStore() + const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) + const mutation = useMutation({ + mutationFn: (data: RegisterProps) => registerUser(data) + }) const handleChange = (value: string) => { setSelectedValue(value); @@ -38,8 +54,8 @@ const RegistrasiBisnis = () => { return ( <> -
    -

    Tipe Bisnis

    +
    +

    Tipe Bisnis

    PKP @@ -98,6 +114,13 @@ const RegistrasiBisnis = () => {
    + ); }; diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx index 9b3f5509..e89a6de3 100644 --- a/src-migrate/modules/register/index.tsx +++ b/src-migrate/modules/register/index.tsx @@ -45,14 +45,14 @@ const Register = () => {

    Daftar Akun Indoteknik

    -

    +

    Buat akun sekarang lebih mudah dan terverifikasi

    -
    +
    Date: Tue, 20 Aug 2024 15:21:31 +0700 Subject: update new register --- .../modules/register/components/FormBisnis.tsx | 135 ++++++++++----------- .../register/components/RegistrasiBisnis.tsx | 25 +++- .../modules/register/stores/useRegisterStore.ts | 30 +++++ 3 files changed, 120 insertions(+), 70 deletions(-) diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx index 6f94748b..72921c2b 100644 --- a/src-migrate/modules/register/components/FormBisnis.tsx +++ b/src-migrate/modules/register/components/FormBisnis.tsx @@ -22,41 +22,41 @@ interface Industry { category: string; } -const Form: React.FC = ({ type, required }) => { +const FormBisnis: React.FC = ({ type, required }) => { const { - form, + formBisnis, isCheckedTNC, isValidCaptcha, errors, - updateForm, - validate, + updateFormBisnis, + validateFormBisnis, } = useRegisterStore() const { control, watch, setValue } = useForm(); const [selectedCategory, setSelectedCategory] = useState(''); const [industries, setIndustries] = useState([]); - const [companyTypes, setCompanyTypes] = useState([]) - const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]) + const [companyTypes, setCompanyTypes] = useState([]); + const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]); - const router = useRouter() - const toast = useToast() + const router = useRouter(); + const toast = useToast(); useEffect(() => { const loadCompanyTypes = async () => { - const dataCompanyTypes = await odooApi('GET', '/api/v1/partner/company_type') - setCompanyTypes(dataCompanyTypes?.map((o: { id: any; name: any; }) => ({ value: o.id, label: o.name }))) - } - loadCompanyTypes() - }, []) + const dataCompanyTypes = await odooApi('GET', '/api/v1/partner/company_type'); + setCompanyTypes(dataCompanyTypes?.map((o: { id: any; name: any; }) => ({ value: o.id, label: o.name }))); + }; + loadCompanyTypes(); + }, []); useEffect(() => { const loadIndustries = async () => { - const dataIndustries = await odooApi('GET', '/api/v1/partner/industry') - setIndustries(dataIndustries?.map((o: { id: any; name: any; category:any; }) => ({ value: o.id, label: o.name, category:o.category }))) - } - loadIndustries() - }, []) + const dataIndustries = await odooApi('GET', '/api/v1/partner/industry'); + setIndustries(dataIndustries?.map((o: { id: any; name: any; category: any; }) => ({ value: o.id, label: o.name, category: o.category }))); + }; + loadIndustries(); + }, []); const selectedIndustry = watch('industry'); @@ -67,51 +67,50 @@ const Form: React.FC = ({ type, required }) => { } }, [selectedIndustry, industries]); - const handleInputChange = (event: ChangeEvent) => { const { name, value } = event.target; - updateForm(name, value) - validate() - } + updateFormBisnis(name, value); + validateFormBisnis(); + }; const handleFileChange = async (event: ChangeEvent) => { - let fileBase64 = '' + let fileBase64 = ''; const file = event.target.files?.[0]; if (file) { if (typeof file !== 'undefined') { if (file.size > 5000000) { // toast.error('Maksimal ukuran file adalah 5MB') - return + return; } - fileBase64 = await getFileBase64(file) + fileBase64 = await getFileBase64(file); } - updateForm("document", fileBase64); // Menyimpan file ke dalam form state - validate(); + updateFormBisnis("document", fileBase64); // Menyimpan file ke dalam formBisnis state + validateFormBisnis(); } - } + }; const mutation = useMutation({ mutationFn: (data: RegisterProps) => registerUser(data) - }) + }); const handleSubmit = async (e: ChangeEvent) => { - e.preventDefault() + e.preventDefault(); - const response = await mutation.mutateAsync(form) + const response = await mutation.mutateAsync(formBisnis); if (response?.register === true) { const urlParams = new URLSearchParams({ activation: 'otp', - email: form.email, + email: formBisnis.email, redirect: (router.query?.next || '/') as string - }) - router.push(`${router.route}?${urlParams}`) + }); + router.push(`${router.route}?${urlParams}`); } const toastProps: UseToastOptions = { duration: 5000, isClosable: true - } + }; switch (response?.reason) { case 'EMAIL_USED': @@ -119,19 +118,19 @@ const Form: React.FC = ({ type, required }) => { ...toastProps, title: 'Email sudah digunakan', status: 'warning' - }) + }); break; case 'NOT_ACTIVE': - const activationUrl = `${router.route}?activation=email` + const activationUrl = `${router.route}?activation=email`; toast({ ...toastProps, title: 'Akun belum aktif', description: <>Akun sudah terdaftar namun belum aktif. Klik untuk aktivasi akun, status: 'warning' - }) - break + }); + break; } - } + }; return (
    @@ -144,7 +143,7 @@ const Form: React.FC = ({ type, required }) => { name='email' className='form-input mt-3' placeholder='example@email.com' - value={form.email} + value={formBisnis.email} onChange={handleInputChange} autoComplete="username" aria-invalid={!!errors.email} @@ -158,36 +157,36 @@ const Form: React.FC = ({ type, required }) => { Nama Bisnis (opsional)
    -
    - } - /> -
    - -
    +
    + } + /> +
    + +
    - } - /> - Kategori : {selectedCategory} + } + /> + Kategori : {selectedCategory}
    @@ -199,7 +198,7 @@ const Form: React.FC = ({ type, required }) => { name='name' className='form-input mt-3' placeholder='Masukan nama lengkap anda' - value={form.name} + value={formBisnis.name} onChange={handleInputChange} aria-invalid={!!errors.name} /> @@ -216,7 +215,7 @@ const Form: React.FC = ({ type, required }) => { name='phone' className='form-input mt-3' placeholder='08xxxxxxxx' - value={form.phone} + value={formBisnis.phone} onChange={handleInputChange} aria-invalid={!!errors.phone} /> @@ -265,4 +264,4 @@ const Form: React.FC = ({ type, required }) => { ) } -export default Form \ No newline at end of file +export default FormBisnis; diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx index c093d556..2c429f2d 100644 --- a/src-migrate/modules/register/components/RegistrasiBisnis.tsx +++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx @@ -20,8 +20,10 @@ const RegistrasiBisnis = () => { const [isIndividuRequired, setIsIndividuRequired] = useState(true); const [isBisnisRequired, setIsBisnisRequired] = useState(true); const [selectedValue, setSelectedValue] = useState('PKP'); + const [selectedValueBisnis, setSelectedValueBisnis] = useState('true'); const { form, + formBisnis, isCheckedTNC, isValidCaptcha, errors, @@ -44,6 +46,15 @@ const RegistrasiBisnis = () => { } }; + const handleChangeBisnis = (value: string) => { + setSelectedValueBisnis(value); + if (value === "true") { + setIsBisnisRequired(true); // Show and require Individu form + } else { + setIsBisnisRequired(false); // Hide and make optional the Individu form + } + }; + const handleClick = () => { setIsIndividuRequired(!isIndividuRequired) }; @@ -52,6 +63,15 @@ const RegistrasiBisnis = () => { setIsBisnisRequired(!isBisnisRequired) }; + const handleSubmit = () => { + console.log("form",form) + console.log("form Bisnis",formBisnis) + }; + console.log("isFormValid",isFormValid) + console.log("isCheckedTNC",isCheckedTNC) + console.log("mutation.isLoading",mutation.isLoading) + console.log("isValidCaptcha",isValidCaptcha) + return ( <>
    @@ -100,7 +120,7 @@ const RegistrasiBisnis = () => {

    Bisnis Terdaftar di Indoteknik?

    - + Sudah Terdaftar Belum Terdaftar @@ -112,15 +132,16 @@ const RegistrasiBisnis = () => { )}
    - + ); }; diff --git a/src-migrate/modules/register/stores/useRegisterStore.ts b/src-migrate/modules/register/stores/useRegisterStore.ts index 1438ccc2..19a055ae 100644 --- a/src-migrate/modules/register/stores/useRegisterStore.ts +++ b/src-migrate/modules/register/stores/useRegisterStore.ts @@ -5,6 +5,7 @@ import { ZodError } from 'zod'; type State = { form: RegisterProps; + formBisnis: RegisterProps; errors: { [key in keyof RegisterProps]?: string; }; @@ -15,11 +16,13 @@ type State = { type Action = { updateForm: (name: string, value: string) => void; + updateFormBisnis: (name: string, value: string) => void; updateValidCaptcha: (value: boolean) => void; toggleCheckTNC: () => void; openTNC: () => void; closeTNC: () => void; validate: () => void; + validateFormBisnis: () => void; }; export const useRegisterStore = create((set, get) => ({ @@ -31,8 +34,19 @@ export const useRegisterStore = create((set, get) => ({ phone: '', document: File, }, + formBisnis: { + company: '', + name: '', + email: '', + password: '', + phone: '', + document: File, + }, updateForm: (name, value) => set((state) => ({ form: { ...state.form, [name]: value } })), + + updateFormBisnis: (name, value) => + set((state) => ({ formBisnis: { ...state.formBisnis, [name]: value } })), errors: {}, validate: () => { @@ -49,6 +63,22 @@ export const useRegisterStore = create((set, get) => ({ } } }, + + validateFormBisnis: () => { + try { + registerSchema.parse(get().formBisnis); + set({ errors: {} }); + } catch (error) { + if (error instanceof ZodError) { + const errors: State['errors'] = {}; + error.errors.forEach( + (e) => (errors[e.path[0] as keyof RegisterProps] = e.message) + ); + set({ errors }); + } + } + }, + isCheckedTNC: false, toggleCheckTNC: () => set((state) => ({ isCheckedTNC: !state.isCheckedTNC })), -- cgit v1.2.3 From 0427b70917d7623d5de1969b99e9c198c38ccca7 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 20 Aug 2024 15:53:01 +0700 Subject: = ({ type, required }) => { {type==='individu' && ( <> - + {/* */}
    +

    + - ); }; diff --git a/src-migrate/modules/register/stores/useRegisterStore.ts b/src-migrate/modules/register/stores/useRegisterStore.ts index 19a055ae..5312bd6c 100644 --- a/src-migrate/modules/register/stores/useRegisterStore.ts +++ b/src-migrate/modules/register/stores/useRegisterStore.ts @@ -32,7 +32,12 @@ export const useRegisterStore = create((set, get) => ({ email: '', password: '', phone: '', - document: File, + document: '', + nameWajibPajak: '', + industry: '', + badanUsaha: '', + jenisUsaha: '', + npwp: '' }, formBisnis: { company: '', @@ -40,7 +45,12 @@ export const useRegisterStore = create((set, get) => ({ email: '', password: '', phone: '', - document: File, + document: '', + nameWajibPajak: '', + industry: '', + badanUsaha: '', + jenisUsaha: '', + npwp: '' }, updateForm: (name, value) => set((state) => ({ form: { ...state.form, [name]: value } })), diff --git a/src-migrate/validations/auth.ts b/src-migrate/validations/auth.ts index 78fc5e71..166fd926 100644 --- a/src-migrate/validations/auth.ts +++ b/src-migrate/validations/auth.ts @@ -2,6 +2,11 @@ import { z } from 'zod'; export const registerSchema = z.object({ name: z.string().min(1, { message: 'Nama harus diisi' }), + document: z.string().min(1, { message: 'Nama harus diisi' }), + nameWajibPajak: z.string().min(1, { message: 'Nama wajib pajak harus diisi' }), + industry: z.string().min(1, { message: 'industri harus diisi' }), + badanUsaha: z.string().min(1, { message: 'badan usaha harus dipilih' }), + jenisUsaha: z.string().min(1, { message: 'jenis usaha harus dipilih' }), email: z .string() .min(1, { message: 'Email harus diisi' }) @@ -14,4 +19,10 @@ export const registerSchema = z.object({ .refine((val) => /^\d{10,12}$/.test(val), { message: 'Format nomor telepon tidak valid, contoh: 081234567890', }), + npwp: z + .string() + .min(1, { message: 'NPWP harus diisi' }) + .refine((val) => /^\d{10,12}$/.test(val), { + message: 'Format nomor telepon tidak valid, contoh: 081234567890', + }), }); -- cgit v1.2.3 From 7e26430c7e808c167a330fc2cd4ce217f288757c Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 20 Aug 2024 16:29:22 +0700 Subject: delete border brand homepage --- src/lib/home/components/PreferredBrand.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/home/components/PreferredBrand.jsx b/src/lib/home/components/PreferredBrand.jsx index fdefb526..56268db7 100644 --- a/src/lib/home/components/PreferredBrand.jsx +++ b/src/lib/home/components/PreferredBrand.jsx @@ -71,7 +71,7 @@ const PreferredBrand = () => { )}
    -
    +
    {manufactures.isLoading && } {!manufactures.isLoading && ( -- cgit v1.2.3 From 16db179d5bb5ebd3ce946fb6e682539ffc8f728e Mon Sep 17 00:00:00 2001 From: Imanuel Marinao Date: Tue, 20 Aug 2024 20:40:32 +0700 Subject: update avoid error --- src/core/components/elements/Navbar/TopBanner.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/components/elements/Navbar/TopBanner.jsx b/src/core/components/elements/Navbar/TopBanner.jsx index 5ea8f635..f438ae67 100644 --- a/src/core/components/elements/Navbar/TopBanner.jsx +++ b/src/core/components/elements/Navbar/TopBanner.jsx @@ -6,7 +6,7 @@ import Link from '../Link/Link'; import { background } from '@chakra-ui/react'; import { useEffect } from 'react'; -const TopBanner = ({ onLoad }) => { +const TopBanner = ({ onLoad = () => {} }) => { const { isDesktop, isMobile } = useDevice() const topBanner = useQuery({ queryKey: 'topBanner', -- cgit v1.2.3 From 2f106583f644e29019828a9e8ed82e23c7c67d0a Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 21 Aug 2024 10:01:27 +0700 Subject: update view new register --- .../modules/register/components/FormBisnis.tsx | 21 ++++++----- .../register/components/RegistrasiBisnis.tsx | 44 ++++++++++++---------- .../modules/register/components/TermCondition.tsx | 2 +- src-migrate/modules/register/index.tsx | 2 +- .../modules/register/stores/useRegisterStore.ts | 2 + 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx index 72921c2b..7b301dc5 100644 --- a/src-migrate/modules/register/components/FormBisnis.tsx +++ b/src-migrate/modules/register/components/FormBisnis.tsx @@ -59,15 +59,16 @@ const FormBisnis: React.FC = ({ type, required }) => { }, []); const selectedIndustry = watch('industry'); - useEffect(() => { const selected = industries.find(industry => industry.value === selectedIndustry); + console.log("selected",selected) if (selected) { setSelectedCategory(selected.category); } }, [selectedIndustry, industries]); const handleInputChange = (event: ChangeEvent) => { + console.log("event",event) const { name, value } = event.target; updateFormBisnis(name, value); validateFormBisnis(); @@ -135,7 +136,7 @@ const FormBisnis: React.FC = ({ type, required }) => { return (
    - + = ({ type, required }) => {
    -