summaryrefslogtreecommitdiff
path: root/src/lib/transaction/components/Transaction.jsx
diff options
context:
space:
mode:
authorIT Fixcomart <it@fixcomart.co.id>2023-03-01 09:18:52 +0000
committerIT Fixcomart <it@fixcomart.co.id>2023-03-01 09:18:52 +0000
commita7abbf4ddc70068620e9f44b74dc162ce2e16ee2 (patch)
tree74f66253717515d364ce74bd8275015c1f829cbc /src/lib/transaction/components/Transaction.jsx
parent90e1edab9b6a8ccc09a49fed3addbec2cbc4e4c3 (diff)
parenta1b9b647a6c4bda1f5db63879639d44543f9557e (diff)
Merged in refactor (pull request #1)
Refactor
Diffstat (limited to 'src/lib/transaction/components/Transaction.jsx')
-rw-r--r--src/lib/transaction/components/Transaction.jsx352
1 files changed, 352 insertions, 0 deletions
diff --git a/src/lib/transaction/components/Transaction.jsx b/src/lib/transaction/components/Transaction.jsx
new file mode 100644
index 00000000..7da33551
--- /dev/null
+++ b/src/lib/transaction/components/Transaction.jsx
@@ -0,0 +1,352 @@
+import Spinner from '@/core/components/elements/Spinner/Spinner'
+import useTransaction from '../hooks/useTransaction'
+import TransactionStatusBadge from './TransactionStatusBadge'
+import Divider from '@/core/components/elements/Divider/Divider'
+import { useRef, useState } from 'react'
+import { downloadPurchaseOrder, downloadQuotation } from '../utils/transactions'
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
+import uploadPoApi from '../api/uploadPoApi'
+import { toast } from 'react-hot-toast'
+import getFileBase64 from '@/core/utils/getFileBase64'
+import currencyFormat from '@/core/utils/currencyFormat'
+import VariantGroupCard from '@/lib/variant/components/VariantGroupCard'
+import { ChevronDownIcon, ChevronRightIcon, ChevronUpIcon } from '@heroicons/react/24/outline'
+import Link from '@/core/components/elements/Link/Link'
+import Alert from '@/core/components/elements/Alert/Alert'
+import checkoutPoApi from '../api/checkoutPoApi'
+import cancelTransactionApi from '../api/cancelTransactionApi'
+
+const Transaction = ({ id }) => {
+ const { transaction } = useTransaction({ id })
+
+ const poNumber = useRef('')
+ const poFile = useRef('')
+ const [uploadPo, setUploadPo] = useState(false)
+ const openUploadPo = () => setUploadPo(true)
+ const closeUploadPo = () => setUploadPo(false)
+ const submitUploadPo = async () => {
+ const file = poFile.current.files[0]
+ const name = poNumber.current.value
+ if (typeof file === 'undefined' || !name) {
+ toast.error('Nomor dan Dokumen PO harus diisi', { position: 'bottom-center' })
+ return
+ }
+ if (file.size > 5000000) {
+ toast.error('Maksimal ukuran file adalah 5MB', { position: 'bottom-center' })
+ return
+ }
+ const data = { name, file: await getFileBase64(file) }
+ const isUploaded = await uploadPoApi({ id, data })
+ if (isUploaded) {
+ toast.success('Berhasil upload PO')
+ transaction.refetch()
+ closeUploadPo()
+ return
+ }
+ toast.error('Terjadi kesalahan internal, coba lagi nanti atau hubungi kami')
+ }
+
+ const [cancelTransaction, setCancelTransaction] = useState(false)
+ const openCancelTransaction = () => setCancelTransaction(true)
+ const closeCancelTransaction = () => setCancelTransaction(false)
+ const submitCancelTransaction = async () => {
+ const isCancelled = await cancelTransactionApi({ transaction: transaction.data })
+ if (isCancelled) {
+ toast.success('Berhasil batalkan transaksi')
+ transaction.refetch()
+ }
+ closeCancelTransaction()
+ }
+
+ const checkout = async () => {
+ if (!transaction.data?.purchaseOrderFile) {
+ toast.error('Mohon upload dokumen PO anda sebelum melanjutkan pesanan')
+ return
+ }
+ await checkoutPoApi({ id })
+ toast.success('Berhasil melanjutkan pesanan')
+ transaction.refetch()
+ }
+
+ if (transaction.isLoading) {
+ return (
+ <div className='flex justify-center my-6'>
+ <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' />
+ </div>
+ )
+ }
+
+ return (
+ transaction.data?.name && (
+ <>
+ <div className='flex flex-col gap-y-4 p-4'>
+ <DescriptionRow label='Status Transaksi'>
+ <div className='flex justify-end'>
+ <TransactionStatusBadge status={transaction.data?.status} />
+ </div>
+ </DescriptionRow>
+ <DescriptionRow label='No Transaksi'>{transaction.data?.name}</DescriptionRow>
+ <DescriptionRow label='Ketentuan Pembayaran'>
+ {transaction.data?.paymentTerm}
+ </DescriptionRow>
+ <DescriptionRow label='Nama Sales'>{transaction.data?.sales}</DescriptionRow>
+ <DescriptionRow label='Waktu Transaksi'>{transaction.data?.dateOrder}</DescriptionRow>
+ </div>
+
+ <Divider />
+
+ <div className='p-4 flex flex-col gap-y-4'>
+ <DescriptionRow label='Purchase Order'>
+ {transaction.data?.purchaseOrderName || '-'}
+ </DescriptionRow>
+ <div className='flex items-center'>
+ <p className='text-gray_r-11 leading-none'>Dokumen PO</p>
+ <button
+ type='button'
+ className='btn-light py-1.5 px-3 ml-auto'
+ onClick={
+ transaction.data?.purchaseOrderFile
+ ? () => downloadPurchaseOrder(transaction.data)
+ : openUploadPo
+ }
+ >
+ {transaction.data?.purchaseOrderFile ? 'Download' : 'Upload'}
+ </button>
+ </div>
+ </div>
+
+ <Divider />
+
+ <div className='font-medium p-4'>Detail Produk</div>
+
+ <div className='p-4 pt-0 flex flex-col gap-y-3'>
+ <VariantGroupCard
+ variants={transaction.data?.products}
+ buyMore
+ />
+ <div className='flex justify-between mt-3 font-medium'>
+ <p>Total Belanja</p>
+ <p>{currencyFormat(transaction.data?.amountTotal)}</p>
+ </div>
+ </div>
+
+ <Divider />
+
+ <SectionAddress address={transaction.data?.address} />
+
+ <Divider />
+
+ <div className='p-4'>
+ <p className='font-medium'>Invoice</p>
+ <div className='flex flex-col gap-y-3 mt-4'>
+ {transaction.data?.invoices?.map((invoice, index) => (
+ <Link
+ href={`/my/invoice/${invoice.id}`}
+ key={index}
+ >
+ <div className='shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between'>
+ <div>
+ <p className='mb-2'>{invoice?.name}</p>
+ <div className='flex items-center gap-x-1'>
+ {invoice.amountResidual > 0 ? (
+ <div className='badge-red'>Belum Lunas</div>
+ ) : (
+ <div className='badge-green'>Lunas</div>
+ )}
+ <p className='text-caption-2 text-gray_r-11'>
+ {currencyFormat(invoice.amountTotal)}
+ </p>
+ </div>
+ </div>
+ <ChevronRightIcon className='w-5 stroke-2' />
+ </div>
+ </Link>
+ ))}
+ {transaction.data?.invoices?.length === 0 && (
+ <Alert
+ type='info'
+ className='text-center'
+ >
+ Belum ada Invoice
+ </Alert>
+ )}
+ </div>
+ </div>
+
+ <Divider />
+
+ <div className='p-4 pt-0'>
+ {transaction.data?.status == 'draft' && (
+ <button
+ className='btn-yellow w-full mt-4'
+ onClick={checkout}
+ >
+ Lanjutkan Transaksi
+ </button>
+ )}
+ <button
+ className='btn-light w-full mt-4'
+ disabled={transaction.data?.status != 'draft'}
+ onClick={downloadQuotation}
+ >
+ Download Quotation
+ </button>
+ {transaction.data?.status != 'draft' && (
+ <button
+ className='btn-light w-full mt-4'
+ disabled={transaction.data?.status != 'waiting'}
+ onClick={openCancelTransaction}
+ >
+ Batalkan Transaksi
+ </button>
+ )}
+ </div>
+
+ <BottomPopup
+ active={cancelTransaction}
+ close={closeCancelTransaction}
+ title='Batalkan Transaksi'
+ >
+ <div className='leading-7 text-gray_r-12/80'>
+ Apakah anda yakin membatalkan transaksi{' '}
+ <span className='underline'>{transaction.data?.name}</span>?
+ </div>
+ <div className='flex mt-6 gap-x-4'>
+ <button
+ className='btn-solid-red flex-1'
+ type='button'
+ onClick={submitCancelTransaction}
+ >
+ Ya, Batalkan
+ </button>
+ <button
+ className='btn-light flex-1'
+ type='button'
+ onClick={closeCancelTransaction}
+ >
+ Batal
+ </button>
+ </div>
+ </BottomPopup>
+
+ <BottomPopup
+ title='Upload PO'
+ close={closeUploadPo}
+ active={uploadPo}
+ >
+ <div>
+ <label>Nomor PO</label>
+ <input
+ type='text'
+ className='form-input mt-3'
+ ref={poNumber}
+ />
+ </div>
+ <div className='mt-4'>
+ <label>Dokumen PO</label>
+ <input
+ type='file'
+ className='form-input mt-3 py-2'
+ ref={poFile}
+ />
+ </div>
+ <div className='grid grid-cols-2 gap-x-3 mt-6'>
+ <button
+ type='button'
+ className='btn-light w-full'
+ onClick={closeUploadPo}
+ >
+ Batal
+ </button>
+ <button
+ type='button'
+ className='btn-solid-red w-full'
+ onClick={submitUploadPo}
+ >
+ Upload
+ </button>
+ </div>
+ </BottomPopup>
+ </>
+ )
+ )
+}
+
+const SectionAddress = ({ address }) => {
+ const [section, setSection] = useState({
+ customer: false,
+ invoice: false,
+ shipping: false
+ })
+ const toggleSection = (name) => {
+ setSection({ ...section, [name]: !section[name] })
+ }
+
+ return (
+ <>
+ <SectionButton
+ label='Detail Pelanggan'
+ active={section.customer}
+ toggle={() => toggleSection('customer')}
+ />
+
+ {section.customer && <SectionContent address={address?.customer} />}
+
+ <Divider />
+
+ <SectionButton
+ label='Detail Pengiriman'
+ active={section.shipping}
+ toggle={() => toggleSection('shipping')}
+ />
+
+ {section.shipping && <SectionContent address={address?.shipping} />}
+
+ <Divider />
+
+ <SectionButton
+ label='Detail Penagihan'
+ active={section.invoice}
+ toggle={() => toggleSection('invoice')}
+ />
+ {section.invoice && <SectionContent address={address?.invoice} />}
+ </>
+ )
+}
+
+const SectionButton = ({ label, active, toggle }) => (
+ <button
+ className='p-4 font-medium flex justify-between w-full'
+ onClick={toggle}
+ >
+ <span>{label}</span>
+ {active ? <ChevronUpIcon className='w-5' /> : <ChevronDownIcon className='w-5' />}
+ </button>
+)
+
+const SectionContent = ({ address }) => {
+ let fullAddress = []
+ if (address?.street) fullAddress.push(address.street)
+ if (address?.subDistrict?.name) fullAddress.push(address.subDistrict.name)
+ if (address?.district?.name) fullAddress.push(address.district.name)
+ if (address?.city?.name) fullAddress.push(address.city.name)
+ fullAddress = fullAddress.join(', ')
+
+ return (
+ <div className='flex flex-col gap-y-4 p-4 border-t border-gray_r-6'>
+ <DescriptionRow label='Nama'>{address.name}</DescriptionRow>
+ <DescriptionRow label='Email'>{address.email || '-'}</DescriptionRow>
+ <DescriptionRow label='No Telepon'>{address.mobile || '-'}</DescriptionRow>
+ <DescriptionRow label='Alamat'>{fullAddress}</DescriptionRow>
+ </div>
+ )
+}
+
+const DescriptionRow = ({ children, label }) => (
+ <div className='grid grid-cols-2'>
+ <span className='text-gray_r-11'>{label}</span>
+ <span className='text-right'>{children}</span>
+ </div>
+)
+
+export default Transaction