summaryrefslogtreecommitdiff
path: root/src/lib/checkout
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-03-03 16:44:12 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-03-03 16:44:12 +0700
commit76961c8312312609dbef0646274f6dd1f6c2bf19 (patch)
tree111c9ff63449f4e188a72435a850ac8efc2a9d28 /src/lib/checkout
parent069f9fa637cd24e9b92c7a1e4de56fa9e263508f (diff)
add midtrans payment email notification
Diffstat (limited to 'src/lib/checkout')
-rw-r--r--src/lib/checkout/components/Checkout.jsx6
-rw-r--r--src/lib/checkout/components/FinishCheckout.jsx18
-rw-r--r--src/lib/checkout/email/FinishCheckoutEmail.jsx326
3 files changed, 342 insertions, 8 deletions
diff --git a/src/lib/checkout/components/Checkout.jsx b/src/lib/checkout/components/Checkout.jsx
index 42608cef..8af3d996 100644
--- a/src/lib/checkout/components/Checkout.jsx
+++ b/src/lib/checkout/components/Checkout.jsx
@@ -126,7 +126,7 @@ const Checkout = () => {
`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/midtrans-payment?transactionId=${isCheckouted.id}`
)
for (const product of products) deleteItemCart({ productId: product.id })
- window.snap.pay(payment.data.token)
+ window.location.href = payment.data.redirectUrl
}
return (
@@ -252,7 +252,7 @@ const Checkout = () => {
<button
className='flex-1 btn-yellow'
onClick={checkout}
- disabled={isLoading}
+ disabled={isLoading || !products || products?.length == 0}
>
{isLoading ? 'Loading...' : 'Bayar'}
</button>
@@ -261,7 +261,7 @@ const Checkout = () => {
<Script
async
src='https://app.sandbox.midtrans.com/snap/snap.js'
- data-client-key=''
+ data-client-key={process.env.NEXT_PUBLIC_MIDTRANS_CLIENT_KEY}
/>
</>
)
diff --git a/src/lib/checkout/components/FinishCheckout.jsx b/src/lib/checkout/components/FinishCheckout.jsx
index a7d65dd0..f5346d67 100644
--- a/src/lib/checkout/components/FinishCheckout.jsx
+++ b/src/lib/checkout/components/FinishCheckout.jsx
@@ -1,8 +1,16 @@
import Link from '@/core/components/elements/Link/Link'
-import useTransaction from '@/lib/transaction/hooks/useTransaction'
+import axios from 'axios'
+import { useEffect } from 'react'
-const FinishCheckout = ({ id }) => {
- const { transaction } = useTransaction({ id })
+const FinishCheckout = ({ query }) => {
+ useEffect(() => {
+ if (query?.order_id) {
+ console.log(`${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/finish-checkout?orderName=${query.order_id}`);
+ axios.post(
+ `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/finish-checkout?orderId=${query.order_id}`
+ )
+ }
+ }, [query])
return (
<div className='p-4'>
@@ -13,11 +21,11 @@ const FinishCheckout = ({ id }) => {
Rincian belanja sudah kami kirimkan ke email anda. Mohon dicek kembali. jika tidak
menerima email, anda dapat menghubungi kami disini.
</p>
- <p className='mb-2 font-medium'>{transaction.data?.name}</p>
+ <p className='mb-2 font-medium'>{query?.order_id?.replaceAll('-', '/')}</p>
<p className='text-caption-2 text-yellow_r-11'>No. Transaksi</p>
</div>
<Link
- href={transaction.data?.id ? `/my/transaction/${transaction.data.id}` : '/'}
+ href='/my/transactions'
className='bg-yellow_r-6 text-yellow_r-12 rounded-b-xl py-4 block'
>
Lihat detail pembelian Anda disini
diff --git a/src/lib/checkout/email/FinishCheckoutEmail.jsx b/src/lib/checkout/email/FinishCheckoutEmail.jsx
new file mode 100644
index 00000000..950fe318
--- /dev/null
+++ b/src/lib/checkout/email/FinishCheckoutEmail.jsx
@@ -0,0 +1,326 @@
+import currencyFormat from '@/core/utils/currencyFormat'
+import toTitleCase from '@/core/utils/toTitleCase'
+import {
+ Body,
+ Column,
+ Container,
+ Head,
+ Heading,
+ Hr,
+ Html,
+ Img,
+ Row,
+ Section,
+ Text
+} from '@react-email/components'
+
+const FinishCheckoutEmail = ({ transaction, payment, statusPayment }) => {
+ return (
+ <Html>
+ <Head />
+ <Body style={style.main}>
+ <Container style={style.container}>
+ <Section style={{ marginTop: '32px' }}>
+ <Img
+ src={`${process.env.SELF_HOST}/images/indoteknik-logo.png`}
+ width='150'
+ height='50'
+ alt='Indoteknik.com'
+ style={{ margin: '0 auto' }}
+ />
+ </Section>
+ <Heading style={style.h1}>
+ {statusPayment == 'success' && 'Terimakasih untuk pembelian anda!'}
+ {statusPayment == 'pending' && 'Menunggu Pembayaran'}
+ {statusPayment == 'failed' && 'Pembayaran Tidak Berhasil'}
+ </Heading>
+
+ <Text style={style.text}>Hai {transaction.address.customer.name},</Text>
+ <Text style={style.text}>
+ {statusPayment == 'success' && (
+ <>
+ Terima kasih atas kepercayaan anda berbelanja di Indoteknik. Dengan ini kami
+ informasikan transaksi yang anda lakukan sebesar{' '}
+ <span style={{ color: '#E20613' }}>{currencyFormat(payment.grossAmount)}</span>{' '}
+ sudah berhasil dilakukan. Pembelian anda akan segera kami proses dan kirim sesuai
+ dengan antrian pesanan yang masuk.
+ </>
+ )}
+ {statusPayment == 'pending' && (
+ <>
+ Terima kasih atas kepercayaan anda berbelanja di Indoteknik. Dengan ini kami
+ informasikan transaksi yang anda lakukan sebesar{' '}
+ <span style={{ color: '#E20613' }}>{currencyFormat(payment.grossAmount)}</span>{' '}
+ belum dilakukan. Silahkan lakukan pembayaran pada hari ini sebelum stoknya
+ kehabisan.
+ </>
+ )}
+ {statusPayment == 'failed' && (
+ <>
+ Terima kasih atas kepercayaan anda berbelanja di Indoteknik. Dengan ini kami
+ informasikan transaksi yang anda lakukan Tidak Berhasil. Mohon untuk tidak melakukan
+ pembayaran dikarenakan transaksi ini gagal kami terima. Segera lakukan pembelian
+ kembali dengan produk yang anda inginkan di website Indoteknik.com.
+ </>
+ )}
+ </Text>
+ <Text style={style.text}>
+ {['pending', 'failed'].includes(statusPayment) && (
+ <>
+ Jika anda mengalami kesulitan, dapat menghubungi Customer Service kami untuk
+ menanyakan transaksi anda lakukan melalui Whatsapp kami.
+ </>
+ )}
+ {statusPayment == 'success' && (
+ <>
+ Anda dapat menghubungi Customer Service kami untuk menanyakan status pesanan yang
+ sudah berhasil anda lakukan melalui Whatsapp kami.
+ </>
+ )}
+ </Text>
+
+ <Text style={{ ...style.text, lineHeight: '100%', marginTop: '24px' }}>
+ <strong>Detail Transaksi</strong>
+ </Text>
+
+ <Hr style={style.hr} />
+
+ <Section style={style.alert}>
+ {statusPayment == 'success' &&
+ 'Struk ini dapat anda simpan sebagai bukti tambahan dalam transaksi yang telah dilakukan.'}
+ {statusPayment == 'pending' &&
+ 'Kami akan menginformasikan melalui email setelah anda berhasil melakukan pembayaran.'}
+ {statusPayment == 'failed' &&
+ 'Dimohon untuk tidak melakukan pembayaran. Karena transaksi anda tidak berhasil dibuat.'}
+ </Section>
+
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>No Transaksi (SO)</Column>
+ <Column style={style.descriptionRCol}>{transaction.name}</Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Tanggal Transaksi</Column>
+ <Column style={style.descriptionRCol}>{payment.transactionTime}</Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Status Pembayaran</Column>
+ <Column style={{ ...style.descriptionRCol }}>
+ {statusPayment == 'success' && (
+ <div style={{ ...style.badge, ...style.badgeGreen }}>Berhasil</div>
+ )}
+ {statusPayment == 'pending' && (
+ <div style={{ ...style.badge, ...style.badgeRed }}>Pending</div>
+ )}
+ {statusPayment == 'failed' && (
+ <div style={{ ...style.badge, ...style.badgeRed }}>Tidak Berhasil</div>
+ )}
+ </Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Metode Pembayaran</Column>
+ <Column style={style.descriptionRCol}>
+ {toTitleCase(payment.paymentType.replaceAll('_', ' '))}
+ </Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Batas Akhir Pembayaran</Column>
+ <Column style={style.descriptionRCol}>{payment.expiryTime}</Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Nominal Transfer</Column>
+ <Column style={style.descriptionRCol}>
+ <span style={{ fontWeight: '600' }}>{currencyFormat(payment.grossAmount)}</span>
+ </Column>
+ </Row>
+
+ <Text style={{ ...style.text, lineHeight: '100%', marginTop: '24px' }}>
+ <strong>Detail Produk</strong>
+ </Text>
+
+ <Hr style={style.hr} />
+
+ {transaction.products.map((product) => (
+ <Row
+ style={style.productRow}
+ key={product.id}
+ >
+ <Column style={style.productLCol}>
+ <Img
+ src={product.parent.image}
+ width='100%'
+ />
+ </Column>
+ <Column style={style.productRCol}>
+ <Text style={style.productName}>{product.name}</Text>
+ <Text style={style.productCode}>{product.code}</Text>
+ <div style={{ dislay: 'flex' }}>
+ <span style={style.productPriceA}>
+ {currencyFormat(product.price.priceDiscount)}
+ </span>
+ {product.price.discountPercentage > 0 && (
+ <>
+ &nbsp;
+ <span style={style.productPriceB}>{currencyFormat(product.price.price)}</span>
+ </>
+ )}
+ &nbsp; x {product.quantity} barang
+ </div>
+ </Column>
+ </Row>
+ ))}
+
+ <Hr style={style.hr} />
+
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Subtotal</Column>
+ <Column style={style.descriptionRCol}>{currencyFormat(transaction.subtotal)}</Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Total Diskon</Column>
+ <Column style={{ ...style.descriptionRCol, color: '#E20613' }}>
+ {currencyFormat(transaction.discountTotal)}
+ </Column>
+ </Row>
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>PPN 11% (Incl.)</Column>
+ <Column style={style.descriptionRCol}>
+ {currencyFormat(transaction.subtotal * 0.11)}
+ </Column>
+ </Row>
+
+ <Hr style={style.hr} />
+
+ <Row style={style.descriptionRow}>
+ <Column style={style.descriptionLCol}>Grand Total</Column>
+ <Column style={style.descriptionRCol}>
+ <span style={{ fontWeight: '600' }}>{currencyFormat(transaction.amountTotal)}</span>
+ </Column>
+ </Row>
+
+ <Hr style={style.hr} />
+
+ <Text style={{ ...style.text, margin: '12px 0 3px' }}>Best regards,</Text>
+
+ <Text style={{ ...style.text, margin: '3px 0 0' }}>
+ <strong>PT. Indoteknik Dotcom Gemilang</strong>
+ <br />
+ Jl. Bandengan Utara 85A No. 8-9 Penjaringan.
+ <br />
+ Kec. Penjaringan, Jakarta Utara - DKI Jakarta
+ </Text>
+ </Container>
+ </Body>
+ </Html>
+ )
+}
+
+const style = {
+ main: {
+ backgroundColor: '#ffffff',
+ margin: '0 auto',
+ fontFamily:
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif"
+ },
+ container: {
+ border: '1px solid #eaeaea',
+ borderRadius: '5px',
+ margin: '40px auto',
+ padding: '20px',
+ width: '465px'
+ },
+ h1: {
+ color: '#000',
+ fontSize: '24px',
+ fontWeight: 'normal',
+ textAlign: 'center',
+ margin: '30px 0',
+ padding: '0'
+ },
+ text: {
+ color: '#000',
+ fontSize: '14px',
+ lineHeight: '24px'
+ },
+ alert: {
+ backgroundColor: '#FDF1C7',
+ border: '1px solid #F8C20A',
+ padding: '8px',
+ borderRadius: '6px',
+ fontSize: '14px',
+ margin: '16px 0'
+ },
+ hr: {
+ border: 'none',
+ borderTop: '1px solid #eaeaea',
+ margin: '8px 0',
+ width: '100%'
+ },
+ descriptionRow: {
+ width: '100%',
+ margin: '10px 0',
+ fontSize: '14px'
+ },
+ descriptionLCol: {
+ width: '50%',
+ color: '#6B7280'
+ },
+ descriptionRCol: {
+ width: '50%',
+ textAlign: 'right'
+ },
+ productRow: {
+ width: '100%',
+ margin: '10px 0',
+ fontSize: '14px'
+ },
+ productLCol: {
+ width: '25%',
+ border: '1px solid #eaeaea',
+ borderRadius: '4px',
+ padding: '1px'
+ },
+ productRCol: {
+ width: '75%',
+ padding: '0 8px',
+ verticalAlign: 'top'
+ },
+ productName: {
+ lineHeight: '121%',
+ margin: '0 0 8px'
+ },
+ productCode: {
+ color: '#6B7280',
+ lineHeight: '100%',
+ margin: '0 0 8px',
+ fontSize: '14px'
+ },
+ productPriceA: {
+ lineHeight: '100%',
+ fontSize: '14px'
+ },
+ productPriceB: {
+ color: '#6B7280',
+ lineHeight: '100%',
+ fontSize: '14px',
+ textDecoration: 'line-through'
+ },
+ badge: {
+ padding: '3px 6px',
+ borderRadius: '6px',
+ fontSize: '14px',
+ width: 'fit-content',
+ marginLeft: 'auto'
+ },
+ badgeRed: {
+ color: '#E20613',
+ backgroundColor: '#FCE2E4',
+ border: '1px solid #E20613'
+ },
+ badgeGreen: {
+ color: '#16A34A',
+ backgroundColor: '#E7F4E9',
+ border: '1px solid #16A34A'
+ }
+}
+
+export default FinishCheckoutEmail