diff options
Diffstat (limited to 'src-migrate')
10 files changed, 174 insertions, 22 deletions
diff --git a/src-migrate/constants/utm-source.ts b/src-migrate/constants/utm-source.ts new file mode 100644 index 00000000..95c03ed2 --- /dev/null +++ b/src-migrate/constants/utm-source.ts @@ -0,0 +1,8 @@ +export const UTM_SOURCE = { + '/': 'web.home', + '/shop/product/[slug]': 'web.other-product', + '/shop/search': 'web.search', + '/shop/brands/[slug]': 'web.brand', + '/shop/category/[slug]': 'web.category', + '/shop/cart': 'web.cart', +}; diff --git a/src-migrate/hooks/useUtmSource.ts b/src-migrate/hooks/useUtmSource.ts new file mode 100644 index 00000000..a72fae36 --- /dev/null +++ b/src-migrate/hooks/useUtmSource.ts @@ -0,0 +1,20 @@ +import { useRouter } from 'next/router'; +import { useEffect, useState } from 'react'; +import { UTM_SOURCE } from '~/constants/utm-source'; + +const useUtmSource = () => { + const router = useRouter(); + const [source, setSource] = useState<string>(); + + useEffect(() => { + console.log(router.pathname); + + if (router.pathname) { + setSource(UTM_SOURCE[router.pathname as keyof typeof UTM_SOURCE]); + } + }, [router.pathname]); + + return source; +}; + +export default useUtmSource; diff --git a/src-migrate/modules/cart/components/CartSummaryMobile.tsx b/src-migrate/modules/cart/components/CartSummaryMobile.tsx new file mode 100644 index 00000000..d9f72e0e --- /dev/null +++ b/src-migrate/modules/cart/components/CartSummaryMobile.tsx @@ -0,0 +1,111 @@ +import style from '../styles/summary.module.css'; + +import React, { useState } from 'react'; +import formatCurrency from '~/libs/formatCurrency'; +import clsxm from '~/libs/clsxm'; +import { Button, Skeleton } from '@chakra-ui/react'; +import _ from 'lodash'; +import { ChevronDownIcon } from '@heroicons/react/24/outline'; +import BottomPopup from '@/core/components/elements/Popup/BottomPopup'; +import useDevice from '@/core/hooks/useDevice'; + +type Props = { + total?: number; + discount?: number; + subtotal?: number; + tax?: number; + shipping?: number; + grandTotal?: number; + isLoaded: boolean; +}; + +const CartSummaryMobile = ({ + total, + discount, + subtotal, + tax, + shipping, + grandTotal, + isLoaded = false, +}: Props) => { + const [showPopup, setShowPopup] = useState(false); + return ( + <> + <BottomPopup + className=' !h-[35%]' + title='Ringkasan Pensanan' + active={showPopup} + close={() => setShowPopup(false)} + > + <div className='mt-4'> + <div className='flex flex-col gap-y-3'> + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={style.label}>Total Belanja</span> + <span className={style.value}> + Rp {formatCurrency(subtotal || 0)} + </span> + </Skeleton> + + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={style.label}>Total Diskon</span> + <span className={clsxm(style.value, style.discount)}> + - Rp {formatCurrency(discount || 0)} + </span> + </Skeleton> + + <div className={style.divider} /> + + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={style.label}>Subtotal</span> + <span className={style.value}> + Rp {formatCurrency(total || 0)} + </span> + </Skeleton> + + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={style.label}>Tax 11%</span> + <span className={style.value}>Rp {formatCurrency(tax || 0)}</span> + </Skeleton> + + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={style.label}>Biaya Kirim</span> + <span className={style.value}> + Rp {formatCurrency(shipping || 0)} + </span> + </Skeleton> + + <div className={style.divider} /> + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={clsxm(style.label, style.grandTotal)}> + Grand Total + </span> + <span className={style.value}> + Rp {formatCurrency(grandTotal || 0)} + </span> + </Skeleton> + </div> + </div> + </BottomPopup> + <div className='flex flex-col gap-y-3'> + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={clsxm(style.label, style.grandTotal)}> + Grand Total + </span> + <button + onClick={() => setShowPopup(true)} + className='bg-gray-300 w-6 h-6 items-center justify-center cursor-pointer hover:bg-red-400 md:hidden ' + > + <ChevronDownIcon className='h-6 w-6 text-white' /> + </button> + </Skeleton> + <Skeleton isLoaded={isLoaded} className={style.line}> + <span className={style.value}> + Rp {formatCurrency(grandTotal || 0)} + </span> + </Skeleton> + </div> + </> + ); +}; + +export default CartSummaryMobile; diff --git a/src-migrate/modules/popup-information/index.tsx b/src-migrate/modules/popup-information/index.tsx index 3d537236..0d36f8e9 100644 --- a/src-migrate/modules/popup-information/index.tsx +++ b/src-migrate/modules/popup-information/index.tsx @@ -1,9 +1,9 @@ import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; -import { Modal } from "~/components/ui/modal" + +import { Modal } from "~/components/ui/modal"; import { getAuth } from '~/libs/auth'; import PageContent from '../page-content'; -import Link from 'next/link'; const PagePopupInformation = () => { const router = useRouter(); @@ -12,9 +12,7 @@ const PagePopupInformation = () => { const [active, setActive] = useState<boolean>(false); useEffect(() => { - if (isHomePage && !auth) { - setActive(true); - } + if (isHomePage && !auth) setActive(true); }, [isHomePage, auth]); return ( <div className='group'> @@ -24,13 +22,8 @@ const PagePopupInformation = () => { close={() => setActive(false)} mode='desktop' > - <div className='w-[350px] md:w-[530px] '> - <Link href={'/register'}> - <PageContent path='/onbording-popup' /> - </Link> - {/* <Link href={'/register'} className='btn-yellow w-full mt-2'> - Daftar Sekarang - </Link> */} + <div className='w-[350px] md:w-[530px]' onClick={() => setActive(false)}> + <PageContent path='/onbording-popup' /> </div> </Modal> </div> diff --git a/src-migrate/modules/product-card/components/ProductCard.tsx b/src-migrate/modules/product-card/components/ProductCard.tsx index 8487cd94..4ddebda5 100644 --- a/src-migrate/modules/product-card/components/ProductCard.tsx +++ b/src-migrate/modules/product-card/components/ProductCard.tsx @@ -1,8 +1,10 @@ import style from '../styles/product-card.module.css' +import clsx from 'clsx' import Link from 'next/link' -import React, { useMemo } from 'react' +import { useMemo } from 'react' import Image from '~/components/ui/image' +import useUtmSource from '~/hooks/useUtmSource' import clsxm from '~/libs/clsxm' import formatCurrency from '~/libs/formatCurrency' import { formatToShortText } from '~/libs/formatNumber' @@ -15,8 +17,10 @@ type Props = { } const ProductCard = ({ product, layout = 'vertical' }: Props) => { + const utmSource = useUtmSource() + const URL = { - product: createSlug('/shop/product/', product.name, product.id.toString()), + product: createSlug('/shop/product/', product.name, product.id.toString()) + `?utm_source=${utmSource}`, manufacture: createSlug('/shop/brands/', product.manufacture.name, product.manufacture.id.toString()), } diff --git a/src-migrate/modules/product-detail/components/Image.tsx b/src-migrate/modules/product-detail/components/Image.tsx index b69cc87f..3d7777f8 100644 --- a/src-migrate/modules/product-detail/components/Image.tsx +++ b/src-migrate/modules/product-detail/components/Image.tsx @@ -67,7 +67,7 @@ const Image = ({ product }: Props) => { <div className='absolute bottom-0 w-full h-14'> <div className="relative w-full h-full"> <ImageUI - src='/images/GAMBAR-BG-FLASH-SALE.jpg' + src='/images/BG-FLASH-SALE.jpg' alt='Flash Sale Indoteknik' width={200} height={100} diff --git a/src-migrate/pages/api/product-variant/[id]/promotion/[category].tsx b/src-migrate/pages/api/product-variant/[id]/promotion/[category].tsx index 50671afd..8da0d9a3 100644 --- a/src-migrate/pages/api/product-variant/[id]/promotion/[category].tsx +++ b/src-migrate/pages/api/product-variant/[id]/promotion/[category].tsx @@ -8,10 +8,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const category = req.query.category as string if (req.method === 'GET') { - const queryParams = new URLSearchParams({ - q: `product_ids:${productId}`, - fq: `type_value_s:${category}` - }) + const queryParams = new URLSearchParams({ q: `product_ids:${productId}` }) + queryParams.append('fq', `type_value_s:${category}`) + queryParams.append('fq', `active_b:true`) const response = await fetch(`${SOLR_HOST}/solr/promotion_program_lines/select?${queryParams.toString()}`) const data: SolrResponse<any[]> = await response.json() diff --git a/src-migrate/pages/api/product-variant/[id]/promotion/highlight.tsx b/src-migrate/pages/api/product-variant/[id]/promotion/highlight.tsx index 8153f346..c4acacf1 100644 --- a/src-migrate/pages/api/product-variant/[id]/promotion/highlight.tsx +++ b/src-migrate/pages/api/product-variant/[id]/promotion/highlight.tsx @@ -16,7 +16,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) let programs: any[] = [] for (const type of types) { - queryParams.set('fq', `type_value_s:${type}`) + queryParams.set('fq', `type_value_s:${type}`) + queryParams.append('fq', `active_b:true`) + const response = await fetch(`${SOLR_HOST}/solr/promotion_program_lines/select?${queryParams.toString()}`) const data: SolrResponse<any[]> = await response.json() programs.push(...data.response.docs) diff --git a/src-migrate/pages/shop/cart/cart.module.css b/src-migrate/pages/shop/cart/cart.module.css index d523a55a..353b131a 100644 --- a/src-migrate/pages/shop/cart/cart.module.css +++ b/src-migrate/pages/shop/cart/cart.module.css @@ -19,7 +19,7 @@ } .summary-wrapper { - @apply w-full md:w-1/4 md:pl-6 mt-6 md:mt-0; + @apply w-full md:w-1/4 md:pl-6 mt-6 md:mt-0 bottom-0 md:sticky sticky bg-white; } .summary { diff --git a/src-migrate/pages/shop/cart/index.tsx b/src-migrate/pages/shop/cart/index.tsx index 9ec58a48..d1a6a6ff 100644 --- a/src-migrate/pages/shop/cart/index.tsx +++ b/src-migrate/pages/shop/cart/index.tsx @@ -10,11 +10,16 @@ import { useCartStore } from '~/modules/cart/stores/useCartStore' import CartItem from '~/modules/cart/components/Item' import CartSummary from '~/modules/cart/components/Summary' import clsxm from '~/libs/clsxm' +import useDevice from '@/core/hooks/useDevice' +import CartSummaryMobile from '~/modules/cart/components/CartSummaryMobile' +import Image from '~/components/ui/image' const CartPage = () => { const auth = getAuth() const { loadCart, cart, summary } = useCartStore() + + const useDivvice = useDevice(); useEffect(() => { if (typeof auth === 'object' && !cart) loadCart(auth.id) @@ -60,12 +65,22 @@ const CartPage = () => { <div className={style['items']}> {cart?.products.map((item) => <CartItem key={item.id} item={item} />)} + + {cart?.products?.length === 0 && ( + <div className='flex flex-col items-center'> + <Image src='/images/empty_cart.svg' alt='Empty Cart' width={450} height={450} /> + <div className='text-title-sm md:text-title-lg text-center font-semibold'>Keranjangnya masih kosong nih</div> + <div className='text-body-2 md:text-body-1 text-center mt-3'>Yuk, tambahin barang-barang yang kamu mau ke keranjang sekarang!<br />Ada banyak potongan belanjanya pakai kode voucher</div> + <Link href='/' className='btn-solid-red rounded-full text-body-1 mt-6'>Mulai Belanja</Link> + </div> + )} </div> </div> <div className={style['summary-wrapper']}> <div className={style['summary']}> - <CartSummary {...summary} isLoaded={!!cart} /> + {useDivvice.isMobile && <CartSummaryMobile {...summary} isLoaded={!!cart} />} + {!useDivvice.isMobile && <CartSummary {...summary} isLoaded={!!cart} />} <div className={style['summary-buttons']}> <Tooltip label={hasSelectedPromo && 'Barang promo tidak dapat dibuat quotation'}> |
