diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2024-11-29 10:55:52 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2024-11-29 10:55:52 +0700 |
| commit | ac83b0ea5afd82194f38fbc913678e16a81b5c2c (patch) | |
| tree | 4373da17bcb43d752b7bd888e28ba906099a19aa /src | |
| parent | c7b437cd0541cde9e2a829ec3c5689dc237505a8 (diff) | |
| parent | b4861f70338adb3960125923a7e6e4032279c88e (diff) | |
Merge branch 'new-release' into Feature/pengajuan-tempo
# Conflicts:
# src/lib/auth/components/Menu.jsx
# src/pages/my/menu.jsx
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/components/elements/Sidebar/Sidebar.jsx | 2 | ||||
| -rw-r--r-- | src/lib/auth/components/Menu.jsx | 14 | ||||
| -rw-r--r-- | src/lib/flashSale/components/FlashSale.jsx | 36 | ||||
| -rw-r--r-- | src/lib/product/components/ProductCard.jsx | 5 | ||||
| -rw-r--r-- | src/lib/transaction/api/checkoutPoApi.js | 19 | ||||
| -rw-r--r-- | src/lib/transaction/components/Transaction.jsx | 132 | ||||
| -rw-r--r-- | src/lib/treckingAwb/component/Manifest.jsx | 1 | ||||
| -rw-r--r-- | src/pages/api/flashsale-header.js | 40 | ||||
| -rw-r--r-- | src/pages/api/search-flashsale.js | 45 | ||||
| -rw-r--r-- | src/pages/my/menu.jsx | 4 |
10 files changed, 258 insertions, 40 deletions
diff --git a/src/core/components/elements/Sidebar/Sidebar.jsx b/src/core/components/elements/Sidebar/Sidebar.jsx index ddae3e20..08498759 100644 --- a/src/core/components/elements/Sidebar/Sidebar.jsx +++ b/src/core/components/elements/Sidebar/Sidebar.jsx @@ -140,7 +140,7 @@ const Sidebar = ({ active, close }) => { <SidebarLink className={itemClassName} href='/tentang-kami'> Tentang Indoteknik </SidebarLink> - <SidebarLink className={itemClassName} href='/contact-us'> + <SidebarLink className={itemClassName} href='/hubungi-kami'> Hubungi Kami </SidebarLink> <button diff --git a/src/lib/auth/components/Menu.jsx b/src/lib/auth/components/Menu.jsx index b288eae9..18d8df91 100644 --- a/src/lib/auth/components/Menu.jsx +++ b/src/lib/auth/components/Menu.jsx @@ -2,12 +2,18 @@ import Link from '@/core/components/elements/Link/Link'; import { useRouter } from 'next/router'; import ImageNext from 'next/image'; import whatsappUrl from '@/core/utils/whatsappUrl'; - +import { deleteAuth } from '@/core/utils/auth'; const Menu = () => { const router = useRouter(); const routeStartWith = (route) => router.pathname.startsWith(route); + const logout = async () => { + deleteAuth().then(() => { + router.push('/login'); + }); + }; + return ( <div className='grid grid-cols-1 bg-white border border-gray_r-6 rounded py-2 px-4 sticky top-48'> <div className='mt-4 mb-1 font-medium'>Menu</div> @@ -107,7 +113,11 @@ const Menu = () => { <p>Profil Saya</p> </div> </LinkItem> - <button type='button' className='text-gray_r-12/80 p-2 text-left'> + <button + type='button' + onClick={logout} + className='text-gray_r-12/80 p-2 text-left' + > <div className='flex gap-x-3 items-center'> <ImageNext src='/images/icon/icon_logout.svg' diff --git a/src/lib/flashSale/components/FlashSale.jsx b/src/lib/flashSale/components/FlashSale.jsx index 8be1d7a6..6d90cad7 100644 --- a/src/lib/flashSale/components/FlashSale.jsx +++ b/src/lib/flashSale/components/FlashSale.jsx @@ -2,10 +2,8 @@ import Image from 'next/image'; import { useEffect, useState } from 'react'; import CountDown from '@/core/components/elements/CountDown/CountDown'; -import productSearchApi from '@/lib/product/api/productSearchApi'; import ProductSlider from '@/lib/product/components/ProductSlider'; -import flashSaleApi from '../api/flashSaleApi'; import { FlashSaleSkeleton } from '../skeleton/FlashSaleSkeleton'; const FlashSale = () => { @@ -14,10 +12,14 @@ const FlashSale = () => { useEffect(() => { const loadFlashSales = async () => { - const dataFlashSales = await flashSaleApi(); - setFlashSales(dataFlashSales); + const res = await fetch('/api/flashsale-header'); + const { data } = await res.json(); + if (data) { + setFlashSales(data); + } setIsLoading(false); }; + loadFlashSales(); }, []); @@ -53,7 +55,10 @@ const FlashSale = () => { height={48} className='w-full rounded mb-4 block sm:hidden' /> - <FlashSaleProduct flashSaleId={flashSale.pricelistId} /> + <FlashSaleProduct + flashSaleId={flashSale.pricelistId} + duration={flashSale.duration} + /> </div> </div> ))} @@ -63,19 +68,24 @@ const FlashSale = () => { ); }; -const FlashSaleProduct = ({ flashSaleId }) => { +const FlashSaleProduct = ({ flashSaleId, duration }) => { const [products, setProducts] = useState(null); - useEffect(() => { + const data_search = new URLSearchParams({ + query: `fq=flashsale_id_i:${flashSaleId}&fq=flashsale_price_f:[1 TO *]&limit=500&orderBy=flashsale-price-asc&source=similar`, + operation: 'AND', + duration: `${duration}`, + }); const loadProducts = async () => { - const dataProducts = await productSearchApi({ - query: `fq=flashsale_id_i:${flashSaleId}&fq=flashsale_price_f:[1 TO *]&limit=500&orderBy=flashsale-price-asc&source=similar`, - operation: 'AND', - }); - setProducts(dataProducts.response); + const res = await fetch( + `/api/search-flashsale?${data_search.toString()}` + ); + const { data } = await res.json(); + setProducts(data.response); }; + loadProducts(); - }, [flashSaleId]); + }, []); return <ProductSlider products={products} />; }; diff --git a/src/lib/product/components/ProductCard.jsx b/src/lib/product/components/ProductCard.jsx index 3e6a6913..16e20703 100644 --- a/src/lib/product/components/ProductCard.jsx +++ b/src/lib/product/components/ProductCard.jsx @@ -18,7 +18,10 @@ const ProductCard = ({ product, simpleTitle, variant = 'vertical' }) => { const [discount, setDiscount] = useState(0); const { isDesktop, isMobile } = useDevice(); let voucherPastiHemat = 0; - voucherPastiHemat = product?.newVoucherPastiHemat[0]; + voucherPastiHemat = product?.newVoucherPastiHemat[0] + ? product?.newVoucherPastiHemat[0] + : product?.newVoucherPastiHemat; + console.log('voucherPastiHemat', voucherPastiHemat); const callForPriceWhatsapp = whatsappUrl('product', { name: product.name, diff --git a/src/lib/transaction/api/checkoutPoApi.js b/src/lib/transaction/api/checkoutPoApi.js index 04421368..3376e773 100644 --- a/src/lib/transaction/api/checkoutPoApi.js +++ b/src/lib/transaction/api/checkoutPoApi.js @@ -1,13 +1,14 @@ -import odooApi from '@/core/api/odooApi' -import { getAuth } from '@/core/utils/auth' +import odooApi from '@/core/api/odooApi'; +import { getAuth } from '@/core/utils/auth'; -const checkoutPoApi = async ({ id }) => { - const auth = getAuth() +const checkoutPoApi = async ({ id, status }) => { + const auth = getAuth(); const dataCheckout = await odooApi( 'POST', - `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout` - ) - return dataCheckout -} + `/api/v1/partner/${auth?.partnerId}/sale_order/${id}/checkout`, + { status } + ); + return dataCheckout; +}; -export default checkoutPoApi +export default checkoutPoApi; diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx index d001c7f4..f5dc507a 100644 --- a/src/lib/transaction/components/Transaction.jsx +++ b/src/lib/transaction/components/Transaction.jsx @@ -38,7 +38,9 @@ import aprpoveApi from '../api/approveApi'; import rejectApi from '../api/rejectApi'; import rejectProductApi from '../api/rejectProductApi'; import { useRouter } from 'next/router'; - +import { gtagPurchase } from '@/core/utils/googleTag'; +import { deleteItemCart } from '@/core/utils/cart'; +import axios from 'axios'; const Transaction = ({ id }) => { const router = useRouter(); const [isModalOpen, setIsModalOpen] = useState(false); @@ -46,9 +48,8 @@ const Transaction = ({ id }) => { const [reason, setReason] = useState(''); const auth = useAuth(); const { transaction } = useTransaction({ id }); - const statusApprovalWeb = transaction.data?.approvalStep; - + const [isLoading, setIsLoading] = useState(false); const { queryAirwayBill } = useAirwayBill({ orderId: id }); const [airwayBillPopup, setAirwayBillPopup] = useState(null); @@ -84,8 +85,26 @@ const Transaction = ({ id }) => { }; const [cancelTransaction, setCancelTransaction] = useState(false); + const [continueNoPo, setContinueNoPo] = useState(false); + const [continueTransaction, setContinueTransaction] = useState(false); const openCancelTransaction = () => setCancelTransaction(true); + const openContinueTransaction = () => { + if (auth.partnerTempo) { + checkout(); + } else { + if (!transaction.data?.purchaseOrderFile) { + setContinueTransaction(true); + } else { + checkoutNoPO(); + } + } + }; + // const ContinueTransaction = () => { + // setContinueNoPo(true); + // checkoutNoPO(); + // }; const closeCancelTransaction = () => setCancelTransaction(false); + const closeContinueTransaction = () => setContinueTransaction(false); const [rejectTransaction, setRejectTransaction] = useState(false); @@ -101,15 +120,70 @@ const Transaction = ({ id }) => { } closeCancelTransaction(); }; - const checkout = async () => { if (!transaction.data?.purchaseOrderFile) { toast.error('Mohon upload dokumen PO anda sebelum melanjutkan pesanan'); return; } - await checkoutPoApi({ id }); + await checkoutPoApi({ id, status: true }); + toast.success('Berhasil melanjutkan pesanan'); + transaction.refetch(); + }; + + const checkoutNoPO = async () => { + setIsLoading(true); + gtagPurchase( + transaction.data.products, + transaction.data.deliveryAmount, + transaction.data.name + ); + + gtag('event', 'conversion', { + send_to: 'AW-954540379/nDymCL3BhaQYENvClMcD', + value: + transaction.data?.amountTotal + + Math.round(parseInt(transaction.data.deliveryAmount * 1.1) / 1000) * + 1000, + currency: 'IDR', + transaction_id: transaction.data.id, + }); + + for (const product of transaction.data.products) + deleteItemCart({ productId: product.id }); + if (transaction.data?.amountTotal > 0) { + const payment = await axios.post( + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/midtrans-payment?transactionId=${transaction.data.id}` + ); + setIsLoading(false); + window.location.href = payment.data.redirectUrl; + } else { + window.location.href = `${ + process.env.NEXT_PUBLIC_SELF_HOST + }/shop/checkout/success?order_id=${transaction.data.name.replace( + /\//g, + '-' + )}`; + } toast.success('Berhasil melanjutkan pesanan'); transaction.refetch(); + + /* const midtrans = async () => { + for (const product of products) deleteItemCart({ productId: product.id }); + if (grandTotal > 0) { + const payment = await axios.post( + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/midtrans-payment?transactionId=${isCheckouted.id}` + ); + setIsLoading(false); + window.location.href = payment.data.redirectUrl; + } else { + window.location.href = `${ + process.env.NEXT_PUBLIC_SELF_HOST + }/shop/checkout/success?order_id=${isCheckouted.name.replace( + /\//g, + '-' + )}`; + } + };*/ }; const handleApproval = async () => { @@ -208,6 +282,32 @@ const Transaction = ({ id }) => { transaction.data?.name && ( <> <BottomPopup + active={continueTransaction} + close={closeContinueTransaction} + title='Lanjutkan Transaksi' + > + <div className='leading-7 text-gray_r-12/80'> + Apakah anda yakin melanjutkan tanpa upload PO?{' '} + <span className='underline'>{transaction.data?.name}</span>? + </div> + <div className='flex justify-end mt-6 gap-x-4'> + <button + className='btn-solid-red w-full md:w-fit' + type='button' + onClick={checkoutNoPO} + > + Ya, Lanjutkan + </button> + <button + className='btn-light w-full md:w-fit' + type='button' + onClick={closeContinueTransaction} + > + Batal + </button> + </div> + </BottomPopup> + <BottomPopup active={cancelTransaction} close={closeCancelTransaction} title='Batalkan Transaksi' @@ -469,7 +569,10 @@ const Transaction = ({ id }) => { )} {transaction.data?.status == 'draft' && !auth?.feature?.soApproval && ( - <button className='btn-yellow w-full mt-4' onClick={checkout}> + <button + className='btn-yellow w-full mt-4' + onClick={openContinueTransaction} + > Lanjutkan Transaksi </button> )} @@ -563,7 +666,10 @@ const Transaction = ({ id }) => { )} {transaction.data?.status == 'draft' && !auth?.feature.soApproval && ( - <button className='btn-yellow' onClick={checkout}> + <button + className='btn-yellow' + onClick={openContinueTransaction} + > Lanjutkan Transaksi </button> )} @@ -778,10 +884,14 @@ const Transaction = ({ id }) => { ? `| ${product?.attributes.join(', ')}` : ''} </div> - <div className='text-[10px] text-red-500 italic mt-2'> - {product.availableQuantity} barang ini bisa di - pickup maksimal pukul 16.00 - </div> + {product.soQty && product.reservedStockQty && ( + <div className='text-[10px] text-red-500 italic mt-2'> + {product.soQty !== product.reservedStockQty + ? 'Barang sedang disiapkan' + : `${product.reservedStockQty} barang bisa di + kirim/pickup`} + </div> + )} </div> </td> {/* <td> diff --git a/src/lib/treckingAwb/component/Manifest.jsx b/src/lib/treckingAwb/component/Manifest.jsx index 02d0bc7a..87e01e38 100644 --- a/src/lib/treckingAwb/component/Manifest.jsx +++ b/src/lib/treckingAwb/component/Manifest.jsx @@ -10,7 +10,6 @@ import { list } from 'postcss'; const Manifest = ({ idAWB, closePopup }) => { const [manifests, setManifests] = useState(null); const [isLoading, setIsLoading] = useState(false); - console.log('manifests', manifests); const formatCustomDate = (date) => { const months = [ 'Jan', diff --git a/src/pages/api/flashsale-header.js b/src/pages/api/flashsale-header.js new file mode 100644 index 00000000..31f8efdd --- /dev/null +++ b/src/pages/api/flashsale-header.js @@ -0,0 +1,40 @@ +import odooApi from '@/core/api/odooApi'; +import { createClient } from 'redis'; + +const client = createClient(); + +client.on('error', (err) => console.error('Redis Client Error', err)); + +const connectRedis = async () => { + if (!client.isOpen) { + await client.connect(); + } +}; + +export default async function handler(req, res) { + try { + await connectRedis(); + const cacheKey = `flashsale_header`; + // await client.del(cacheKey); + let cachedData = await client.get(cacheKey); + + if (cachedData) { + const data = JSON.parse(cachedData); + return res.status(200).json({ data }); + } else { + const flashSale = await odooApi('GET', `/api/v1/flashsale/header`); + + await client.set( + cacheKey, + JSON.stringify(flashSale), + 'EX', + flashSale.duration + ); + cachedData = await client.get(cacheKey); + return res.status(200).json({ data: cachedData }); + } + } catch (error) { + console.error('Error interacting with Redis or fetching data:', error); + return res.status(500).json({ error: 'Internal Server Error' }); + } +} diff --git a/src/pages/api/search-flashsale.js b/src/pages/api/search-flashsale.js new file mode 100644 index 00000000..d9e56c83 --- /dev/null +++ b/src/pages/api/search-flashsale.js @@ -0,0 +1,45 @@ +import odooApi from '@/core/api/odooApi'; +import { createClient } from 'redis'; +import _ from 'lodash-contrib'; +import axios from 'axios'; + +const client = createClient(); + +client.on('error', (err) => console.error('Redis Client Error', err)); + +const connectRedis = async () => { + if (!client.isOpen) { + await client.connect(); + } +}; + +export default async function handler(req, res) { + const { query, operation, duration } = req.query; + try { + await connectRedis(); + const cacheKey = `flashsale_product`; + // await client.del(cacheKey); + let cachedData = await client.get(cacheKey); + + if (cachedData) { + const data = JSON.parse(cachedData); + return res.status(200).json({ data }); + } else { + const dataProductSearch = await axios( + `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/search?${query}&operation=${operation}]` + ); + + await client.set( + cacheKey, + JSON.stringify(dataProductSearch.data), + 'EX', + duration + ); + cachedData = await client.get(cacheKey); + return res.status(200).json({ data: cachedData }); + } + } catch (error) { + console.error('Error interacting with Redis or fetching data:', error); + return res.status(500).json({ error: 'Internal Server Error' }); + } +} diff --git a/src/pages/my/menu.jsx b/src/pages/my/menu.jsx index 63b4d35c..407e400f 100644 --- a/src/pages/my/menu.jsx +++ b/src/pages/my/menu.jsx @@ -8,7 +8,7 @@ import { ChevronRightIcon, UserIcon } from '@heroicons/react/24/solid'; import { signOut, useSession } from 'next-auth/react'; import { useRouter } from 'next/router'; import ImageNext from 'next/image'; - +import whatsappUrl from '@/core/utils/whatsappUrl'; export default function Menu() { const auth = useAuth(); const router = useRouter(); @@ -118,7 +118,7 @@ export default function Menu() { <MenuHeader>Pusat Bantuan</MenuHeader> <div className='divide-y divide-gray_r-6 border-y border-gray_r-6 mt-4'> - <LinkItem href='/'> + <LinkItem href={whatsappUrl('', '', '')}> {' '} <div className='flex gap-x-3 items-center'> <ImageNext |
