From f99e0aba70efad0deb907d8e27f09fc9f527c8a4 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 17 Feb 2023 17:07:50 +0700 Subject: Refactor --- src/lib/product/components/Product.jsx | 276 +++++++++++++++++++++ src/lib/product/components/ProductCard.jsx | 68 +++++ src/lib/product/components/ProductFilter.jsx | 131 ++++++++++ src/lib/product/components/ProductSearch.jsx | 95 +++++++ src/lib/product/components/ProductSimilar.jsx | 15 ++ src/lib/product/components/ProductSlider.jsx | 51 ++++ .../components/Skeleton/ProductSearchSkeleton.jsx | 14 ++ 7 files changed, 650 insertions(+) create mode 100644 src/lib/product/components/Product.jsx create mode 100644 src/lib/product/components/ProductCard.jsx create mode 100644 src/lib/product/components/ProductFilter.jsx create mode 100644 src/lib/product/components/ProductSearch.jsx create mode 100644 src/lib/product/components/ProductSimilar.jsx create mode 100644 src/lib/product/components/ProductSlider.jsx create mode 100644 src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx new file mode 100644 index 00000000..2a3624e7 --- /dev/null +++ b/src/lib/product/components/Product.jsx @@ -0,0 +1,276 @@ +import Badge from "@/core/components/elements/Badge/Badge" +import Divider from "@/core/components/elements/Divider/Divider" +import Image from "@/core/components/elements/Image/Image" +import Link from "@/core/components/elements/Link/Link" +import currencyFormat from "@/core/utils/currencyFormat" +import { useEffect, useState } from "react" +import Select from "react-select" +import ProductSimilar from "./ProductSimilar" +import LazyLoad from "react-lazy-load" +import { toast } from "react-hot-toast" +import { addItemCart } from "@/core/utils/cart" + +const informationTabOptions = [ + { value: 'specification', label: 'Spesifikasi' }, + { value: 'description', label: 'Deskripsi' }, + { value: 'important', label: 'Info Penting' }, +] + +const Product = ({ product }) => { + const [ quantity, setQuantity ] = useState('1') + const [ selectedVariant, setSelectedVariant ] = useState(null) + const [ informationTab, setInformationTab ] = useState(null) + + const [ activeVariant, setActiveVariant ] = useState({ + id: product.id, + code: product.code, + name: product.name, + price: product.lowestPrice, + stock: product.stockTotal, + weight: product.weight, + }) + + const variantOptions = product.variants?.map((variant) => ({ + value: variant.id, + label: + (variant.code ? `[${variant.code}] ` : '') + + + (variant.attributes.length > 0 ? variant.attributes.join(', ') : product.name) + })) + + useEffect(() => { + if (!selectedVariant && variantOptions.length == 1) { + setSelectedVariant(variantOptions[0]) + } + }, [selectedVariant, variantOptions]) + + useEffect(() => { + if (selectedVariant) { + const variant = product.variants.find(variant => variant.id == selectedVariant.value) + const variantAttributes = variant.attributes.length > 0 ? ' - ' + variant.attributes.join(', ') : '' + console.log(variant); + setActiveVariant({ + id: variant.id, + code: variant.code, + name: variant.parent.name + variantAttributes, + price: variant.price, + stock: variant.stock, + weight: variant.weight + }) + } + }, [selectedVariant, product]) + + useEffect(() => { + if (!informationTab) { + setInformationTab(informationTabOptions[0].value) + } + }, [informationTab]) + + const handleClickCart = () => { + if (!selectedVariant) { + toast.error('Pilih varian terlebih dahulu') + return + } + if (!quantity || quantity < 1 || isNaN(parseInt(quantity))) { + toast.error('Jumlah barang minimal 1') + return + } + addItemCart({ + productId: activeVariant.id, + quantity + }) + toast.success('Berhasil menambahkan ke keranjang') + } + + return ( + <> + {product.name} + +
+ { product.manufacture?.name } +

+ {activeVariant?.name} +

+ { activeVariant?.price?.discountPercentage > 0 && ( +
+
+ {currencyFormat(activeVariant?.price?.priceDiscount)} +
+ + {activeVariant?.price?.discountPercentage}% + +
+ ) } +

+ { activeVariant?.price?.price > 0 ? currencyFormat(activeVariant?.price?.price) : ( + + Hubungi kami untuk dapatkan harga terbaik,  + klik disini + + ) } +

+
+ + + +
+
+ + setQuantity(e.target.value)} + /> +
+ + +
+ + + + +
+

Informasi Produk

+
+ { informationTabOptions.map((option) => ( + setInformationTab(option.value)} + > + {option.label} + + )) } +
+ + + + {product?.variantTotal} Varian + + + SKU-{product?.id} + + + {activeVariant?.code || '-'} + + + { activeVariant?.stock > 0 && ( + +
Ready Stock
+
+ { activeVariant?.stock > 5 ? '> 5' : '< 5' } +
+
+ ) } + { activeVariant?.stock == 0 && ( + + Tanya Stok + + ) } +
+ + { activeVariant?.weight > 0 && ( + { activeVariant?.weight } KG + ) } + { activeVariant?.weight == 0 && ( + + Tanya Berat + + ) } + +
+ + +
+ + + +
+

Kamu Mungkin Juga Suka

+ + + +
+ + ) +} + +const TabButton = ({ children, active, ...props }) => { + const activeClassName = active ? 'text-red_r-11 border-b border-red_r-11' : 'text-gray_r-11' + return ( + + ) +} + +const TabContent = ({ children, active, className, ...props }) => ( +
+ { children } +
+) + +const SpecificationContent = ({ children, label }) => ( +
+ { label } + { children } +
+) + +export default Product \ No newline at end of file diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx new file mode 100644 index 00000000..86ac3a64 --- /dev/null +++ b/src/lib/product/components/ProductCard.jsx @@ -0,0 +1,68 @@ +import Image from "@/core/components/elements/Image/Image" +import Link from "@/core/components/elements/Link/Link" +import currencyFormat from "@/core/utils/currencyFormat" +import { createSlug } from "@/core/utils/slug" + +const ProductCard = ({ product, simpleTitle }) => { + return ( + <> +
+ + {product?.name} + { product.variantTotal > 1 && ( +
{ product.variantTotal } Varian
+ ) } + +
+ + {product?.manufacture?.name} + + + {product?.name} + + { product?.lowestPrice?.discountPercentage > 0 && ( +
+
+ {currencyFormat(product?.lowestPrice?.price)} +
+
+ {product?.lowestPrice?.discountPercentage}% +
+
+ ) } + +
+ { product?.lowestPrice?.priceDiscount > 0 ? currencyFormat(product?.lowestPrice?.priceDiscount) : ( + Call for price + ) } +
+ { product?.stockTotal > 0 && ( +
+
+ Ready Stock +
+
+ { product?.stockTotal > 5 ? '> 5' : '< 5' } +
+
+ ) } +
+
+ + ) +} + +export default ProductCard \ No newline at end of file diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx new file mode 100644 index 00000000..023b6a8b --- /dev/null +++ b/src/lib/product/components/ProductFilter.jsx @@ -0,0 +1,131 @@ +import BottomPopup from "@/core/components/elements/Popup/BottomPopup" +import { useRouter } from "next/router" +import { useState } from "react" +import _ from "lodash" +import { toQuery } from "lodash-contrib" + +const orderOptions = [ + { value: 'price-asc', label: 'Harga Terendah' }, + { value: 'price-desc', label: 'Harga Tertinggi' }, + { value: 'popular', label: 'Populer' }, + { value: 'stock', label: 'Ready Stock' }, +] + +const ProductFilter = ({ + active, + close, + brands, + categories, + prefixUrl, + defaultBrand = null +}) => { + const router = useRouter() + const { query } = router + const [ order, setOrder ] = useState(query?.orderBy) + const [ brand, setBrand ] = useState(query?.brand) + const [ category, setCategory ] = useState(query?.category) + const [ priceFrom, setPriceFrom ] = useState(query?.priceFrom) + const [ priceTo, setPriceTo ] = useState(query?.priceTo) + + const handleSubmit = () => { + let params = { + q: router.query.q, + orderBy: order, + brand, + category, + priceFrom, + priceTo + } + params = _.pickBy(params, _.identity) + params = toQuery(params) + router.push(`${prefixUrl}?${params}`) + } + + return ( + +
+ { !defaultBrand && ( +
+ + +
+ ) } +
+ + +
+
+ +
+ { orderOptions.map((orderOption) => ( + + )) } +
+
+
+ +
+ setPriceFrom(e.target.value)} + /> + + setPriceTo(e.target.value)} + /> +
+
+ +
+
+ ) +} + +export default ProductFilter \ No newline at end of file diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx new file mode 100644 index 00000000..14df9864 --- /dev/null +++ b/src/lib/product/components/ProductSearch.jsx @@ -0,0 +1,95 @@ +import { useEffect, useState } from "react" +import useProductSearch from "../hooks/useProductSearch" +import ProductCard from "./ProductCard" +import Pagination from "@/core/components/elements/Pagination/Pagination" +import { toQuery } from "lodash-contrib" +import _ from "lodash" +import ProductSearchSkeleton from "./Skeleton/ProductSearchSkeleton" +import ProductFilter from "./ProductFilter" +import useActive from "@/core/hooks/useActive" + +const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { + const { page = 1 } = query + if (defaultBrand) query.brand = defaultBrand.toLowerCase() + const { productSearch } = useProductSearch({ query }) + const [ products, setProducts ] = useState(null) + const popup = useActive() + + const pageCount = Math.ceil(productSearch.data?.response.numFound / productSearch.data?.responseHeader.params.rows) + const productStart = productSearch.data?.responseHeader.params.start + const productRows = productSearch.data?.responseHeader.params.rows + const productFound = productSearch.data?.response.numFound + + const brands = productSearch.data?.facetCounts?.facetFields?.brandStr?.filter((value, index) => { + if (index % 2 === 0) { + return true + } + }) + const categories = productSearch.data?.facetCounts?.facetFields?.categoryNameStr?.filter((value, index) => { + if (index % 2 === 0) { + return true + } + }) + + useEffect(() => { + if (!products) { + setProducts(productSearch.data?.response?.products) + } + }, [query, products, productSearch]) + + if (productSearch.isLoading) { + return + } + + return ( +
+

Produk

+ +
+ { productFound > 0 ? ( + <> + Menampilkan  + {pageCount > 1 ? ( + <> + {productStart + 1}-{ + (productStart + productRows) > productFound ? productFound : productStart + productRows + } +  dari  + + ) : ''} + { productFound } +  produk { query.q && (<>untuk pencarian { query.q }) } + + ) : 'Mungkin yang anda cari'} +
+ + + +
+ { products && products.map((product) => ( + + )) } +
+ + + + +
+ ) +} + +export default ProductSearch \ No newline at end of file diff --git a/src/lib/product/components/ProductSimilar.jsx b/src/lib/product/components/ProductSimilar.jsx new file mode 100644 index 00000000..89cab536 --- /dev/null +++ b/src/lib/product/components/ProductSimilar.jsx @@ -0,0 +1,15 @@ +import PopularProductSkeleton from "@/lib/home/components/Skeleton/PopularProductSkeleton" +import useProductSimilar from "../hooks/useProductSimilar" +import ProductSlider from "./ProductSlider" + +const ProductSimilar = ({ query }) => { + const { productSimilar } = useProductSimilar({ query }) + + if (productSimilar.isLoading) { + return + } + + return +} + +export default ProductSimilar \ No newline at end of file diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx new file mode 100644 index 00000000..8d677547 --- /dev/null +++ b/src/lib/product/components/ProductSlider.jsx @@ -0,0 +1,51 @@ +import { Swiper, SwiperSlide } from "swiper/react" +import ProductCard from "./ProductCard" +import "swiper/css" +import Image from "@/core/components/elements/Image/Image" +import Link from "@/core/components/elements/Link/Link" +import { useState } from "react" + +const bannerClassName = 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' + +const ProductSlider = ({ + products, + simpleTitle = false, + bannerMode = false +}) => { + const [ activeIndex, setActiveIndex ] = useState(0) + const swiperSliderFirstMove = (swiper) => { + setActiveIndex(swiper.activeIndex) + } + + return ( + <> + { bannerMode && ( + {products.banner.name} 0 ? 'opacity-0' : 'opacity-100'}`} + /> + ) } + + { bannerMode && ( + + + + ) } + { products?.products?.map((product, index) => ( + + + + )) } + + + ) +} + +export default ProductSlider \ No newline at end of file diff --git a/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx b/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx new file mode 100644 index 00000000..e51a565c --- /dev/null +++ b/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx @@ -0,0 +1,14 @@ +import ProductCardSkeleton from "@/core/components/elements/Skeleton/ProductCardSkeleton" + +const ProductSearchSkeleton = () => ( +
+ + + + + + +
+) + +export default ProductSearchSkeleton \ No newline at end of file -- cgit v1.2.3 From 69f55de26319e570ce0a8c4dbe8a29cb0d0b51c5 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Sat, 18 Feb 2023 22:03:55 +0700 Subject: optimization --- src/lib/product/components/Product.jsx | 2 +- src/lib/product/components/ProductCard.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 2a3624e7..299cdc77 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -87,7 +87,7 @@ const Product = ({ product }) => { {product.name}
diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 86ac3a64..9eb00ae0 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -14,7 +14,7 @@ const ProductCard = ({ product, simpleTitle }) => { {product?.name} { product.variantTotal > 1 && (
{ product.variantTotal } Varian
-- cgit v1.2.3 From 75767ed41d28947429f3dbef9c7e128ebc552e64 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Sat, 18 Feb 2023 22:18:46 +0700 Subject: change animation --- src/lib/product/components/Product.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 299cdc77..396eba5f 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -48,7 +48,7 @@ const Product = ({ product }) => { if (selectedVariant) { const variant = product.variants.find(variant => variant.id == selectedVariant.value) const variantAttributes = variant.attributes.length > 0 ? ' - ' + variant.attributes.join(', ') : '' - console.log(variant); + setActiveVariant({ id: variant.id, code: variant.code, -- cgit v1.2.3 From d22df6bd30b8ed4bcfa938dcbbedc5fc376c2304 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 20 Feb 2023 10:49:35 +0700 Subject: cart refactor --- src/lib/product/components/Product.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 396eba5f..39d29d4d 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -8,7 +8,7 @@ import Select from "react-select" import ProductSimilar from "./ProductSimilar" import LazyLoad from "react-lazy-load" import { toast } from "react-hot-toast" -import { addItemCart } from "@/core/utils/cart" +import { updateItemCart } from "@/core/utils/cart" const informationTabOptions = [ { value: 'specification', label: 'Spesifikasi' }, @@ -75,7 +75,7 @@ const Product = ({ product }) => { toast.error('Jumlah barang minimal 1') return } - addItemCart({ + updateItemCart({ productId: activeVariant.id, quantity }) @@ -98,7 +98,7 @@ const Product = ({ product }) => { { activeVariant?.price?.discountPercentage > 0 && (
- {currencyFormat(activeVariant?.price?.priceDiscount)} + {currencyFormat(activeVariant?.price?.price)}
{activeVariant?.price?.discountPercentage}% @@ -106,7 +106,7 @@ const Product = ({ product }) => {
) }

- { activeVariant?.price?.price > 0 ? currencyFormat(activeVariant?.price?.price) : ( + { activeVariant?.price?.priceDiscount > 0 ? currencyFormat(activeVariant?.price?.priceDiscount) : ( Hubungi kami untuk dapatkan harga terbaik,  klik disini -- cgit v1.2.3 From 525166e62b793b351d1a6be2421c0a33b22f7b7b Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 20 Feb 2023 11:35:25 +0700 Subject: cart refactor --- src/lib/product/components/Product.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 39d29d4d..92f4e37d 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -245,7 +245,7 @@ const Product = ({ product }) => { } const TabButton = ({ children, active, ...props }) => { - const activeClassName = active ? 'text-red_r-11 border-b border-red_r-11' : 'text-gray_r-11' + const activeClassName = active ? 'text-red_r-11 underline underline-offset-4' : 'text-gray_r-11' return ( -

@@ -164,78 +157,70 @@ const Product = ({ product }) => { -
-

Informasi Produk

-
- { informationTabOptions.map((option) => ( - +

Informasi Produk

+
+ {informationTabOptions.map((option) => ( + setInformationTab(option.value)} > {option.label} - )) } + ))}
- - + {product?.variantTotal} Varian - + SKU-{product?.id} - + {activeVariant?.code || '-'} - - - { activeVariant?.stock > 0 && ( - -
Ready Stock
-
- { activeVariant?.stock > 5 ? '> 5' : '< 5' } -
+
+ + {activeVariant?.stock > 0 && ( + +
Ready Stock
+
{activeVariant?.stock > 5 ? '> 5' : '< 5'}
- ) } - { activeVariant?.stock == 0 && ( - + )} + {activeVariant?.stock == 0 && ( + Tanya Stok - ) } -
- - { activeVariant?.weight > 0 && ( - { activeVariant?.weight } KG - ) } - { activeVariant?.weight == 0 && ( - + )} + + + {activeVariant?.weight > 0 && {activeVariant?.weight} KG} + {activeVariant?.weight == 0 && ( + Tanya Berat - ) } -
+ )} +
-
-

Kamu Mungkin Juga Suka

+
+

Kamu Mungkin Juga Suka

@@ -247,30 +232,23 @@ const Product = ({ product }) => { const TabButton = ({ children, active, ...props }) => { const activeClassName = active ? 'text-red_r-11 underline underline-offset-4' : 'text-gray_r-11' return ( - ) } const TabContent = ({ children, active, className, ...props }) => ( -
- { children } +
+ {children}
) const SpecificationContent = ({ children, label }) => ( -
- { label } - { children } +
+ {label} + {children}
) -export default Product \ No newline at end of file +export default Product diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 9eb00ae0..8a2f1d7f 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -1,68 +1,68 @@ -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import currencyFormat from "@/core/utils/currencyFormat" -import { createSlug } from "@/core/utils/slug" +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import currencyFormat from '@/core/utils/currencyFormat' +import { createSlug } from '@/core/utils/slug' const ProductCard = ({ product, simpleTitle }) => { return ( <> -
- + - {product?.name} - { product.variantTotal > 1 && ( -
{ product.variantTotal } Varian
- ) } + {product.variantTotal > 1 && ( +
+ {product.variantTotal} Varian +
+ )} -
- + {product?.manufacture?.name} - {product?.name} - { product?.lowestPrice?.discountPercentage > 0 && ( -
-
+ {product?.lowestPrice?.discountPercentage > 0 && ( +
+
{currencyFormat(product?.lowestPrice?.price)}
-
- {product?.lowestPrice?.discountPercentage}% -
+
{product?.lowestPrice?.discountPercentage}%
- ) } + )} -
- { product?.lowestPrice?.priceDiscount > 0 ? currencyFormat(product?.lowestPrice?.priceDiscount) : ( - Call for price - ) } +
+ {product?.lowestPrice?.priceDiscount > 0 ? ( + currencyFormat(product?.lowestPrice?.priceDiscount) + ) : ( + Call for price + )}
- { product?.stockTotal > 0 && ( -
-
- Ready Stock -
-
- { product?.stockTotal > 5 ? '> 5' : '< 5' } -
+ {product?.stockTotal > 0 && ( +
+
Ready Stock
+
{product?.stockTotal > 5 ? '> 5' : '< 5'}
- ) } + )}
) } -export default ProductCard \ No newline at end of file +export default ProductCard diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx index 023b6a8b..d920cfb8 100644 --- a/src/lib/product/components/ProductFilter.jsx +++ b/src/lib/product/components/ProductFilter.jsx @@ -1,31 +1,24 @@ -import BottomPopup from "@/core/components/elements/Popup/BottomPopup" -import { useRouter } from "next/router" -import { useState } from "react" -import _ from "lodash" -import { toQuery } from "lodash-contrib" +import BottomPopup from '@/core/components/elements/Popup/BottomPopup' +import { useRouter } from 'next/router' +import { useState } from 'react' +import _ from 'lodash' +import { toQuery } from 'lodash-contrib' const orderOptions = [ { value: 'price-asc', label: 'Harga Terendah' }, { value: 'price-desc', label: 'Harga Tertinggi' }, { value: 'popular', label: 'Populer' }, - { value: 'stock', label: 'Ready Stock' }, + { value: 'stock', label: 'Ready Stock' } ] -const ProductFilter = ({ - active, - close, - brands, - categories, - prefixUrl, - defaultBrand = null -}) => { +const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBrand = null }) => { const router = useRouter() const { query } = router - const [ order, setOrder ] = useState(query?.orderBy) - const [ brand, setBrand ] = useState(query?.brand) - const [ category, setCategory ] = useState(query?.category) - const [ priceFrom, setPriceFrom ] = useState(query?.priceFrom) - const [ priceTo, setPriceTo ] = useState(query?.priceTo) + const [order, setOrder] = useState(query?.orderBy) + const [brand, setBrand] = useState(query?.brand) + const [category, setCategory] = useState(query?.category) + const [priceFrom, setPriceFrom] = useState(query?.priceFrom) + const [priceTo, setPriceTo] = useState(query?.priceTo) const handleSubmit = () => { let params = { @@ -42,85 +35,79 @@ const ProductFilter = ({ } return ( - -
- { !defaultBrand && ( + +
+ {!defaultBrand && (
-
- ) } + )}
-
-
- { orderOptions.map((orderOption) => ( - - )) } + ))}
-
- + setPriceFrom(e.target.value)} /> - setPriceTo(e.target.value)} />
-
@@ -128,4 +115,4 @@ const ProductFilter = ({ ) } -export default ProductFilter \ No newline at end of file +export default ProductFilter diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 14df9864..25d0278f 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -1,21 +1,23 @@ -import { useEffect, useState } from "react" -import useProductSearch from "../hooks/useProductSearch" -import ProductCard from "./ProductCard" -import Pagination from "@/core/components/elements/Pagination/Pagination" -import { toQuery } from "lodash-contrib" -import _ from "lodash" -import ProductSearchSkeleton from "./Skeleton/ProductSearchSkeleton" -import ProductFilter from "./ProductFilter" -import useActive from "@/core/hooks/useActive" +import { useEffect, useState } from 'react' +import useProductSearch from '../hooks/useProductSearch' +import ProductCard from './ProductCard' +import Pagination from '@/core/components/elements/Pagination/Pagination' +import { toQuery } from 'lodash-contrib' +import _ from 'lodash' +import ProductSearchSkeleton from './Skeleton/ProductSearchSkeleton' +import ProductFilter from './ProductFilter' +import useActive from '@/core/hooks/useActive' const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { const { page = 1 } = query if (defaultBrand) query.brand = defaultBrand.toLowerCase() const { productSearch } = useProductSearch({ query }) - const [ products, setProducts ] = useState(null) + const [products, setProducts] = useState(null) const popup = useActive() - const pageCount = Math.ceil(productSearch.data?.response.numFound / productSearch.data?.responseHeader.params.rows) + const pageCount = Math.ceil( + productSearch.data?.response.numFound / productSearch.data?.responseHeader.params.rows + ) const productStart = productSearch.data?.responseHeader.params.start const productRows = productSearch.data?.responseHeader.params.rows const productFound = productSearch.data?.response.numFound @@ -25,11 +27,13 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { return true } }) - const categories = productSearch.data?.facetCounts?.facetFields?.categoryNameStr?.filter((value, index) => { - if (index % 2 === 0) { - return true + const categories = productSearch.data?.facetCounts?.facetFields?.categoryNameStr?.filter( + (value, index) => { + if (index % 2 === 0) { + return true + } } - }) + ) useEffect(() => { if (!products) { @@ -40,47 +44,55 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { if (productSearch.isLoading) { return } - + return ( -
-

Produk

- -
- { productFound > 0 ? ( +
+

Produk

+ +
+ {productFound > 0 ? ( <> Menampilkan  {pageCount > 1 ? ( <> - {productStart + 1}-{ - (productStart + productRows) > productFound ? productFound : productStart + productRows - } + {productStart + 1}- + {productStart + productRows > productFound + ? productFound + : productStart + productRows}  dari  - ) : ''} - { productFound } -  produk { query.q && (<>untuk pencarian { query.q }) } + ) : ( + '' + )} + {productFound} +  produk{' '} + {query.q && ( + <> + untuk pencarian {query.q} + + )} - ) : 'Mungkin yang anda cari'} + ) : ( + 'Mungkin yang anda cari' + )}
- -
- { products && products.map((product) => ( - - )) } +
+ {products && products.map((product) => )}
- { ) } -export default ProductSearch \ No newline at end of file +export default ProductSearch diff --git a/src/lib/product/components/ProductSimilar.jsx b/src/lib/product/components/ProductSimilar.jsx index 89cab536..63a33089 100644 --- a/src/lib/product/components/ProductSimilar.jsx +++ b/src/lib/product/components/ProductSimilar.jsx @@ -1,6 +1,6 @@ -import PopularProductSkeleton from "@/lib/home/components/Skeleton/PopularProductSkeleton" -import useProductSimilar from "../hooks/useProductSimilar" -import ProductSlider from "./ProductSlider" +import PopularProductSkeleton from '@/lib/home/components/Skeleton/PopularProductSkeleton' +import useProductSimilar from '../hooks/useProductSimilar' +import ProductSlider from './ProductSlider' const ProductSimilar = ({ query }) => { const { productSimilar } = useProductSimilar({ query }) @@ -12,4 +12,4 @@ const ProductSimilar = ({ query }) => { return } -export default ProductSimilar \ No newline at end of file +export default ProductSimilar diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index 8d677547..aafd3cf1 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -1,51 +1,48 @@ -import { Swiper, SwiperSlide } from "swiper/react" -import ProductCard from "./ProductCard" -import "swiper/css" -import Image from "@/core/components/elements/Image/Image" -import Link from "@/core/components/elements/Link/Link" -import { useState } from "react" +import { Swiper, SwiperSlide } from 'swiper/react' +import ProductCard from './ProductCard' +import 'swiper/css' +import Image from '@/core/components/elements/Image/Image' +import Link from '@/core/components/elements/Link/Link' +import { useState } from 'react' -const bannerClassName = 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' +const bannerClassName = + 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' -const ProductSlider = ({ - products, - simpleTitle = false, - bannerMode = false -}) => { - const [ activeIndex, setActiveIndex ] = useState(0) +const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => { + const [activeIndex, setActiveIndex] = useState(0) const swiperSliderFirstMove = (swiper) => { setActiveIndex(swiper.activeIndex) } return ( <> - { bannerMode && ( - {products.banner.name} 0 ? 'opacity-0' : 'opacity-100'}`} + {bannerMode && ( + {products.banner.name} 0 ? 'opacity-0' : 'opacity-100'}`} /> - ) } - - { bannerMode && ( + {bannerMode && ( - + - ) } - { products?.products?.map((product, index) => ( + )} + {products?.products?.map((product, index) => ( - )) } + ))} ) } -export default ProductSlider \ No newline at end of file +export default ProductSlider diff --git a/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx b/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx index e51a565c..fa1e175d 100644 --- a/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx +++ b/src/lib/product/components/Skeleton/ProductSearchSkeleton.jsx @@ -1,7 +1,7 @@ -import ProductCardSkeleton from "@/core/components/elements/Skeleton/ProductCardSkeleton" +import ProductCardSkeleton from '@/core/components/elements/Skeleton/ProductCardSkeleton' const ProductSearchSkeleton = () => ( -
+
@@ -11,4 +11,4 @@ const ProductSearchSkeleton = () => (
) -export default ProductSearchSkeleton \ No newline at end of file +export default ProductSearchSkeleton -- cgit v1.2.3 From 7265295454801c1d921385a4b67fb3780b46771e Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Wed, 22 Feb 2023 14:00:00 +0700 Subject: fix --- src/lib/product/components/ProductCard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 8a2f1d7f..0fe75c56 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -6,7 +6,7 @@ import { createSlug } from '@/core/utils/slug' const ProductCard = ({ product, simpleTitle }) => { return ( <> -
+
Date: Wed, 22 Feb 2023 14:02:28 +0700 Subject: fix --- src/lib/product/components/ProductCard.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 0fe75c56..dd221e4f 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -6,7 +6,7 @@ import { createSlug } from '@/core/utils/slug' const ProductCard = ({ product, simpleTitle }) => { return ( <> -
+
{
)} -
+
Date: Wed, 22 Feb 2023 14:42:23 +0700 Subject: fix --- src/lib/product/components/ProductSlider.jsx | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index aafd3cf1..eeea7acc 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -1,34 +1,43 @@ import { Swiper, SwiperSlide } from 'swiper/react' +import { FreeMode } from 'swiper' import ProductCard from './ProductCard' import 'swiper/css' +import 'swiper/css/free-mode' import Image from '@/core/components/elements/Image/Image' import Link from '@/core/components/elements/Link/Link' -import { useState } from 'react' +import { useRef, useState } from 'react' const bannerClassName = 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => { - const [activeIndex, setActiveIndex] = useState(0) - const swiperSliderFirstMove = (swiper) => { - setActiveIndex(swiper.activeIndex) + const bannerRef = useRef('') + + const onSliderMove = (swiper) => { + if (!bannerMode) return + const calculateOpacity = (132 + swiper.translate) / 100 + bannerRef.current.style = `opacity: ${calculateOpacity > 0 ? calculateOpacity : 0}` } return ( <> {bannerMode && ( - {products.banner.name} 0 ? 'opacity-0' : 'opacity-100'}`} - /> +
+ {products.banner.name} +
)} {bannerMode && ( -- cgit v1.2.3 From 7cbd033633ebc549ce06cff278b197c4f186f9dd Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Wed, 22 Feb 2023 14:54:18 +0700 Subject: fix --- src/lib/product/components/ProductSlider.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/ProductSlider.jsx b/src/lib/product/components/ProductSlider.jsx index eeea7acc..0dab2f6b 100644 --- a/src/lib/product/components/ProductSlider.jsx +++ b/src/lib/product/components/ProductSlider.jsx @@ -2,10 +2,9 @@ import { Swiper, SwiperSlide } from 'swiper/react' import { FreeMode } from 'swiper' import ProductCard from './ProductCard' import 'swiper/css' -import 'swiper/css/free-mode' import Image from '@/core/components/elements/Image/Image' import Link from '@/core/components/elements/Link/Link' -import { useRef, useState } from 'react' +import { useRef } from 'react' const bannerClassName = 'absolute rounded-r top-0 left-0 h-full max-w-[52%] idt-transition border border-gray_r-6' @@ -13,7 +12,7 @@ const bannerClassName = const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => { const bannerRef = useRef('') - const onSliderMove = (swiper) => { + const changeBannerOpacity = (swiper) => { if (!bannerMode) return const calculateOpacity = (132 + swiper.translate) / 100 bannerRef.current.style = `opacity: ${calculateOpacity > 0 ? calculateOpacity : 0}` @@ -35,7 +34,9 @@ const ProductSlider = ({ products, simpleTitle = false, bannerMode = false }) => freeMode={{ enabled: true, sticky: false }} slidesPerView={2.2} spaceBetween={8} - onSliderMove={onSliderMove} + onSliderMove={changeBannerOpacity} + onSlideChangeTransitionEnd={changeBannerOpacity} + onSlideChangeTransitionStart={changeBannerOpacity} prefix='product' modules={[FreeMode]} > -- cgit v1.2.3 From 8cfb615556e67408d7afb6d9694b2407447085ff Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Wed, 22 Feb 2023 23:34:50 +0700 Subject: fix --- src/lib/product/components/Product.jsx | 81 ++++++++++++++++++++++++++---- src/lib/product/components/ProductCard.jsx | 20 +++++--- 2 files changed, 85 insertions(+), 16 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/Product.jsx b/src/lib/product/components/Product.jsx index 2181c38e..9e33316c 100644 --- a/src/lib/product/components/Product.jsx +++ b/src/lib/product/components/Product.jsx @@ -9,6 +9,11 @@ import ProductSimilar from './ProductSimilar' import LazyLoad from 'react-lazy-load' import { toast } from 'react-hot-toast' import { updateItemCart } from '@/core/utils/cart' +import useWishlist from '@/lib/wishlist/hooks/useWishlist' +import { HeartIcon } from '@heroicons/react/24/outline' +import useAuth from '@/core/hooks/useAuth' +import { useRouter } from 'next/router' +import createOrDeleteWishlistApi from '@/lib/wishlist/api/createOrDeleteWishlistApi' const informationTabOptions = [ { value: 'specification', label: 'Spesifikasi' }, @@ -17,6 +22,9 @@ const informationTabOptions = [ ] const Product = ({ product }) => { + const auth = useAuth() + const router = useRouter() + const { wishlist } = useWishlist({ productId: product?.id }) const [quantity, setQuantity] = useState('1') const [selectedVariant, setSelectedVariant] = useState(null) const [informationTab, setInformationTab] = useState(null) @@ -82,6 +90,21 @@ const Product = ({ product }) => { toast.success('Berhasil menambahkan ke keranjang') } + const toggleWishlist = async () => { + if (!auth) { + router.push('/login') + return + } + const data = { product_id: product.id } + await createOrDeleteWishlistApi({ data }) + if (wishlist.data.productTotal > 0) { + toast.success('Berhasil menghapus dari wishlist') + } else { + toast.success('Berhasil menambahkan ke wishlist') + } + wishlist.refetch() + } + return ( <> { />
- - {product.manufacture?.name} - +
+ {product.manufacture?.name ? ( + {product.manufacture?.name} + ) : ( +
-
+ )} + +

{activeVariant?.name}

{activeVariant?.price?.discountPercentage > 0 && (
@@ -109,7 +147,10 @@ const Product = ({ product }) => { ) : ( Hubungi kami untuk dapatkan harga terbaik,  - + klik disini @@ -146,10 +187,17 @@ const Product = ({ product }) => { onChange={(e) => setQuantity(e.target.value)} />
- -
@@ -193,7 +241,10 @@ const Product = ({ product }) => { )} {activeVariant?.stock == 0 && ( - + Tanya Stok )} @@ -201,7 +252,10 @@ const Product = ({ product }) => { {activeVariant?.weight > 0 && {activeVariant?.weight} KG} {activeVariant?.weight == 0 && ( - + Tanya Berat )} @@ -232,14 +286,21 @@ const Product = ({ product }) => { const TabButton = ({ children, active, ...props }) => { const activeClassName = active ? 'text-red_r-11 underline underline-offset-4' : 'text-gray_r-11' return ( - ) } const TabContent = ({ children, active, className, ...props }) => ( -
+
{children}
) diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index dd221e4f..6b88a3bd 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -23,12 +23,20 @@ const ProductCard = ({ product, simpleTitle }) => { )}
- - {product?.manufacture?.name} - + {product?.manufacture?.name ? ( + + {product.manufacture.name} + + ) : ( +
-
+ )} Date: Wed, 22 Feb 2023 23:36:47 +0700 Subject: fix --- src/lib/product/components/ProductFilter.jsx | 22 ++++++++++++++++++---- src/lib/product/components/ProductSearch.jsx | 13 +++++++++++-- src/lib/product/components/ProductSlider.jsx | 10 ++++++++-- 3 files changed, 37 insertions(+), 8 deletions(-) (limited to 'src/lib/product/components') diff --git a/src/lib/product/components/ProductFilter.jsx b/src/lib/product/components/ProductFilter.jsx index d920cfb8..eca95f74 100644 --- a/src/lib/product/components/ProductFilter.jsx +++ b/src/lib/product/components/ProductFilter.jsx @@ -35,7 +35,11 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr } return ( - +
{!defaultBrand && (
@@ -48,7 +52,10 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr > {brands.map((brand, index) => ( - ))} @@ -65,7 +72,10 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr > {categories.map((category, index) => ( - ))} @@ -107,7 +117,11 @@ const ProductFilter = ({ active, close, brands, categories, prefixUrl, defaultBr />
-
diff --git a/src/lib/product/components/ProductSearch.jsx b/src/lib/product/components/ProductSearch.jsx index 25d0278f..52bd5119 100644 --- a/src/lib/product/components/ProductSearch.jsx +++ b/src/lib/product/components/ProductSearch.jsx @@ -77,12 +77,21 @@ const ProductSearch = ({ query, prefixUrl, defaultBrand = null }) => { )}
-
- {products && products.map((product) => )} + {products && + products.map((product) => ( + + ))}
> {bannerMode && ( - + )} {products?.products?.map((product, index) => ( - + ))}
-- cgit v1.2.3