summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-migrate/modules/register/components/TermCondition.tsx48
-rw-r--r--src-migrate/types/auth.ts9
-rw-r--r--src/core/components/elements/Sidebar/Sidebar.jsx2
-rw-r--r--src/lib/auth/components/Menu.jsx14
-rw-r--r--src/lib/flashSale/components/FlashSale.jsx36
-rw-r--r--src/lib/product/components/ProductCard.jsx5
-rw-r--r--src/lib/transaction/api/checkoutPoApi.js19
-rw-r--r--src/lib/transaction/components/Transaction.jsx132
-rw-r--r--src/lib/treckingAwb/component/Manifest.jsx1
-rw-r--r--src/pages/api/flashsale-header.js40
-rw-r--r--src/pages/api/search-flashsale.js45
-rw-r--r--src/pages/my/menu.jsx4
12 files changed, 294 insertions, 61 deletions
diff --git a/src-migrate/modules/register/components/TermCondition.tsx b/src-migrate/modules/register/components/TermCondition.tsx
index d54fe921..44275917 100644
--- a/src-migrate/modules/register/components/TermCondition.tsx
+++ b/src-migrate/modules/register/components/TermCondition.tsx
@@ -1,34 +1,48 @@
-import { Checkbox } from '@chakra-ui/react'
-import React from 'react'
-import { Modal } from '~/components/ui/modal'
-import { useRegisterStore } from "../stores/useRegisterStore";
-import PageContent from '~/modules/page-content'
+import { Checkbox } from '@chakra-ui/react';
+import React from 'react';
+import { Modal } from '~/components/ui/modal';
+import { useRegisterStore } from '../stores/useRegisterStore';
+
+import dynamic from 'next/dynamic';
+const PageContent = dynamic(
+ () => import('@/lib/content/components/PageContent')
+);
const TermCondition = () => {
- const { isOpenTNC, closeTNC, isCheckedTNC, toggleCheckTNC, openTNC } = useRegisterStore()
+ const { isOpenTNC, closeTNC, isCheckedTNC, toggleCheckTNC, openTNC } =
+ useRegisterStore();
return (
<>
- <div className="mt-4 flex items-center gap-x-2">
- <Checkbox id='tnc' name='tnc' colorScheme='red' isChecked={isCheckedTNC} onChange={toggleCheckTNC} />
+ <div className='mt-4 flex items-center gap-x-2'>
+ <Checkbox
+ id='tnc'
+ name='tnc'
+ colorScheme='red'
+ isChecked={isCheckedTNC}
+ onChange={toggleCheckTNC}
+ />
<div>
- <label htmlFor="tnc" className="cursor-pointer">Dengan ini saya menyetujui</label>
- {' '}
+ <label htmlFor='tnc' className='cursor-pointer'>
+ Dengan ini saya menyetujui
+ </label>{' '}
<span
- className="font-medium text-danger-500 cursor-pointer"
+ className='font-medium text-danger-500 cursor-pointer'
onClick={openTNC}
>
syarat dan ketentuan
</span>
- <label htmlFor="tnc" className="ml-2 cursor-pointer">yang berlaku</label>
+ <label htmlFor='tnc' className='ml-2 cursor-pointer'>
+ yang berlaku
+ </label>
</div>
</div>
- <Modal active={isOpenTNC} close={closeTNC} >
- <PageContent path='/register#tnd' />
+ <Modal active={isOpenTNC} close={closeTNC}>
+ <PageContent path='/registerTnd' />
</Modal>
</>
- )
-}
+ );
+};
-export default TermCondition \ No newline at end of file
+export default TermCondition;
diff --git a/src-migrate/types/auth.ts b/src-migrate/types/auth.ts
index 593e120f..8feac2e1 100644
--- a/src-migrate/types/auth.ts
+++ b/src-migrate/types/auth.ts
@@ -16,10 +16,11 @@ export type AuthProps = {
company: boolean;
pricelist: string | null;
token: string;
- feature : {
- onlyReadyStock : boolean,
- soApproval : boolean
- }
+ feature: {
+ onlyReadyStock: boolean;
+ soApproval: boolean;
+ };
+ partner_tempo: boolean;
};
export type AuthApiProps = OdooApiRes<AuthProps>;
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