From e07a57651649cb2493e5b00a361797cf1392a186 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 1 Aug 2024 11:59:26 +0700 Subject: update template switch --- .../components/Product/ProductDesktopVariant.jsx | 66 ++++++++++++++++++-- .../components/Product/ProductMobileVariant.jsx | 71 +++++++++++++++++++--- 2 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/lib/product/components/Product/ProductDesktopVariant.jsx b/src/lib/product/components/Product/ProductDesktopVariant.jsx index 09b30a44..882673f4 100644 --- a/src/lib/product/components/Product/ProductDesktopVariant.jsx +++ b/src/lib/product/components/Product/ProductDesktopVariant.jsx @@ -6,6 +6,11 @@ import { useRouter } from 'next/router'; import { useCallback, useEffect, useRef, useState } from 'react'; import { toast } from 'react-hot-toast'; import LazyLoad from 'react-lazy-load'; +import { Button } from '@chakra-ui/react' +import { MessageCircleIcon, Share2Icon } from 'lucide-react' +import AddToWishlist from '../../../../../src-migrate/modules/product-detail/components/AddToWishlist' +import { RWebShare } from 'react-web-share' +// import Link from 'next/link' import { useProductCartContext } from '@/contexts/ProductCartContext'; import odooApi from '@/core/api/odooApi'; @@ -18,11 +23,14 @@ import { updateItemCart } from '@/core/utils/cart'; import currencyFormat from '@/core/utils/currencyFormat'; import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; +import Breadcrumb from '../../../../../src-migrate/modules/product-detail/components/Breadcrumb'; import productSimilarApi from '../../api/productSimilarApi'; import ProductCard from '../ProductCard'; import ProductSimilar from '../ProductSimilar'; +const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST + const ProductDesktopVariant = ({ product, wishlist, @@ -32,7 +40,7 @@ const ProductDesktopVariant = ({ const router = useRouter(); const auth = useAuth(); const { slug } = router.query; - + const [ askAdminUrl, setAskAdminUrl ] = useState() const [lowestPrice, setLowestPrice] = useState(null); const [addCartAlert, setAddCartAlert] = useState(false); @@ -53,6 +61,20 @@ const ProductDesktopVariant = ({ setLowestPrice(lowest); }, [getLowestPrice]); + useEffect(() => { + const createdAskUrl = whatsappUrl({ + template: 'product', + payload: { + manufacture: product.manufacture.name, + productName: product.name, + url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath + }, + fallbackUrl: router.asPath + }) + + setAskAdminUrl(createdAskUrl) + }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl]) + const [informationTab, setInformationTab] = useState( informationTabOptions[0].value ); @@ -154,6 +176,7 @@ const ProductDesktopVariant = ({ return (
+
@@ -263,9 +286,42 @@ const ProductDesktopVariant = ({
+
+
+ + + + + + + +
+ -
+ +

Informasi Produk

-
+
{product?.isFlashsale > 0 && product?.price?.discountPercentage > 0 ? ( <> @@ -359,7 +415,7 @@ const ProductDesktopVariant = ({ Beli
-
+ {/*
+
*/}
Produk Serupa diff --git a/src/lib/product/components/Product/ProductMobileVariant.jsx b/src/lib/product/components/Product/ProductMobileVariant.jsx index af9e52bb..ce836d5b 100644 --- a/src/lib/product/components/Product/ProductMobileVariant.jsx +++ b/src/lib/product/components/Product/ProductMobileVariant.jsx @@ -16,9 +16,15 @@ import currencyFormat from '@/core/utils/currencyFormat'; import { gtagAddToCart } from '@/core/utils/googleTag'; import { createSlug } from '@/core/utils/slug'; import whatsappUrl from '@/core/utils/whatsappUrl'; - +import Breadcrumb from '../../../../../src-migrate/modules/product-detail/components/Breadcrumb'; +import { Button } from '@chakra-ui/react' +import { MessageCircleIcon, Share2Icon } from 'lucide-react' +import AddToWishlist from '../../../../../src-migrate/modules/product-detail/components/AddToWishlist' +import { RWebShare } from 'react-web-share' import ProductSimilar from '../ProductSimilar'; +const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST + const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { const router = useRouter(); @@ -28,7 +34,7 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { informationTabOptions[0].value ); const [addCartAlert, setAddCartAlert] = useState(false); - + const [ askAdminUrl, setAskAdminUrl ] = useState() const [isLoadingSLA, setIsLoadingSLA] = useState(true); const getLowestPrice = () => { @@ -60,6 +66,20 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { } }, [selectedVariant, product]); + useEffect(() => { + const createdAskUrl = whatsappUrl({ + template: 'product', + payload: { + manufacture: product.manufacture.name, + productName: product.name, + url: process.env.NEXT_PUBLIC_SELF_HOST + router.asPath + }, + fallbackUrl: router.asPath + }) + + setAskAdminUrl(createdAskUrl) + }, [router.asPath, product.manufacture.name, product.name, setAskAdminUrl]) + const validAction = () => { let isValid = true; if (!selectedVariant) { @@ -120,14 +140,17 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => { return ( +
+ +
{product.name}
-
+
{product.manufacture?.name ? ( { ) : (
-
)} - + + + + + + +
+ {/* + */}
-

{activeVariant?.name}

+

{activeVariant?.name}

{activeVariant.isFlashSale && activeVariant?.price?.discountPercentage > 0 ? ( @@ -173,11 +226,11 @@ const ProductMobileVariant = ({ product, wishlist, toggleWishlist }) => {
) : ( -

+

{activeVariant?.price?.price > 0 ? ( <> {currencyFormat(activeVariant?.price?.price)} -
+
Termasuk PPN:{' '} {currencyFormat( activeVariant?.price.price * process.env.NEXT_PUBLIC_PPN -- cgit v1.2.3 From bd62835db7dc521a17d6b0aea81badaae6ade95c Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 2 Aug 2024 16:47:42 +0700 Subject: update template switch --- .../product-card/components/ProductCard.tsx | 150 ++++++++++++++++++--- src-migrate/services/product.ts | 37 ++++- src-migrate/types/product.ts | 6 +- 3 files changed, 171 insertions(+), 22 deletions(-) diff --git a/src-migrate/modules/product-card/components/ProductCard.tsx b/src-migrate/modules/product-card/components/ProductCard.tsx index 0febfadb..3e34d5c3 100644 --- a/src-migrate/modules/product-card/components/ProductCard.tsx +++ b/src-migrate/modules/product-card/components/ProductCard.tsx @@ -10,6 +10,10 @@ import formatCurrency from '~/libs/formatCurrency' import { formatToShortText } from '~/libs/formatNumber' import { createSlug } from '~/libs/slug' import { IProduct } from '~/types/product' +import { useRouter } from 'next/router'; +import currencyFormat from '@/core/utils/currencyFormat'; +import whatsappUrl from '@/core/utils/whatsappUrl'; +import { sellingProductFormat } from '@/core/utils/formatValue'; type Props = { product: IProduct @@ -18,7 +22,14 @@ type Props = { const ProductCard = ({ product, layout = 'vertical' }: Props) => { const utmSource = useUtmSource() - + const router = useRouter(); + + const id = product.id.toString () + const callForPriceWhatsapp = whatsappUrl('product', { + name: product.name, + manufacture: product.manufacture?.name, + url: createSlug('/shop/product/', product.name, id, true), + }); const URL = { product: createSlug('/shop/product/', product.name, product.id.toString()) + `?utm_source=${utmSource}`, @@ -75,6 +86,42 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => {

+ {layout === 'vertical' && ( +
+ {router.pathname != '/' && product?.flash_sale.id > 0 && ( +
+
+ +
+
+
+
+ + {Math.floor(product?.lowest_price.discount_percentage ? product?.lowest_price.discount_percentage : product?.lowest_price.discountPercentage)}% + +
+
+ + + {product?.flash_sale?.tag != 'false' || + product?.flash_sale?.tag + ? product?.flash_sale?.tag + : 'FLASH SALE'} + +
+
+
+
+ )} +
+ )} {product.variant_total > 1 && (
{product.variant_total} Varian
@@ -86,6 +133,24 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => { [style['content-v']]: layout === 'vertical', [style['content-h']]: layout === 'horizontal', })}> + {layout === 'horizontal' && ( +
+ {product.flash_sale.id > 0 && ( +
+ + + {' '} + {product?.flash_sale?.tag != 'false' || product?.flash_sale?.tag + ? product?.flash_sale?.tag + : 'FLASH SALE'} + +
+ )} +
+ )} { {product.name}
- -
+ {product?.flash_sale?.id > 0 ? (
) : + ( +
Rp {formatCurrency(product.lowest_price.price)}
+ ) + } + +
-
- Inc PPN: - Rp {formatCurrency(Math.round(product.lowest_price.price * 1.11))} -
+ {product?.flash_sale?.id > 0 && + product?.lowest_price?.discountPercentage > 0 ? ( + <> + {product?.lowest_price.discountPercentage > 0 && ( +
+
+ {Math.floor(product?.lowest_price.discount_percentage ? product?.lowest_price.discount_percentage : product?.lowest_price.discountPercentage)}% +
+
+ {currencyFormat(product?.lowest_price?.price)} +
+
+ )} -
+
+ {product?.lowest_price?.price_discount ? product?.lowest_price?.price_discount : product?.lowest_price?.priceDiscount > 0 ? ( + currencyFormat(product?.lowest_price?.price_discount ? product?.lowest_price?.price_discount : product?.lowest_price?.priceDiscount) + ) : ( + + Call for Inquiry + + )} +
+
+ {product?.stockTotal > 0 && ( +
Ready Stock
+ )} + {/*
{product?.stockTotal > 5 ? '> 5' : '< 5'}
*/} + {product?.qtySold > 0 && ( +
+ {sellingProductFormat(product?.qtySold) + ' Terjual'} +
+ )} +
+ + ) : ( +
+
+ Inc PPN: + Rp {formatCurrency(Math.round(product.lowest_price.price * 1.11))} +
-
- {product.stock_total > 0 && ( -
- Ready Stock -
- )} - {product.qty_sold > 0 && ( -
- {formatToShortText(product.qty_sold)} Terjual +
+ +
+ {product.stock_total > 0 && ( +
+ Ready Stock +
+ )} + {product.qty_sold > 0 && ( +
+ {formatToShortText(product.qty_sold)} Terjual +
+ )} +
)} -
+
diff --git a/src-migrate/services/product.ts b/src-migrate/services/product.ts index fe415d11..51667eb9 100644 --- a/src-migrate/services/product.ts +++ b/src-migrate/services/product.ts @@ -2,6 +2,7 @@ import { IProduct, IProductDetail } from '~/types/product'; import snakeCase from 'snakecase-keys'; import odooApi from '~/libs/odooApi'; import { ICategoryBreadcrumb } from '~/types/category'; +import productSearchApi from '../../src/lib/product/api/productSearchApi' const SELF_HOST = process.env.NEXT_PUBLIC_SELF_HOST; @@ -40,6 +41,27 @@ export const getProductSimilar = async ({ except, limit = 30, }: GetProductSimilarProps): Promise => { + let dataflashSale = null + const flashSale = await odooApi('GET', '/api/v1/flashsale/header') + if (flashSale && flashSale.length > 0) { + const dataFlash = await productSearchApi({ + query: `fq=flashsale_id_i:${flashSale[0].pricelist_id}&fq=flashsale_price_f:[1 TO *]&limit=4`, + operation: 'AND' + }) + + dataflashSale = dataFlash.response.products.map((product: { + qtySold: any; + stockTotal: any; + flashSale: any; lowestPrice: any; +}) => ({ + ...product, + lowest_price: product.lowestPrice, + flash_sale: product.flashSale, + stock_total: product.stockTotal, + qty_sold: product.qtySold, + lowestPrice: undefined + })); + } const query = [ `q=${name}`, 'page=1', @@ -47,16 +69,25 @@ export const getProductSimilar = async ({ 'operation=OR', 'priceFrom=1', ]; - if (except?.productId) query.push(`fq=-product_id_i:${except.productId}`); if (except?.manufactureId) query.push(`fq=-manufacture_id_i:${except.manufactureId}`); - const url = `${SELF_HOST}/api/shop/search?${query.join('&')}`; - return await fetch(url) + const fetchedData = await fetch(url) .then((res) => res.json()) .then((res) => snakeCase(res.response)); + + if (dataflashSale) { + fetchedData.products = [ + ...dataflashSale, + ...fetchedData.products + ] + } else { + fetchedData.products = [...fetchedData.products] + } + + return fetchedData; }; export const getProductCategoryBreadcrumb = async ( diff --git a/src-migrate/types/product.ts b/src-migrate/types/product.ts index 681cdc8e..75d55002 100644 --- a/src-migrate/types/product.ts +++ b/src-migrate/types/product.ts @@ -1,6 +1,8 @@ import { IProductVariantDetail } from './productVariant'; export interface IProduct { + qtySold: number; + stockTotal: number; id: number; image: string; code: string; @@ -18,11 +20,13 @@ export interface IProduct { name: string; }[]; flash_sale: { - id: string; + id: number; remaining_time: number; tag: string; }; lowest_price: { + priceDiscount: number; + discountPercentage: number; price: number; price_discount: number; discount_percentage: number; -- cgit v1.2.3 From 616d8ffc973eba673069243ec8981b5234234fe5 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 8 Aug 2024 17:09:56 +0700 Subject: add similar product template --- .../modules/product-detail/components/ProductDetail.tsx | 2 +- .../modules/product-detail/components/SimilarBottom.tsx | 6 ++++-- src-migrate/services/product.ts | 13 ++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src-migrate/modules/product-detail/components/ProductDetail.tsx b/src-migrate/modules/product-detail/components/ProductDetail.tsx index fad35a7d..f5feae76 100644 --- a/src-migrate/modules/product-detail/components/ProductDetail.tsx +++ b/src-migrate/modules/product-detail/components/ProductDetail.tsx @@ -178,7 +178,7 @@ const ProductDetail = ({ product }: Props) => {
- +
diff --git a/src-migrate/modules/product-detail/components/SimilarBottom.tsx b/src-migrate/modules/product-detail/components/SimilarBottom.tsx index 40d4dd82..ab33f106 100644 --- a/src-migrate/modules/product-detail/components/SimilarBottom.tsx +++ b/src-migrate/modules/product-detail/components/SimilarBottom.tsx @@ -5,12 +5,14 @@ import { IProductDetail } from '~/types/product' type Props = { product: IProductDetail + source: string } -const SimilarBottom = ({ product }: Props) => { +const SimilarBottom = ({ product, source }: Props) => { const productSimilar = useProductSimilar({ name: product.name, - except: { productId: product.id } + except: { productId: product.id }, + source: source }) const products = productSimilar.data?.products || [] diff --git a/src-migrate/services/product.ts b/src-migrate/services/product.ts index 51667eb9..ec5435cd 100644 --- a/src-migrate/services/product.ts +++ b/src-migrate/services/product.ts @@ -21,6 +21,7 @@ export const getProductById = async ( }; export interface GetProductSimilarProps { + source?: string; name: string; except?: { productId?: number; @@ -34,18 +35,22 @@ export interface GetProductSimilarRes { num_found: number; num_found_exact: boolean; start: number; + source: string; } export const getProductSimilar = async ({ name, except, limit = 30, + source, }: GetProductSimilarProps): Promise => { let dataflashSale = null const flashSale = await odooApi('GET', '/api/v1/flashsale/header') if (flashSale && flashSale.length > 0) { const dataFlash = await productSearchApi({ - query: `fq=flashsale_id_i:${flashSale[0].pricelist_id}&fq=flashsale_price_f:[1 TO *]&limit=4`, + query: `fq=flashsale_id_i:${flashSale[0].pricelist_id}&fq=flashsale_price_f:[1 TO *]&limit=${ + source === 'bottom' ? '4' : '1' + }`, operation: 'AND' }) @@ -61,6 +66,12 @@ export const getProductSimilar = async ({ qty_sold: product.qtySold, lowestPrice: undefined })); + if (source === 'bottom') { + dataflashSale = dataflashSale.slice('2', '4') + } else { + dataflashSale = dataflashSale + } + console.log("dataflashSale",dataflashSale) } const query = [ `q=${name}`, -- cgit v1.2.3