summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-migrate/modules/cart/components/CartSummaryMobile.tsx3
-rw-r--r--src-migrate/modules/cart/components/Summary.tsx3
-rw-r--r--src-migrate/modules/cart/stores/useCartStore.ts14
-rw-r--r--src-migrate/modules/product-card/components/ProductCard.tsx3
-rw-r--r--src-migrate/modules/product-detail/components/PriceAction.tsx3
-rw-r--r--src-migrate/modules/register/components/FormBisnis.tsx7
-rw-r--r--src-migrate/modules/register/components/RegistrasiBisnis.tsx19
-rw-r--r--src-migrate/modules/register/index.tsx54
-rw-r--r--src-migrate/validations/auth.ts2
-rw-r--r--src/api/promoApi.js4
-rw-r--r--src/core/components/elements/Footer/BasicFooter.jsx12
-rw-r--r--src/core/utils/googleTag.js4
-rw-r--r--src/lib/cart/components/Cart.jsx3
-rw-r--r--src/lib/cart/components/CartOld.jsx3
-rw-r--r--src/lib/cart/components/Cartheader.jsx3
-rw-r--r--src/lib/checkout/components/Checkout.jsx6
-rw-r--r--src/lib/checkout/components/CheckoutOld.jsx2
-rw-r--r--src/lib/checkout/email/FinishCheckoutEmail.jsx5
-rw-r--r--src/lib/flashSale/components/FlashSale.jsx14
-rw-r--r--src/lib/form/components/KunjunganSales.jsx215
-rw-r--r--src/lib/form/components/KunjunganService.jsx361
-rw-r--r--src/lib/form/components/Merchant.jsx56
-rw-r--r--src/lib/form/components/RequestForQuotation.jsx215
-rw-r--r--src/lib/form/components/SuratDukungan.jsx33
-rw-r--r--src/lib/home/components/ServiceList.jsx2
-rw-r--r--src/lib/invoice/components/Invoice.jsx5
-rw-r--r--src/lib/quotation/components/Quotation.jsx7
-rw-r--r--src/lib/transaction/components/Transaction.jsx5
-rw-r--r--src/pages/api/flashsale-header.js12
-rw-r--r--src/pages/api/shop/midtrans-payment.js1
-rw-r--r--src/pages/daftar-merchant.jsx (renamed from src/pages/my/daftar-merchant.jsx)0
-rw-r--r--src/pages/google_merchant/products/[page].js5
-rw-r--r--src/pages/kunjungan-sales.jsx (renamed from src/pages/my/kunjungan-sales.jsx)0
-rw-r--r--src/pages/kunjungan-service.jsx (renamed from src/pages/my/kunjungan-service.jsx)0
-rw-r--r--src/pages/my/pembayaran-tempo.jsx15
-rw-r--r--src/pages/pembayaran-tempo-detail.jsx13
-rw-r--r--src/pages/pembayaran-tempo.jsx14
-rw-r--r--src/pages/request-for-quotation.jsx (renamed from src/pages/my/request-for-quotation.jsx)0
-rw-r--r--src/pages/sitemap/homepage.xml.js28
-rw-r--r--src/pages/surat-dukungan.jsx (renamed from src/pages/my/surat-dukungan.jsx)0
40 files changed, 713 insertions, 438 deletions
diff --git a/src-migrate/modules/cart/components/CartSummaryMobile.tsx b/src-migrate/modules/cart/components/CartSummaryMobile.tsx
index d9f72e0e..02258204 100644
--- a/src-migrate/modules/cart/components/CartSummaryMobile.tsx
+++ b/src-migrate/modules/cart/components/CartSummaryMobile.tsx
@@ -29,6 +29,7 @@ const CartSummaryMobile = ({
isLoaded = false,
}: Props) => {
const [showPopup, setShowPopup] = useState(false);
+ const PPN : number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
return (
<>
<BottomPopup
@@ -63,7 +64,7 @@ const CartSummaryMobile = ({
</Skeleton>
<Skeleton isLoaded={isLoaded} className={style.line}>
- <span className={style.label}>Tax 11%</span>
+ <span className={style.label}>Tax {((PPN - 1) * 100).toFixed(0)}%</span>
<span className={style.value}>Rp {formatCurrency(tax || 0)}</span>
</Skeleton>
diff --git a/src-migrate/modules/cart/components/Summary.tsx b/src-migrate/modules/cart/components/Summary.tsx
index 2e55c8df..0af5ab18 100644
--- a/src-migrate/modules/cart/components/Summary.tsx
+++ b/src-migrate/modules/cart/components/Summary.tsx
@@ -25,6 +25,7 @@ const CartSummary = ({
grandTotal,
isLoaded = false,
}: Props) => {
+ const PPN : number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
return (
<>
<div className='text-h-sm font-medium'>Ringkasan Pesanan</div>
@@ -50,7 +51,7 @@ const CartSummary = ({
</Skeleton>
<Skeleton isLoaded={isLoaded} className={style.line}>
- <span className={style.label}>Tax 11%</span>
+ <span className={style.label}>Tax {((PPN - 1) * 100).toFixed(0)}%</span>
<span className={style.value}>Rp {formatCurrency(tax || 0)}</span>
</Skeleton>
diff --git a/src-migrate/modules/cart/stores/useCartStore.ts b/src-migrate/modules/cart/stores/useCartStore.ts
index c2ebf50f..e7d2cdd3 100644
--- a/src-migrate/modules/cart/stores/useCartStore.ts
+++ b/src-migrate/modules/cart/stores/useCartStore.ts
@@ -43,17 +43,20 @@ export const useCartStore = create<State & Action>((set, get) => ({
updateCartItem: (updatedCart) => {
const cart = get().cart;
if (!cart) return;
-
+
set({ cart: updatedCart });
const summary = computeSummary(updatedCart);
set({ summary });
},
-
+
}));
const computeSummary = (cart: CartProps) => {
let subtotal = 0;
let discount = 0;
+
+ const PPN: number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
+
for (const item of cart?.products) {
if (!item.selected) continue;
@@ -67,8 +70,9 @@ const computeSummary = (cart: CartProps) => {
discount += price - item.price.price_discount * item.quantity;
}
let total = subtotal - discount;
- let tax = Math.round(total * 0.11);
- let grandTotal = total + tax;
+ let grandTotal = total * PPN;
+ let tax = grandTotal - total;
+ // let grandTotal = total + tax;
- return { subtotal, discount, total, tax, grandTotal };
+ return { subtotal, discount, total, grandTotal, tax };
}; \ No newline at end of file
diff --git a/src-migrate/modules/product-card/components/ProductCard.tsx b/src-migrate/modules/product-card/components/ProductCard.tsx
index a439cdc8..8d3b55fb 100644
--- a/src-migrate/modules/product-card/components/ProductCard.tsx
+++ b/src-migrate/modules/product-card/components/ProductCard.tsx
@@ -16,6 +16,7 @@ type Props = {
layout?: 'vertical' | 'horizontal';
};
+const PPN : number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
const ProductCard = ({ product, layout = 'vertical' }: Props) => {
const utmSource = useUtmSource();
const { isDesktop, isMobile } = useDevice();
@@ -127,7 +128,7 @@ const ProductCard = ({ product, layout = 'vertical' }: Props) => {
<div className={style['price-inc']}>
Inc PPN: Rp{' '}
- {formatCurrency(Math.round(product.lowest_price.price * 1.11))}
+ {formatCurrency(Math.round(product.lowest_price.price * PPN))}
</div>
<div className='h-1' />
diff --git a/src-migrate/modules/product-detail/components/PriceAction.tsx b/src-migrate/modules/product-detail/components/PriceAction.tsx
index 0b27b1b3..9348bbfb 100644
--- a/src-migrate/modules/product-detail/components/PriceAction.tsx
+++ b/src-migrate/modules/product-detail/components/PriceAction.tsx
@@ -17,6 +17,7 @@ type Props = {
product: IProductDetail;
};
+const PPN : number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
const PriceAction = ({ product }: Props) => {
const {
activePrice,
@@ -101,7 +102,7 @@ const PriceAction = ({ product }: Props) => {
<div className='h-1' />
<div className={style['secondary-text']}>
Termasuk PPN: Rp{' '}
- {formatCurrency(Math.round(activePrice.price_discount * 1.11))}
+ {formatCurrency(Math.round(activePrice.price_discount * PPN))}
</div>
</>
)}
diff --git a/src-migrate/modules/register/components/FormBisnis.tsx b/src-migrate/modules/register/components/FormBisnis.tsx
index e4cf3442..12397956 100644
--- a/src-migrate/modules/register/components/FormBisnis.tsx
+++ b/src-migrate/modules/register/components/FormBisnis.tsx
@@ -1,9 +1,5 @@
import { ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
-import { useMutation } from 'react-query';
import { useRegisterStore } from '../stores/useRegisterStore';
-import { RegisterProps } from '~/types/auth';
-import { registerUser } from '~/services/auth';
-import { useRouter } from 'next/router';
import {
Button,
Checkbox,
@@ -11,12 +7,10 @@ import {
color,
useToast,
} from '@chakra-ui/react';
-import Link from 'next/link';
import getFileBase64 from '@/core/utils/getFileBase64';
import { Controller, useForm } from 'react-hook-form';
import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
import odooApi from '~/libs/odooApi';
-import { toast } from 'react-hot-toast';
import { EyeIcon } from '@heroicons/react/24/outline';
import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
import Image from 'next/image';
@@ -60,7 +54,6 @@ const form: React.FC<FormProps> = ({
const [industries, setIndustries] = useState<industry_id[]>([]);
const [companyTypes, setCompanyTypes] = useState<companyType[]>([]);
- const router = useRouter();
const toast = useToast();
const emailRef = useRef<HTMLInputElement>(null);
diff --git a/src-migrate/modules/register/components/RegistrasiBisnis.tsx b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
index ce4d3972..40caed65 100644
--- a/src-migrate/modules/register/components/RegistrasiBisnis.tsx
+++ b/src-migrate/modules/register/components/RegistrasiBisnis.tsx
@@ -1,19 +1,10 @@
-import { ChangeEvent, useEffect, useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
import FormBisnis from './FormBisnis';
import Form from './Form';
-import TermCondition from './TermCondition';
-import FormCaptcha from './FormCaptcha';
import { Radio, RadioGroup, Stack, Divider, Button } from '@chakra-ui/react';
import React from 'react';
import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
import { useRegisterStore } from '../stores/useRegisterStore';
-import { useMutation } from 'react-query';
-import { RegisterProps } from '~/types/auth';
-import { registerUser } from '~/services/auth';
-import router from 'next/router';
-import { useRouter } from 'next/router';
-import { UseToastOptions, useToast } from '@chakra-ui/react';
-import Link from 'next/link';
interface FormProps {
chekValid: boolean;
buttonSubmitClick: boolean;
@@ -28,13 +19,7 @@ const RegistrasiBisnis: React.FC<FormProps> = ({
const [isBisnisClicked, setisBisnisClicked] = useState(true);
const [selectedValue, setSelectedValue] = useState('PKP');
const [selectedValueBisnis, setSelectedValueBisnis] = useState('false');
- const { form, isCheckedTNC, isValidCaptcha, errors, validate, updateForm } =
- useRegisterStore();
- const isFormValid = useMemo(() => Object.keys(errors).length === 0, [errors]);
- const toast = useToast();
- const mutation = useMutation({
- mutationFn: (data: RegisterProps) => registerUser(data),
- });
+ const { validate, updateForm } = useRegisterStore();
useEffect(() => {
if (selectedValue === 'PKP') {
diff --git a/src-migrate/modules/register/index.tsx b/src-migrate/modules/register/index.tsx
index 2cc8a28b..39f4771c 100644
--- a/src-migrate/modules/register/index.tsx
+++ b/src-migrate/modules/register/index.tsx
@@ -1,20 +1,24 @@
-import PageContent from '~/modules/page-content';
-import RegistrasiIndividu from './components/RegistrasiIndividu';
-import RegistrasiBisnis from './components/RegistrasiBisnis';
+import dynamic from 'next/dynamic';
import Link from 'next/link';
import Image from 'next/image';
-import IndoteknikLogo from '~/images/logo.png';
-import AccountActivation from '../account-activation';
import { useMemo, useState } from 'react';
-import { useRegisterStore } from './stores/useRegisterStore';
-import FormCaptcha from './components/FormCaptcha';
-import TermCondition from './components/TermCondition';
+import { useRouter } from 'next/router';
import { Button } from '@chakra-ui/react';
-import { useMutation } from 'react-query';
import { UseToastOptions, useToast } from '@chakra-ui/react';
-import { RegisterProps } from '~/types/auth';
+import { useMutation } from 'react-query';
+import { useRegisterStore } from './stores/useRegisterStore';
import { registerUser } from '~/services/auth';
-import { useRouter } from 'next/router';
+import IndoteknikLogo from '~/images/logo.png';
+import { RegisterProps } from '~/types/auth';
+
+const PageContent = dynamic(() => import('~/modules/page-content'));
+const RegistrasiIndividu = dynamic(
+ () => import('./components/RegistrasiIndividu')
+);
+const RegistrasiBisnis = dynamic(() => import('./components/RegistrasiBisnis'));
+const FormCaptcha = dynamic(() => import('./components/FormCaptcha'));
+const TermCondition = dynamic(() => import('./components/TermCondition'));
+const AccountActivation = dynamic(() => import('../account-activation'));
const LOGO_WIDTH = 150;
const LOGO_HEIGHT = LOGO_WIDTH / 3;
@@ -47,6 +51,7 @@ const Register = () => {
setIsIndividuClicked(false);
setIsBisnisClicked(true);
};
+
const handleSubmit = async () => {
if (!isFormValid) {
setNotValid(true);
@@ -98,10 +103,11 @@ const Register = () => {
break;
}
};
+
return (
<div className='container'>
<div className='grid grid-cols-1 md:grid-cols-2 gap-x-8 pt-10 px-2 md:pt-16'>
- <section className=''>
+ <section>
<div className='px-8 py-4 border'>
<Link href='/' className='block md:hidden'>
<Image
@@ -126,7 +132,7 @@ const Register = () => {
</label>
<div className='grid grid-cols-2 gap-x-3 mt-2 h-14 font-bold text-black hover:cursor-pointer'>
<div
- className={` border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${
+ className={`border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${
isIndividuClicked ? 'bg-red-500 text-white' : ''
}`}
onClick={handleIndividuClick}
@@ -134,7 +140,7 @@ const Register = () => {
<p>Individu</p>
</div>
<div
- className={` border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${
+ className={`border rounded-md flex justify-center items-center transition-colors duration-300 ease-in-out ${
isBisnisClicked ? 'bg-red-500 text-white' : ''
}`}
onClick={handleBisnisClick}
@@ -144,20 +150,16 @@ const Register = () => {
</div>
<div className='transition-opacity duration-300 ease-in-out'>
{isIndividuClicked && (
- <div className='opacity-100'>
- <RegistrasiIndividu
- chekValid={notValid}
- buttonSubmitClick={buttonSubmitClick}
- />
- </div>
+ <RegistrasiIndividu
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
)}
{isBisnisClicked && (
- <div className='opacity-100'>
- <RegistrasiBisnis
- chekValid={notValid}
- buttonSubmitClick={buttonSubmitClick}
- />
- </div>
+ <RegistrasiBisnis
+ chekValid={notValid}
+ buttonSubmitClick={buttonSubmitClick}
+ />
)}
</div>
<section className='mt-2'>
diff --git a/src-migrate/validations/auth.ts b/src-migrate/validations/auth.ts
index 3abdfb57..8e867ade 100644
--- a/src-migrate/validations/auth.ts
+++ b/src-migrate/validations/auth.ts
@@ -11,7 +11,7 @@ export const registerSchema = z
phone: z
.string()
.min(1, { message: 'Nomor telepon harus diisi' })
- .refine((val) => /^\d{10,12}$/.test(val), {
+ .refine((val) => /^\d{9,13}$/.test(val), {
message: 'Format nomor telepon tidak valid, contoh: 081234567890',
}),
type_acc: z.string().optional(),
diff --git a/src/api/promoApi.js b/src/api/promoApi.js
index 3f85db8e..8adc4647 100644
--- a/src/api/promoApi.js
+++ b/src/api/promoApi.js
@@ -22,7 +22,9 @@ export const fetchPromoItemsSolr = async (type, start, rows) => {
// let rows = 10
try {
const queryParams = new URLSearchParams({ q: type });
- const response = await fetch(`/solr/promotion_program_lines/select?${queryParams.toString()}&rows=${rows}&start=${start}&${sort}`);
+ const response = await fetch(
+ `/solr/promotion_program_lines/select?${queryParams.toString()}&rows=${rows}&start=${start}&${sort}&fq=active_b%3Atrue`
+ );
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
diff --git a/src/core/components/elements/Footer/BasicFooter.jsx b/src/core/components/elements/Footer/BasicFooter.jsx
index d804bd24..579846e0 100644
--- a/src/core/components/elements/Footer/BasicFooter.jsx
+++ b/src/core/components/elements/Footer/BasicFooter.jsx
@@ -229,32 +229,32 @@ const Form = () => (
<div className={headerClassName}>Formulir</div>
<ul className='flex flex-col gap-y-3'>
<li>
- <InternalItemLink href='/my/request-for-quotation'>
+ <InternalItemLink href='/request-for-quotation'>
Request for Quotation
</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/kunjungan-sales'>
+ <InternalItemLink href='/kunjungan-sales'>
Kunjungan Sales
</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/kunjungan-service'>
+ <InternalItemLink href='/kunjungan-service'>
Kunjungan Service
</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/pembayaran-tempo'>
+ <InternalItemLink href='/pembayaran-tempo'>
Pembayaran Tempo
</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/surat-dukungan'>
+ <InternalItemLink href='/surat-dukungan'>
Surat Dukungan
</InternalItemLink>
</li>
<li>
- <InternalItemLink href='/my/daftar-merchant'>
+ <InternalItemLink href='/daftar-merchant'>
Daftar Merchant
</InternalItemLink>
</li>
diff --git a/src/core/utils/googleTag.js b/src/core/utils/googleTag.js
index 96a6bd2e..f1550071 100644
--- a/src/core/utils/googleTag.js
+++ b/src/core/utils/googleTag.js
@@ -1,3 +1,5 @@
+const PPN = process.env.NEXT_PUBLIC_PPN
+
const mapVariants = (variants) => {
return variants.map((variant) => {
const res = {
@@ -22,7 +24,7 @@ const sumTotal = (variants) => {
0
)
let subtotal = totalPurchase - totalDiscount
- let tax = Math.round(subtotal * 0.11)
+ let tax = Math.round(subtotal * (PPN - 1))
let grandTotal = subtotal + tax
return {
totalPurchase: totalPurchase,
diff --git a/src/lib/cart/components/Cart.jsx b/src/lib/cart/components/Cart.jsx
index c6aaa596..1e25d959 100644
--- a/src/lib/cart/components/Cart.jsx
+++ b/src/lib/cart/components/Cart.jsx
@@ -27,6 +27,7 @@ import CardProdcuctsList from '@/core/components/elements/Product/cartProductsLi
// import cardProdcuctsList from '@/core/components/elements/Product/cartProductsList'
const Cart = () => {
+ const PPN = process.env.NEXT_PUBLIC_PPN
const router = useRouter()
const [products, setProducts] = useState(null)
const [isLoading, setIsLoading] = useState(true)
@@ -97,7 +98,7 @@ const Cart = () => {
if (product.canBuy == false) {
toggleSelected(product.id)
}
- let priceBeforeTax = product.price.price / 1.11
+ let priceBeforeTax = product.price.price / PPN
calculateTotalPriceBeforeTax += priceBeforeTax * product.quantity
calculateTotalTaxAmount += (product.price.price - priceBeforeTax) * product.quantity
calculateTotalDiscountAmount +=
diff --git a/src/lib/cart/components/CartOld.jsx b/src/lib/cart/components/CartOld.jsx
index 718541af..358efa49 100644
--- a/src/lib/cart/components/CartOld.jsx
+++ b/src/lib/cart/components/CartOld.jsx
@@ -20,6 +20,7 @@ import whatsappUrl from '@/core/utils/whatsappUrl'
import useAuth from '@/core/hooks/useAuth'
const Cart = () => {
+ const PPN = process.env.NEXT_PUBLIC_PPN
const router = useRouter()
const [products, setProducts] = useState(null)
const auth = useAuth()
@@ -67,7 +68,7 @@ const Cart = () => {
})
if (!product.selected) continue
- let priceBeforeTax = product.price.price / 1.11
+ let priceBeforeTax = product.price.price / PPN
calculateTotalPriceBeforeTax += priceBeforeTax * product.quantity
calculateTotalTaxAmount += (product.price.price - priceBeforeTax) * product.quantity
calculateTotalDiscountAmount +=
diff --git a/src/lib/cart/components/Cartheader.jsx b/src/lib/cart/components/Cartheader.jsx
index 1c30bb13..6d4e2679 100644
--- a/src/lib/cart/components/Cartheader.jsx
+++ b/src/lib/cart/components/Cartheader.jsx
@@ -14,6 +14,7 @@ const { ShoppingCartIcon, PhotoIcon } = require('@heroicons/react/24/outline');
const { default: Link } = require('next/link');
const Cardheader = (cartCount) => {
+ const PPN = process.env.NEXT_PUBLIC_PPN
const router = useRouter();
const [subTotal, setSubTotal] = useState(null);
const [buttonLoading, SetButtonTerapkan] = useState(false);
@@ -66,7 +67,7 @@ const Cardheader = (cartCount) => {
for (const product of products) {
if (product.quantity == '') continue;
- let priceBeforeTax = product.price.price / 1.11;
+ let priceBeforeTax = product.price.price / PPN;
calculateTotalPriceBeforeTax += priceBeforeTax * product.quantity;
calculateTotalTaxAmount +=
(product.price.price - priceBeforeTax) * product.quantity;
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 6fb5cdb4..e3b586f1 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -50,6 +50,7 @@ function convertToInternational(number) {
}
const Checkout = () => {
+ const PPN = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
const router = useRouter();
const query = router.query.source ?? null;
const qVoucher = router.query.voucher ?? null;
@@ -587,7 +588,6 @@ const Checkout = () => {
setItemTnC(item);
SetBottomPopupTnC(true);
};
- // const taxTotal = (totalAmount - totalDiscountAmount - discountVoucher) * 0.11
const hasNoPrice = useMemo(() => {
if (!products) return false;
@@ -1210,7 +1210,7 @@ const Checkout = () => {
<div>{currencyFormat(cartCheckout?.subtotal)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
- <div className='text-gray_r-11'>PPN 11%</div>
+ <div className='text-gray_r-11'>PPN {((PPN - 1) * 100).toFixed(0)}%</div>
<div>{currencyFormat(cartCheckout?.tax)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
@@ -1514,7 +1514,7 @@ const Checkout = () => {
<div>{currencyFormat(cartCheckout?.subtotal)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
- <div className='text-gray_r-11'>PPN 11%</div>
+ <div className='text-gray_r-11'>PPN {((PPN - 1) * 100).toFixed(0)}%</div>
<div>{currencyFormat(cartCheckout?.tax)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
diff --git a/src/lib/checkout/components/CheckoutOld.jsx b/src/lib/checkout/components/CheckoutOld.jsx
index 5b479a73..433c5672 100644
--- a/src/lib/checkout/components/CheckoutOld.jsx
+++ b/src/lib/checkout/components/CheckoutOld.jsx
@@ -239,7 +239,7 @@ const Checkout = () => {
setIsLoading(false)
window.location.href = payment.data.redirectUrl
}
- const taxTotal = (totalAmount - totalDiscountAmount) * 0.11
+ const taxTotal = (totalAmount - totalDiscountAmount) * (PPN - 1)
return (
<>
diff --git a/src/lib/checkout/email/FinishCheckoutEmail.jsx b/src/lib/checkout/email/FinishCheckoutEmail.jsx
index d19ba1ca..9a94587e 100644
--- a/src/lib/checkout/email/FinishCheckoutEmail.jsx
+++ b/src/lib/checkout/email/FinishCheckoutEmail.jsx
@@ -17,6 +17,7 @@ import {
import FinishCheckout from '../components/FinishCheckout'
const FinishCheckoutEmail = ({ transaction, payment, statusPayment }) => {
+ const PPN = process.env.NEXT_PUBLIC_PPN
return (
<Html>
@@ -206,9 +207,9 @@ const FinishCheckoutEmail = ({ transaction, payment, statusPayment }) => {
</Column>
</Row>
<Row style={style.descriptionRow}>
- <Column style={style.descriptionLCol}>PPN 11% (Incl.)</Column>
+ <Column style={style.descriptionLCol}>PPN {((PPN - 1) * 100).toFixed(0)}% (Incl.)</Column>
<Column style={style.descriptionRCol}>
- {currencyFormat(transaction.subtotal * 0.11)}
+ {currencyFormat(transaction.subtotal * (PPN - 1))}
</Column>
</Row>
diff --git a/src/lib/flashSale/components/FlashSale.jsx b/src/lib/flashSale/components/FlashSale.jsx
index f4be279e..9c0e713b 100644
--- a/src/lib/flashSale/components/FlashSale.jsx
+++ b/src/lib/flashSale/components/FlashSale.jsx
@@ -9,13 +9,23 @@ import { FlashSaleSkeleton } from '../skeleton/FlashSaleSkeleton';
const FlashSale = () => {
const [flashSales, setFlashSales] = useState(null);
const [isLoading, setIsLoading] = useState(true);
+ const [duration, setDuration] = useState();
+ const calculateRemainingTime = (endDate) => {
+ const currentTime = new Date();
+ const endTime = new Date(endDate);
+ const remainingTimeInSeconds = (endTime - currentTime) / 1000;
+
+ return Math.max(Math.round(remainingTimeInSeconds), 0);
+ };
useEffect(() => {
const loadFlashSales = async () => {
const res = await fetch('/api/flashsale-header');
const { data } = await res.json();
if (data) {
setFlashSales(data);
+ const remainingTime = calculateRemainingTime(data[0]?.endDate);
+ setDuration(remainingTime);
}
setIsLoading(false);
};
@@ -37,7 +47,7 @@ const FlashSale = () => {
<div className='font-medium sm:text-h-lg mt-1.5'>
{flashSale.name}
</div>
- <CountDown initialTime={flashSale.duration} />
+ <CountDown initialTime={duration} />
</div>
<div className='relative'>
@@ -59,7 +69,7 @@ const FlashSale = () => {
/>
<FlashSaleProduct
flashSaleId={flashSale.pricelistId}
- duration={flashSale.duration}
+ duration={duration}
/>
</div>
</div>
diff --git a/src/lib/form/components/KunjunganSales.jsx b/src/lib/form/components/KunjunganSales.jsx
index ffa8f135..3779b836 100644
--- a/src/lib/form/components/KunjunganSales.jsx
+++ b/src/lib/form/components/KunjunganSales.jsx
@@ -1,17 +1,18 @@
-import odooApi from '@/core/api/odooApi'
-import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'
-import cityApi from '@/lib/address/api/cityApi'
-import { yupResolver } from '@hookform/resolvers/yup'
-import React, { useEffect, useRef, useState } from 'react'
-import ReCAPTCHA from 'react-google-recaptcha'
-import { Controller, useForm } from 'react-hook-form'
-import { toast } from 'react-hot-toast'
-import * as Yup from 'yup'
-import createLeadApi from '../api/createLeadApi'
-import PageContent from '@/lib/content/components/PageContent'
-
-import useAuth from '@/core/hooks/useAuth'
-import { useRouter } from 'next/router'
+import odooApi from '@/core/api/odooApi';
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import cityApi from '@/lib/address/api/cityApi';
+import stateApi from '@/lib/address/api/stateApi.js';
+import { yupResolver } from '@hookform/resolvers/yup';
+import React, { useEffect, useRef, useState } from 'react';
+import ReCAPTCHA from 'react-google-recaptcha';
+import { Controller, useForm } from 'react-hook-form';
+import { toast } from 'react-hot-toast';
+import * as Yup from 'yup';
+import createLeadApi from '../api/createLeadApi';
+import PageContent from '@/lib/content/components/PageContent';
+
+import useAuth from '@/core/hooks/useAuth';
+import { useRouter } from 'next/router';
const KunjunganSales = () => {
const {
@@ -19,44 +20,72 @@ const KunjunganSales = () => {
handleSubmit,
formState: { errors },
control,
- reset
+ reset,
+ watch,
+ setValue,
} = useForm({
resolver: yupResolver(validationSchema),
- defaultValues
- })
- const [cities, setCities] = useState([])
- const [companyTypes, setCompanyTypes] = useState([])
- const router = useRouter()
+ defaultValues,
+ });
+ const [cities, setCities] = useState([]);
+ const [state, setState] = useState([]);
+ const [companyTypes, setCompanyTypes] = useState([]);
+ const router = useRouter();
+
+ const auth = useAuth();
- const auth = useAuth()
+ const recaptchaRef = useRef(null);
-
+ if (auth == false) {
+ router.push(`/login?next=${encodeURIComponent('/kunjungan-sales')}`);
+ }
+
+ useEffect(() => {
+ const loadState = async () => {
+ let dataState = await stateApi();
+ dataState = dataState.map((state) => ({
+ value: state.id,
+ label: state.name,
+ }));
+ setState(dataState);
+ };
+ loadState();
+ }, []);
- const recaptchaRef = useRef(null)
+ const watchState = watch('state');
useEffect(() => {
- if(auth == false) {
- router.push('/login')
+ if (auth == false) {
+ return;
}
const loadCities = async () => {
- let dataCities = await cityApi()
- dataCities = dataCities.map((obj) => ({ value: obj.name, label: obj.name }))
- setCities(dataCities)
- }
+ setValue('city', '');
+ let dataCities = await cityApi({ stateId: watchState });
+ dataCities = dataCities?.map((obj) => ({
+ value: obj.name,
+ label: obj.name,
+ }));
+ setCities(dataCities);
+ };
const loadCompanyTypes = async () => {
- const dataCompanyTypes = await odooApi('GET', '/api/v1/partner/company_type')
- setCompanyTypes(dataCompanyTypes?.map((obj) => ({ value: obj.name, label: obj.name })))
- }
+ const dataCompanyTypes = await odooApi(
+ 'GET',
+ '/api/v1/partner/company_type'
+ );
+ setCompanyTypes(
+ dataCompanyTypes?.map((obj) => ({ value: obj.name, label: obj.name }))
+ );
+ };
- loadCompanyTypes()
- loadCities()
- }, [auth])
+ loadCompanyTypes();
+ loadCities();
+ }, [auth, watchState, setValue]);
const onSubmitHandler = async (values) => {
- const recaptchaValue = recaptchaRef.current.getValue()
+ const recaptchaValue = recaptchaRef.current.getValue();
if (!recaptchaValue) {
- toast.error('Recaptcha harus diisi')
- return
+ toast.error('Recaptcha harus diisi');
+ return;
}
const data = {
@@ -71,29 +100,37 @@ const KunjunganSales = () => {
`Unit Perusahaan: ${values.companyType}`,
`No. Handphone: ${values.mobile}`,
`Alamat Email: ${values.email}`,
- `Keterangan: ${values.description}`
- ].join('\n')
- }
+ `Keterangan: ${values.description}`,
+ ].join('\n'),
+ };
- const createLead = await createLeadApi({ data })
+ const createLead = await createLeadApi({ data });
if (createLead) {
- toast.success('Berhasil mengirimkan formulir kunjungan sales')
- reset()
- recaptchaRef.current.reset()
+ toast.success('Berhasil mengirimkan formulir kunjungan sales');
+ reset();
+ recaptchaRef.current.reset();
}
+ };
+ if (!auth) {
+ return;
}
return (
<div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
- <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Kunjungan Sales</h1>
+ <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>
+ Kunjungan Sales
+ </h1>
<div className='w-full grid grid-cols-1 md:grid-cols-2 gap-x-2'>
- <form onSubmit={handleSubmit(onSubmitHandler)} className='grid grid-cols-1 gap-y-6'>
+ <form
+ onSubmit={handleSubmit(onSubmitHandler)}
+ className='grid grid-cols-1 gap-y-6'
+ >
<div
className='flex items-center bg-blue-100 border border-blue-300 text-blue-500 font-medium px-4 py-3 rounded leading-6'
role='alert'
>
- Hubungi kami untuk mendapatkan kunjungan sales kami dan dapatkan berbagai kelebihannya
- dengan menjadi pelanggan korporat kami.
+ Hubungi kami untuk mendapatkan kunjungan sales kami dan dapatkan
+ berbagai kelebihannya dengan menjadi pelanggan korporat kami.
</div>
<div>
<label className='form-label mb-2'>Nama Perusahan*</label>
@@ -104,7 +141,9 @@ const KunjunganSales = () => {
className='form-input'
aria-invalid={errors.company?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.company?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.company?.message}
+ </div>
</div>
<div>
@@ -116,7 +155,9 @@ const KunjunganSales = () => {
className='form-input'
aria-invalid={errors.phone?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.phone?.message}
+ </div>
</div>
<div>
@@ -128,7 +169,21 @@ const KunjunganSales = () => {
className='form-input'
aria-invalid={errors.address?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.address?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.address?.message}
+ </div>
+ </div>
+
+ <div>
+ <label className='form-label mb-2'>Provinsi*</label>
+ <Controller
+ name='state'
+ control={control}
+ render={(props) => <HookFormSelect {...props} options={state} />}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.stateId?.message}
+ </div>
</div>
<div>
@@ -138,7 +193,9 @@ const KunjunganSales = () => {
control={control}
render={(props) => <HookFormSelect {...props} options={cities} />}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.city?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.city?.message}
+ </div>
</div>
<div>
@@ -146,9 +203,13 @@ const KunjunganSales = () => {
<Controller
name='companyType'
control={control}
- render={(props) => <HookFormSelect {...props} options={companyTypes} />}
+ render={(props) => (
+ <HookFormSelect {...props} options={companyTypes} />
+ )}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.companyType?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.companyType?.message}
+ </div>
</div>
<div>
@@ -160,7 +221,9 @@ const KunjunganSales = () => {
className='form-input'
aria-invalid={errors.mobile?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.mobile?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.mobile?.message}
+ </div>
</div>
<div>
@@ -172,34 +235,49 @@ const KunjunganSales = () => {
className='form-input'
aria-invalid={errors.email?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.email?.message}
+ </div>
</div>
<div>
<label className='form-label mb-2'>Keterangan</label>
- <textarea {...register('description')} type='text' className='form-input' />
+ <textarea
+ {...register('description')}
+ type='text'
+ className='form-input'
+ />
</div>
- <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
+ <ReCAPTCHA
+ ref={recaptchaRef}
+ sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE}
+ />
- <button type='submit' className='btn-yellow w-full md:w-fit ml-0 md:ml-auto'>
+ <button
+ type='submit'
+ className='btn-yellow w-full md:w-fit ml-0 md:ml-auto'
+ >
Simpan
</button>
</form>
<PageContent path='/kunjungan-sales' />
</div>
</div>
- )
-}
+ );
+};
const validationSchema = Yup.object().shape({
- email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ email: Yup.string()
+ .email('Format harus seperti contoh@email.com')
+ .required('Harus di-isi'),
company: Yup.string().required('Harus di-isi'),
phone: Yup.string().required('Harus di-isi'),
mobile: Yup.string().required('Harus di-isi'),
address: Yup.string().required('Harus di-isi'),
- city: Yup.string().required('Harus dipilih')
-})
+ city: Yup.string().required('Harus dipilih'),
+ state: Yup.string().required('Harus dipilih'),
+});
const defaultValues = {
email: '',
@@ -208,8 +286,9 @@ const defaultValues = {
mobile: '',
address: '',
city: '',
+ state: '',
companyType: '',
- description: ''
-}
+ description: '',
+};
-export default KunjunganSales
+export default KunjunganSales;
diff --git a/src/lib/form/components/KunjunganService.jsx b/src/lib/form/components/KunjunganService.jsx
index 5720d14e..e3c83f78 100644
--- a/src/lib/form/components/KunjunganService.jsx
+++ b/src/lib/form/components/KunjunganService.jsx
@@ -1,16 +1,17 @@
-import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'
-import cityApi from '@/lib/address/api/cityApi'
-import { yupResolver } from '@hookform/resolvers/yup'
-import React, { useEffect, useRef, useState } from 'react'
-import ReCAPTCHA from 'react-google-recaptcha'
-import { Controller, useForm } from 'react-hook-form'
-import { toast } from 'react-hot-toast'
-import * as Yup from 'yup'
-import createLeadApi from '../api/createLeadApi'
-import PageContent from '@/lib/content/components/PageContent'
-import { useRouter } from 'next/router'
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import cityApi from '@/lib/address/api/cityApi';
+import stateApi from '@/lib/address/api/stateApi.js';
+import { yupResolver } from '@hookform/resolvers/yup';
+import React, { useEffect, useRef, useState } from 'react';
+import ReCAPTCHA from 'react-google-recaptcha';
+import { Controller, useForm } from 'react-hook-form';
+import { toast } from 'react-hot-toast';
+import * as Yup from 'yup';
+import createLeadApi from '../api/createLeadApi';
+import PageContent from '@/lib/content/components/PageContent';
+import { useRouter } from 'next/router';
-import useAuth from '@/core/hooks/useAuth'
+import useAuth from '@/core/hooks/useAuth';
const CreateKunjunganService = () => {
const {
@@ -18,37 +19,61 @@ const CreateKunjunganService = () => {
handleSubmit,
formState: { errors },
control,
- reset
+ reset,
+ watch,
+ setValue,
} = useForm({
resolver: yupResolver(validationSchema),
- defaultValues
- })
- const [cities, setCities] = useState([])
- const [company_unit, setCompany_unit] = useState([])
-
- const router = useRouter()
+ defaultValues,
+ });
+ const [cities, setCities] = useState([]);
+ const [state, setState] = useState([]);
+ const [company_unit, setCompany_unit] = useState([]);
- const auth = useAuth()
+ const router = useRouter();
- const recaptchaRef = useRef(null)
+ const auth = useAuth();
+ if (auth == false) {
+ router.push(`/login?next=${encodeURIComponent('/kunjungan-service')}`);
+ }
+
+ const recaptchaRef = useRef(null);
+
+ useEffect(() => {
+ const loadState = async () => {
+ let dataState = await stateApi();
+ dataState = dataState.map((state) => ({
+ value: state.id,
+ label: state.name,
+ }));
+ setState(dataState);
+ };
+ loadState();
+ }, []);
+
+ const watchState = watch('state');
useEffect(() => {
- if(auth == false) {
- router.push('/login')
+ if (auth == false) {
+ return;
}
const loadCities = async () => {
- let dataCities = await cityApi()
- dataCities = dataCities.map((city) => ({ value: city.id, label: city.name }))
- setCities(dataCities)
- }
- loadCities()
- }, [auth])
+ setValue('city', '');
+ let dataCities = await cityApi({ stateId: watchState });
+ dataCities = dataCities.map((city) => ({
+ value: city.id,
+ label: city.name,
+ }));
+ setCities(dataCities);
+ };
+ loadCities();
+ }, [auth, watchState, setValue]);
const onSubmitHandler = async (values) => {
- const recaptchaValue = recaptchaRef.current.getValue()
+ const recaptchaValue = recaptchaRef.current.getValue();
if (!recaptchaValue) {
- toast.error('Catcha harus diisi')
- return
+ toast.error('Catcha harus diisi');
+ return;
}
const data = {
...values,
@@ -70,164 +95,212 @@ const CreateKunjunganService = () => {
' \r\n Email : ' +
values.email +
' \r\n Keterangan : ' +
- values.description
- }
+ values.description,
+ };
- const create_leads = await createLeadApi({ data })
+ const create_leads = await createLeadApi({ data });
if (create_leads) {
- toast.success('Berhasil menambahkan alamat')
- reset()
- recaptchaRef.current.reset()
+ toast.success('Berhasil menambahkan alamat');
+ reset();
+ recaptchaRef.current.reset();
}
+ };
+ if (!auth) {
+ return;
}
return (
<div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
- <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Kunjungan Service</h1>
+ <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>
+ Kunjungan Service
+ </h1>
<div className='w-full p-4 bg-white border border-gray_r-6 rounded'>
<div
className='flex items-center bg-blue-100 border border-blue-400 text-blue-500 font-bold px-4 py-3 mb-4'
role='alert'
>
<p>
- Tidak punya waktu untuk melakukan service atau perawatan rutin? Silahkan hubungi teknisi
- kami untuk melakukan kunjungan ke tempat Anda di Jabodetabek.
+ Tidak punya waktu untuk melakukan service atau perawatan rutin?
+ Silahkan hubungi teknisi kami untuk melakukan kunjungan ke tempat
+ Anda di Jabodetabek.
</p>
</div>
<div className='w-full grid grid-cols-2 gap-x-2'>
-
- <form onSubmit={handleSubmit(onSubmitHandler)}>
- <div className=''>
- <div>
- <label className='form-label mb-2'>Nama Perusahan *</label>
- <input
- {...register('company')}
- placeholder='PT.Indoteknik'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.company?.message}</div>
+ <form onSubmit={handleSubmit(onSubmitHandler)}>
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>Nama Perusahan *</label>
+ <input
+ {...register('company')}
+ placeholder='PT.Indoteknik'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.company?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <label className='form-label mb-2'>No. Telp *</label>
- <input
- {...register('phone')}
- placeholder='021-XXXX'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>No. Telp *</label>
+ <input
+ {...register('phone')}
+ placeholder='021-XXXX'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.phone?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <label className='form-label mb-2'>Alamat*</label>
- <input
- {...register('address')}
- placeholder='jl. Bandengan no.31 '
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.address?.message}</div>
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>Alamat*</label>
+ <input
+ {...register('address')}
+ placeholder='jl. Bandengan no.31 '
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.address?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
<div>
- <label className='form-label mb-2'>Kota*</label>
+ <label className='form-label mb-2'>Provinsi*</label>
<Controller
- name='city'
+ name='state'
control={control}
- render={(props) => <HookFormSelect {...props} options={cities} />}
+ render={(props) => (
+ <HookFormSelect {...props} options={state} />
+ )}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.city?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.state?.message}
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <label className='form-label mb-2'>Contact Person*</label>
- <input
- {...register('cp')}
- placeholder='Jhone doe'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.cp?.message}</div>
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>Kota*</label>
+ <Controller
+ name='city'
+ control={control}
+ render={(props) => (
+ <HookFormSelect {...props} options={cities} />
+ )}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.city?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <label className='form-label mb-2'>No HP *</label>
- <input
- {...register('mobile')}
- placeholder='628XXXXXXX'
- type='text'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.mobile?.message}</div>
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>Contact Person*</label>
+ <input
+ {...register('cp')}
+ placeholder='Jhone doe'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.cp?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <label className='form-label mb-2'>Alamat Email *</label>
- <input
- {...register('email')}
- placeholder='contoh@email.com'
- type='email'
- className='form-input'
- />
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>No HP *</label>
+ <input
+ {...register('mobile')}
+ placeholder='628XXXXXXX'
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.mobile?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <label className='form-label mb-2'>
- Sebutkan: Merek, Tipe, Permasalahan, Service, Perawatan
- </label>
- <textarea {...register('description')} type='text' className='form-input' />
- <div className='text-caption-2 text-danger-500 mt-1'>
- {errors.description?.message}
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>Alamat Email *</label>
+ <input
+ {...register('email')}
+ placeholder='contoh@email.com'
+ type='email'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.email?.message}
+ </div>
</div>
</div>
- </div>
- <div className=''>
- <div>
- <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
+ <div className=''>
+ <div>
+ <label className='form-label mb-2'>
+ Sebutkan: Merek, Tipe, Permasalahan, Service, Perawatan
+ </label>
+ <textarea
+ {...register('description')}
+ type='text'
+ className='form-input'
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.description?.message}
+ </div>
+ </div>
</div>
- </div>
- <div className=''>
- <div>
- <button type='submit' className='btn-yellow w-full md:w-fit mt-6 ml-0 md:ml-auto'>
- Simpan
- </button>
+ <div className=''>
+ <div>
+ <ReCAPTCHA
+ ref={recaptchaRef}
+ sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE}
+ />
+ </div>
+ </div>
+ <div className=''>
+ <div>
+ <button
+ type='submit'
+ className='btn-yellow w-full md:w-fit mt-6 ml-0 md:ml-auto'
+ >
+ Simpan
+ </button>
+ </div>
</div>
- </div>
- </form>
- <PageContent path='/kunjungan-service' />
+ </form>
+ <PageContent path='/kunjungan-service' />
</div>
</div>
</div>
- )
-}
+ );
+};
const validationSchema = Yup.object().shape({
company: Yup.string().required('Harus di-isi'),
- email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ email: Yup.string()
+ .email('Format harus seperti contoh@email.com')
+ .required('Harus di-isi'),
phone: Yup.string().required('Harus di-isi'),
city: Yup.string().required('Harus di-isi'),
+ state: Yup.string().required('Harus dipilih'),
cp: Yup.string().required('Harus di-isi'),
mobile: Yup.string().required('Harus di-isi'),
email: Yup.string().required('Harus di-isi'),
- address: Yup.string().required('Harus di-isi')
-})
+ address: Yup.string().required('Harus di-isi'),
+});
const defaultValues = {
company: '',
email: '',
phone: '',
city: '',
+ state: '',
cp: '',
mobile: '',
email: '',
- address: ''
-}
+ address: '',
+};
-export default CreateKunjunganService
+export default CreateKunjunganService;
diff --git a/src/lib/form/components/Merchant.jsx b/src/lib/form/components/Merchant.jsx
index 85f72bf8..ee7d177d 100644
--- a/src/lib/form/components/Merchant.jsx
+++ b/src/lib/form/components/Merchant.jsx
@@ -1,5 +1,6 @@
import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
import cityApi from '@/lib/address/api/cityApi';
+import stateApi from '@/lib/address/api/stateApi.js';
import { yupResolver } from '@hookform/resolvers/yup';
import React, { useEffect, useRef, useState } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';
@@ -9,8 +10,7 @@ import * as Yup from 'yup';
import createLeadApi from '../api/createLeadApi';
import PageContent from '@/lib/content/components/PageContent';
import { useRouter } from 'next/router';
-import useAuth from '@/core/hooks/useAuth'
-
+import useAuth from '@/core/hooks/useAuth';
const CreateMerchant = () => {
const {
@@ -19,6 +19,8 @@ const CreateMerchant = () => {
formState: { errors },
control,
reset,
+ watch,
+ setValue,
} = useForm({
resolver: yupResolver(validationSchema),
defaultValues,
@@ -50,27 +52,45 @@ const CreateMerchant = () => {
},
];
const [cities, setCities] = useState([]);
+ const [state, setState] = useState([]);
const [company_unit, setCompany_unit] = useState(list_unit);
const recaptchaRef = useRef(null);
- const router = useRouter()
+ const router = useRouter();
+
+ const auth = useAuth();
+ if (auth == false) {
+ router.push(`/login?next=${encodeURIComponent('/daftar-merchant')}`);
+ }
- const auth = useAuth()
+ useEffect(() => {
+ const loadState = async () => {
+ let dataState = await stateApi();
+ dataState = dataState.map((state) => ({
+ value: state.id,
+ label: state.name,
+ }));
+ setState(dataState);
+ };
+ loadState();
+ }, []);
+ const watchState = watch('state');
useEffect(() => {
- if(auth == false) {
- router.push('/login')
+ if (auth == false) {
+ return;
}
const loadCities = async () => {
- let dataCities = await cityApi();
- dataCities = dataCities.map((city) => ({
+ setValue('city', '');
+ let dataCities = await cityApi({ stateId: watchState });
+ dataCities = dataCities?.map((city) => ({
value: city.id,
label: city.name,
}));
setCities(dataCities);
};
loadCities();
- }, [auth]);
+ }, [auth, watchState, setValue]);
const onSubmitHandler = async (values) => {
const recaptchaValue = recaptchaRef.current.getValue();
@@ -111,6 +131,9 @@ const CreateMerchant = () => {
recaptchaRef.current.reset();
}
};
+ if (!auth) {
+ return;
+ }
return (
<div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
<h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>
@@ -172,6 +195,19 @@ const CreateMerchant = () => {
</div>
</div>
</div>
+ <div>
+ <label className='form-label mb-2'>Provinsi*</label>
+ <Controller
+ name='state'
+ control={control}
+ render={(props) => (
+ <HookFormSelect {...props} options={state} />
+ )}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.state?.message}
+ </div>
+ </div>
<div className=''>
<div>
<label className='form-label mb-2'>Kota*</label>
@@ -290,6 +326,7 @@ const validationSchema = Yup.object().shape({
.required('Harus di-isi'),
phone: Yup.string().required('Harus di-isi'),
cp: Yup.string().required('Harus di-isi'),
+ state: Yup.string().required('Harus dipilih'),
city: Yup.string().required('Harus di-isi'),
company_unit: Yup.string().required('Harus di-isi'),
address: Yup.string().required('Harus di-isi'),
@@ -300,6 +337,7 @@ const defaultValues = {
company: '',
email: '',
phone: '',
+ state: '',
city: '',
company_unit: '',
cp: '',
diff --git a/src/lib/form/components/RequestForQuotation.jsx b/src/lib/form/components/RequestForQuotation.jsx
index 68b7fa17..170a5c62 100644
--- a/src/lib/form/components/RequestForQuotation.jsx
+++ b/src/lib/form/components/RequestForQuotation.jsx
@@ -1,18 +1,19 @@
-import odooApi from '@/core/api/odooApi'
-import HookFormSelect from '@/core/components/elements/Select/HookFormSelect'
-import cityApi from '@/lib/address/api/cityApi'
-import { yupResolver } from '@hookform/resolvers/yup'
-import React, { useEffect, useRef, useState } from 'react'
-import ReCAPTCHA from 'react-google-recaptcha'
-import { Controller, useForm } from 'react-hook-form'
-import { toast } from 'react-hot-toast'
-import * as Yup from 'yup'
-import createLeadApi from '../api/createLeadApi'
-import getFileBase64 from '@/core/utils/getFileBase64'
-import PageContent from '@/lib/content/components/PageContent'
-import { useRouter } from 'next/router'
-
-import useAuth from '@/core/hooks/useAuth'
+import odooApi from '@/core/api/odooApi';
+import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
+import cityApi from '@/lib/address/api/cityApi';
+import stateApi from '@/lib/address/api/stateApi.js';
+import { yupResolver } from '@hookform/resolvers/yup';
+import React, { useEffect, useRef, useState } from 'react';
+import ReCAPTCHA from 'react-google-recaptcha';
+import { Controller, useForm } from 'react-hook-form';
+import { toast } from 'react-hot-toast';
+import * as Yup from 'yup';
+import createLeadApi from '../api/createLeadApi';
+import getFileBase64 from '@/core/utils/getFileBase64';
+import PageContent from '@/lib/content/components/PageContent';
+import { useRouter } from 'next/router';
+
+import useAuth from '@/core/hooks/useAuth';
const RequestForQuotation = () => {
const {
@@ -20,47 +21,69 @@ const RequestForQuotation = () => {
handleSubmit,
formState: { errors },
control,
- reset
+ reset,
+ watch,
+ setValue,
} = useForm({
resolver: yupResolver(validationSchema),
- defaultValues
- })
- const [cities, setCities] = useState([])
+ defaultValues,
+ });
+ const [cities, setCities] = useState([]);
+ const [state, setState] = useState([]);
- const quotationFileRef = useRef(null)
- const recaptchaRef = useRef(null)
- const router = useRouter()
+ const quotationFileRef = useRef(null);
+ const recaptchaRef = useRef(null);
+ const router = useRouter();
- const auth = useAuth()
+ const auth = useAuth();
+ if (auth == false) {
+ router.push(`/login?next=${encodeURIComponent('/request-for-quotation')}`);
+ }
+ useEffect(() => {
+ const loadState = async () => {
+ let dataState = await stateApi();
+ dataState = dataState.map((state) => ({
+ value: state.id,
+ label: state.name,
+ }));
+ setState(dataState);
+ };
+ loadState();
+ }, []);
+ const watchState = watch('state');
useEffect(() => {
- if(auth == false) {
- router.push('/login')
+ if (!auth) {
+ return;
}
const loadCities = async () => {
- let dataCities = await cityApi()
- dataCities = dataCities.map((obj) => ({ value: obj.name, label: obj.name }))
- setCities(dataCities)
- }
- loadCities()
- }, [auth])
+ setValue('city', '');
+ let dataCities = await cityApi({ stateId: watchState });
+ dataCities = dataCities?.map((obj) => ({
+ value: obj.name,
+ label: obj.name,
+ }));
+ setCities(dataCities);
+ };
+ loadCities();
+ }, [auth, watchState, setValue]);
const onSubmitHandler = async (values) => {
- const recaptchaValue = recaptchaRef.current.getValue()
+ const recaptchaValue = recaptchaRef.current.getValue();
if (!recaptchaValue) {
- toast.error('Recaptcha harus diisi')
- return
+ toast.error('Recaptcha harus diisi');
+ return;
}
- const file = quotationFileRef.current.files[0]
- let fileBase64 = null
+ const file = quotationFileRef.current.files[0];
+ let fileBase64 = null;
if (typeof file !== 'undefined') {
if (file.size > 5000000) {
- toast.error('Maksimal ukuran file adalah 5MB')
- return
+ toast.error('Maksimal ukuran file adalah 5MB');
+ return;
}
- fileBase64 = await getFileBase64(file)
+ fileBase64 = await getFileBase64(file);
}
const data = {
@@ -73,33 +96,42 @@ const RequestForQuotation = () => {
`Kota: ${values.city}`,
`No. Handphone: ${values.mobile}`,
`Alamat Email: ${values.email}`,
- `Keterangan: ${values.description}`
- ].join('\n')
- }
+ `Keterangan: ${values.description}`,
+ ].join('\n'),
+ };
- if (fileBase64) data.file_quotation = fileBase64
+ if (fileBase64) data.file_quotation = fileBase64;
- const createLead = await createLeadApi({ data })
+ const createLead = await createLeadApi({ data });
if (createLead) {
- toast.success('Berhasil mengirimkan formulir request for quotation')
- reset()
- recaptchaRef.current.reset()
+ toast.success('Berhasil mengirimkan formulir request for quotation');
+ reset();
+ recaptchaRef.current.reset();
}
+ };
+ if (!auth) {
+ return;
}
return (
<div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
- <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>Request for Quotation</h1>
+ <h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>
+ Request for Quotation
+ </h1>
<div className='w-full grid grid-cols-1 md:grid-cols-2 gap-x-2'>
- <form onSubmit={handleSubmit(onSubmitHandler)} className='grid grid-cols-1 gap-y-6'>
+ <form
+ onSubmit={handleSubmit(onSubmitHandler)}
+ className='grid grid-cols-1 gap-y-6'
+ >
<div
className='flex items-center bg-blue-100 border border-blue-300 text-blue-500 font-medium px-4 py-3 rounded leading-6'
role='alert'
>
- Halaman untuk pengajuan penawaran harga, lengkapi data di bawah ini dengan jelas untuk
- mempermudah tim support kami melayani kebutuhan Anda. Tim kami akan sesegera mungkin
- untuk membuatkan penawaran harga terbaik, hubungi kami melalui telpon jika ada
- keterlambatan pelayanan.
+ Halaman untuk pengajuan penawaran harga, lengkapi data di bawah ini
+ dengan jelas untuk mempermudah tim support kami melayani kebutuhan
+ Anda. Tim kami akan sesegera mungkin untuk membuatkan penawaran
+ harga terbaik, hubungi kami melalui telpon jika ada keterlambatan
+ pelayanan.
</div>
<div>
<label className='form-label mb-2'>Nama Perusahan*</label>
@@ -110,7 +142,9 @@ const RequestForQuotation = () => {
className='form-input'
aria-invalid={errors.company?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.company?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.company?.message}
+ </div>
</div>
<div>
@@ -122,7 +156,21 @@ const RequestForQuotation = () => {
className='form-input'
aria-invalid={errors.phone?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.phone?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.phone?.message}
+ </div>
+ </div>
+
+ <div>
+ <label className='form-label mb-2'>Provinsi*</label>
+ <Controller
+ name='state'
+ control={control}
+ render={(props) => <HookFormSelect {...props} options={state} />}
+ />
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.state?.message}
+ </div>
</div>
<div>
@@ -132,7 +180,9 @@ const RequestForQuotation = () => {
control={control}
render={(props) => <HookFormSelect {...props} options={cities} />}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.city?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.city?.message}
+ </div>
</div>
<div>
@@ -144,7 +194,9 @@ const RequestForQuotation = () => {
className='form-input'
aria-invalid={errors.contactPerson?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.contactPerson?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.contactPerson?.message}
+ </div>
</div>
<div>
@@ -156,7 +208,9 @@ const RequestForQuotation = () => {
className='form-input'
aria-invalid={errors.mobile?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.mobile?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.mobile?.message}
+ </div>
</div>
<div>
@@ -168,39 +222,59 @@ const RequestForQuotation = () => {
className='form-input'
aria-invalid={errors.email?.message}
/>
- <div className='text-caption-2 text-danger-500 mt-1'>{errors.email?.message}</div>
+ <div className='text-caption-2 text-danger-500 mt-1'>
+ {errors.email?.message}
+ </div>
</div>
<div>
<label className='form-label mb-2'>Keterangan</label>
- <textarea {...register('description')} type='text' className='form-input' />
+ <textarea
+ {...register('description')}
+ type='text'
+ className='form-input'
+ />
</div>
<div>
<label className='form-label mb-2'>File Daftar Produk</label>
- <input type="file" name="quotationFile" className='form-input' ref={quotationFileRef} />
+ <input
+ type='file'
+ name='quotationFile'
+ className='form-input'
+ ref={quotationFileRef}
+ />
</div>
- <ReCAPTCHA ref={recaptchaRef} sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE} />
+ <ReCAPTCHA
+ ref={recaptchaRef}
+ sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_GOOGLE}
+ />
- <button type='submit' className='btn-yellow w-full md:w-fit ml-0 md:ml-auto'>
+ <button
+ type='submit'
+ className='btn-yellow w-full md:w-fit ml-0 md:ml-auto'
+ >
Simpan
</button>
</form>
<PageContent path='/request-for-quotation' />
</div>
</div>
- )
-}
+ );
+};
const validationSchema = Yup.object().shape({
- email: Yup.string().email('Format harus seperti contoh@email.com').required('Harus di-isi'),
+ email: Yup.string()
+ .email('Format harus seperti contoh@email.com')
+ .required('Harus di-isi'),
company: Yup.string().required('Harus di-isi'),
phone: Yup.string().required('Harus di-isi'),
mobile: Yup.string().required('Harus di-isi'),
city: Yup.string().required('Harus dipilih'),
+ state: Yup.string().required('Harus dipilih'),
contactPerson: Yup.string().required('Harus dipilih'),
-})
+});
const defaultValues = {
email: '',
@@ -209,7 +283,8 @@ const defaultValues = {
mobile: '',
address: '',
city: '',
- description: ''
-}
+ state: '',
+ description: '',
+};
-export default RequestForQuotation
+export default RequestForQuotation;
diff --git a/src/lib/form/components/SuratDukungan.jsx b/src/lib/form/components/SuratDukungan.jsx
index 31e7ee83..fadb2c57 100644
--- a/src/lib/form/components/SuratDukungan.jsx
+++ b/src/lib/form/components/SuratDukungan.jsx
@@ -1,5 +1,6 @@
import HookFormSelect from '@/core/components/elements/Select/HookFormSelect';
import cityApi from '@/lib/address/api/cityApi';
+import stateApi from '@/lib/address/api/stateApi.js';
import { yupResolver } from '@hookform/resolvers/yup';
import React, { useEffect, useRef, useState } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';
@@ -10,7 +11,7 @@ import createLeadsApi from '../api/createLeadApi';
import PageContent from '@/lib/content/components/PageContent';
-import useAuth from '@/core/hooks/useAuth'
+import useAuth from '@/core/hooks/useAuth';
import { useRouter } from 'next/router';
const CreateSuratDukungan = () => {
@@ -20,32 +21,21 @@ const CreateSuratDukungan = () => {
formState: { errors },
control,
reset,
+ watch,
+ setValue,
} = useForm({
resolver: yupResolver(validationSchema),
defaultValues,
});
- const [cities, setCities] = useState([]);
const [company_unit, setCompany_unit] = useState([]);
const recaptchaRef = useRef(null);
- const router = useRouter()
+ const router = useRouter();
- const auth = useAuth()
-
- useEffect(() => {
- if(auth == false) {
- router.push('/login')
- }
- const loadCities = async () => {
- let dataCities = await cityApi();
- dataCities = dataCities.map((city) => ({
- value: city.id,
- label: city.name,
- }));
- setCities(dataCities);
- };
- loadCities();
- }, [auth]);
+ const auth = useAuth();
+ if (auth == false) {
+ router.push(`/login?next=${encodeURIComponent('/surat-dukungan')}`);
+ }
const onSubmitHandler = async (values) => {
const recaptchaValue = recaptchaRef.current.getValue();
@@ -85,6 +75,9 @@ const CreateSuratDukungan = () => {
recaptchaRef.current.reset();
}
};
+ if (!auth) {
+ return;
+ }
return (
<div className='container mx-auto p-4 md:p-0 my-0 md:my-10'>
<h1 className='text-h-sm md:text-title-sm font-semibold mb-6'>
@@ -241,7 +234,7 @@ const CreateSuratDukungan = () => {
</div>
</form>
</div>
- <PageContent path='/surat-dukungan'/>
+ <PageContent path='/surat-dukungan' />
</div>
</div>
</div>
diff --git a/src/lib/home/components/ServiceList.jsx b/src/lib/home/components/ServiceList.jsx
index 6d03a587..e32e8747 100644
--- a/src/lib/home/components/ServiceList.jsx
+++ b/src/lib/home/components/ServiceList.jsx
@@ -59,7 +59,7 @@ const ServiceList = () => {
</div>
<div className='w-full '>
<Link
- href='/pembayaran-tempo'
+ href='/pembayaran-tempo-detail'
className='border border-gray-200 p-2 flex items-center gap-x-2 rounded-lg'
>
<div className=''>
diff --git a/src/lib/invoice/components/Invoice.jsx b/src/lib/invoice/components/Invoice.jsx
index 81202b1c..15bfa746 100644
--- a/src/lib/invoice/components/Invoice.jsx
+++ b/src/lib/invoice/components/Invoice.jsx
@@ -13,6 +13,7 @@ import { createSlug } from '@/core/utils/slug'
import { useEffect, useState } from 'react'
const Invoice = ({ id }) => {
+ const PPN = process.env.NEXT_PUBLIC_PPN
const { invoice } = useInvoice({ id })
const [totalAmount, setTotalAmount] = useState(0)
@@ -255,8 +256,8 @@ const Invoice = ({ id }) => {
{currencyFormat(invoice.data?.amountTotal)}
</div>
- <div className='text-right'>PPN 11% (Incl.)</div>
- <div className='text-right font-medium'>{currencyFormat(totalAmount * 0.11)}</div>
+ <div className='text-right'>PPN {((PPN - 1) * 100).toFixed(0)}% (Incl.)</div>
+ <div className='text-right font-medium'>{currencyFormat(invoice.data?.amountTotal - totalAmount)}</div>
</div>
</div>
</div>
diff --git a/src/lib/quotation/components/Quotation.jsx b/src/lib/quotation/components/Quotation.jsx
index 5a2f63a5..2f4d6c46 100644
--- a/src/lib/quotation/components/Quotation.jsx
+++ b/src/lib/quotation/components/Quotation.jsx
@@ -37,6 +37,7 @@ const { checkoutApi } = require('@/lib/checkout/api/checkoutApi');
const { getProductsCheckout } = require('@/lib/checkout/api/checkoutApi');
const Quotation = () => {
+ const PPN = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
const router = useRouter();
const auth = useAuth();
const query = router.query.source ?? null;
@@ -307,7 +308,7 @@ const Quotation = () => {
toast.error('Gagal melakukan transaksi, terjadi kesalahan internal');
};
- const taxTotal = (totalAmount - totalDiscountAmount) * 0.11;
+ const taxTotal = (totalAmount - totalDiscountAmount) * (PPN - 1);
return (
<>
@@ -425,7 +426,7 @@ const Quotation = () => {
<div>{currencyFormat(cartCheckout?.subtotal)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
- <div className='text-gray_r-11'>PPN 11%</div>
+ <div className='text-gray_r-11'>PPN {((PPN - 1) * 100).toFixed(0)}%</div>
<div>{currencyFormat(cartCheckout?.tax)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
@@ -574,7 +575,7 @@ const Quotation = () => {
<div>{currencyFormat(cartCheckout?.subtotal)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
- <div className='text-gray_r-11'>PPN 11%</div>
+ <div className='text-gray_r-11'>PPN {((PPN - 1) * 100).toFixed(0)}%</div>
<div>{currencyFormat(cartCheckout?.tax)}</div>
</div>
<div className='flex gap-x-2 justify-between'>
diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx
index f5dc507a..b2fb2c17 100644
--- a/src/lib/transaction/components/Transaction.jsx
+++ b/src/lib/transaction/components/Transaction.jsx
@@ -42,6 +42,7 @@ import { gtagPurchase } from '@/core/utils/googleTag';
import { deleteItemCart } from '@/core/utils/cart';
import axios from 'axios';
const Transaction = ({ id }) => {
+ const PPN = process.env.NEXT_PUBLIC_PPN;
const router = useRouter();
const [isModalOpen, setIsModalOpen] = useState(false);
const [selectedProduct, setSelectedProduct] = useState(null);
@@ -207,7 +208,7 @@ const Transaction = ({ id }) => {
<p>{currencyFormat(transaction.data?.amountUntaxed)}</p>
</div>
<div className='flex justify-between mt-1'>
- <p className='text-gray_r-12/70'>PPN 11%</p>
+ <p className='text-gray_r-12/70'>PPN {((PPN - 1) * 100).toFixed(0)}%</p>
<p>{currencyFormat(transaction.data?.amountTax)}</p>
</div>
<div className='flex justify-between mt-1'>
@@ -975,7 +976,7 @@ const Transaction = ({ id }) => {
{currencyFormat(transaction.data?.amountUntaxed)}
</div>
- <div className='text-right'>PPN 11%</div>
+ <div className='text-right'>PPN {((PPN - 1) * 100).toFixed(0)}%</div>
<div className='text-right font-medium'>
{currencyFormat(transaction.data?.amountTax)}
</div>
diff --git a/src/pages/api/flashsale-header.js b/src/pages/api/flashsale-header.js
index 21cb9c9d..578801ae 100644
--- a/src/pages/api/flashsale-header.js
+++ b/src/pages/api/flashsale-header.js
@@ -20,13 +20,19 @@ export default async function handler(req, res) {
let cachedData = await client.get(cacheKey);
if (cachedData) {
- const data = JSON.parse(cachedData);
+ const data = JSON.parse(cachedData);
// Periksa apakah data adalah array dan panjangnya 0
if (!data || (Array.isArray(data) && data.length === 0)) {
await client.del(cacheKey); // Hapus kunci jika data kosong
return res.status(200).json({ data: [] });
}
+ // Periksa apakah end_date lebih besar dari waktu saat ini
+ const currentTime = new Date();
+ if (data[0].endDate && new Date(data[0].endDate) < currentTime) {
+ await client.del(cacheKey); // Hapus kunci jika end_date lebih kecil dari waktu saat ini
+ return res.status(200).json({ data: [] });
+ }
return res.status(200).json({ data });
} else {
const flashSale = await odooApi('GET', `/api/v1/flashsale/header`);
@@ -37,11 +43,11 @@ export default async function handler(req, res) {
cacheKey,
JSON.stringify(flashSale),
'EX',
- flashSale.duration
+ flashSale.duration
);
cachedData = await client.get(cacheKey);
- const data = JSON.parse(cachedData);
+ const data = JSON.parse(cachedData);
return res.status(200).json({ data });
}
}
diff --git a/src/pages/api/shop/midtrans-payment.js b/src/pages/api/shop/midtrans-payment.js
index 12aaa51f..f90e9e81 100644
--- a/src/pages/api/shop/midtrans-payment.js
+++ b/src/pages/api/shop/midtrans-payment.js
@@ -3,6 +3,7 @@ import camelcaseObjectDeep from 'camelcase-object-deep'
import midtransClient from 'midtrans-client'
export default async function handler(req, res) {
+ const PPN = process.env.NEXT_PUBLIC_PPN
const { transactionId = null } = req.query
if (!transactionId) {
diff --git a/src/pages/my/daftar-merchant.jsx b/src/pages/daftar-merchant.jsx
index e1fa9bcb..e1fa9bcb 100644
--- a/src/pages/my/daftar-merchant.jsx
+++ b/src/pages/daftar-merchant.jsx
diff --git a/src/pages/google_merchant/products/[page].js b/src/pages/google_merchant/products/[page].js
index 0c2cf3c5..8395f839 100644
--- a/src/pages/google_merchant/products/[page].js
+++ b/src/pages/google_merchant/products/[page].js
@@ -6,6 +6,7 @@ import _ from 'lodash-contrib';
import { create } from 'xmlbuilder';
export async function getServerSideProps({ res, query }) {
+ const PPN = process.env.NEXT_PUBLIC_PPN
const titleContent = 'Indoteknik.com: B2B Industrial Supply & Solution';
const descriptionContent =
'Temukan pilihan produk B2B Industri & Alat Teknik untuk Perusahaan, UMKM & Pemerintah dengan lengkap, mudah dan transparan.';
@@ -77,7 +78,7 @@ export async function getServerSideProps({ res, query }) {
'g:availability': { '#text': availability },
'g:brand': { '#text': product.manufacture?.name || '' },
'g:price': {
- '#text': `${Math.round(product.lowestPrice.price * 1.11)} IDR`,
+ '#text': `${Math.round(product.lowestPrice.price * PPN)} IDR`,
},
};
@@ -93,7 +94,7 @@ export async function getServerSideProps({ res, query }) {
if (product.lowestPrice.discountPercentage > 0) {
item['g:sale_price'] = {
- '#text': `${Math.round(product.lowestPrice.priceDiscount * 1.11)} IDR`,
+ '#text': `${Math.round(product.lowestPrice.priceDiscount * PPN)} IDR`,
};
}
productItems.push(item);
diff --git a/src/pages/my/kunjungan-sales.jsx b/src/pages/kunjungan-sales.jsx
index 052991d9..052991d9 100644
--- a/src/pages/my/kunjungan-sales.jsx
+++ b/src/pages/kunjungan-sales.jsx
diff --git a/src/pages/my/kunjungan-service.jsx b/src/pages/kunjungan-service.jsx
index 37de5a0b..37de5a0b 100644
--- a/src/pages/my/kunjungan-service.jsx
+++ b/src/pages/kunjungan-service.jsx
diff --git a/src/pages/my/pembayaran-tempo.jsx b/src/pages/my/pembayaran-tempo.jsx
deleted file mode 100644
index 8947bdd9..00000000
--- a/src/pages/my/pembayaran-tempo.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import Seo from '@/core/components/Seo'
-import BasicLayout from '@/core/components/layouts/BasicLayout'
-import PembayaranTempo from '@/lib/form/components/PembayaranTempo'
-
-export default function pembayaranTempo() {
- return (
- <>
- <Seo title='Pembayaran Tempo - Indoteknik.com' />
-
- <BasicLayout>
- <PembayaranTempo />
- </BasicLayout>
- </>
- )
-}
diff --git a/src/pages/pembayaran-tempo-detail.jsx b/src/pages/pembayaran-tempo-detail.jsx
new file mode 100644
index 00000000..363e3099
--- /dev/null
+++ b/src/pages/pembayaran-tempo-detail.jsx
@@ -0,0 +1,13 @@
+import Seo from '@/core/components/Seo'
+import BasicLayout from '@/core/components/layouts/BasicLayout'
+import IframeContent from '@/lib/iframe/components/IframeContent'
+
+export default function PembnayaranTempo() {
+ return (
+ <BasicLayout>
+ <Seo title='Pambayaran Tempo - Indoteknik.com' />
+
+ <IframeContent url={`${process.env.NEXT_PUBLIC_ODOO_HOST}/content?url=pembayaran-tempo`} />
+ </BasicLayout>
+ )
+}
diff --git a/src/pages/pembayaran-tempo.jsx b/src/pages/pembayaran-tempo.jsx
index 363e3099..8947bdd9 100644
--- a/src/pages/pembayaran-tempo.jsx
+++ b/src/pages/pembayaran-tempo.jsx
@@ -1,13 +1,15 @@
import Seo from '@/core/components/Seo'
import BasicLayout from '@/core/components/layouts/BasicLayout'
-import IframeContent from '@/lib/iframe/components/IframeContent'
+import PembayaranTempo from '@/lib/form/components/PembayaranTempo'
-export default function PembnayaranTempo() {
+export default function pembayaranTempo() {
return (
- <BasicLayout>
- <Seo title='Pambayaran Tempo - Indoteknik.com' />
+ <>
+ <Seo title='Pembayaran Tempo - Indoteknik.com' />
- <IframeContent url={`${process.env.NEXT_PUBLIC_ODOO_HOST}/content?url=pembayaran-tempo`} />
- </BasicLayout>
+ <BasicLayout>
+ <PembayaranTempo />
+ </BasicLayout>
+ </>
)
}
diff --git a/src/pages/my/request-for-quotation.jsx b/src/pages/request-for-quotation.jsx
index 40fda009..40fda009 100644
--- a/src/pages/my/request-for-quotation.jsx
+++ b/src/pages/request-for-quotation.jsx
diff --git a/src/pages/sitemap/homepage.xml.js b/src/pages/sitemap/homepage.xml.js
index 08c52112..fa622d5c 100644
--- a/src/pages/sitemap/homepage.xml.js
+++ b/src/pages/sitemap/homepage.xml.js
@@ -5,29 +5,29 @@ export async function getServerSideProps({ res }) {
{ label: 'Hubungi Kami', url: 'https://indoteknik.com/hubungi-kami' },
{ label: 'Tentang Kami', url: 'https://indoteknik.com/tentang-kami' },
{ label: 'Karir', url: 'https://indoteknik.com/karir' },
- { label: 'Daftar Tempo', url: 'https://indoteknik.com/my/pembayaran-tempo' },
+ { label: 'Daftar Tempo', url: 'https://indoteknik.com/pembayaran-tempo' },
];
const sitemap = create('urlset', { encoding: 'utf-8' }).att(
'xmlns',
'http://www.sitemaps.org/schemas/sitemap/0.9'
- )
+ );
- const date = new Date()
+ const date = new Date();
links.forEach((link) => {
- const url = sitemap.ele('url')
- url.ele('loc', link.url)
- url.ele('lastmod', date.toISOString().slice(0, 10))
- url.ele('changefreq', 'daily')
- url.ele('priority', '1.0')
- })
+ const url = sitemap.ele('url');
+ url.ele('loc', link.url);
+ url.ele('lastmod', date.toISOString().slice(0, 10));
+ url.ele('changefreq', 'daily');
+ url.ele('priority', '1.0');
+ });
- res.setHeader('Content-Type', 'text/xml')
- res.write(sitemap.end())
- res.end()
+ res.setHeader('Content-Type', 'text/xml');
+ res.write(sitemap.end());
+ res.end();
- return { props: {} }
+ return { props: {} };
}
export default function SitemapProducts() {
- return null
+ return null;
}
diff --git a/src/pages/my/surat-dukungan.jsx b/src/pages/surat-dukungan.jsx
index 8058f34d..8058f34d 100644
--- a/src/pages/my/surat-dukungan.jsx
+++ b/src/pages/surat-dukungan.jsx