diff options
| author | Miqdad <ahmadmiqdad27@gmail.com> | 2025-08-27 13:16:59 +0700 |
|---|---|---|
| committer | Miqdad <ahmadmiqdad27@gmail.com> | 2025-08-27 13:16:59 +0700 |
| commit | 3a9a0995dad8d3deb602534814a6bb79b26afb54 (patch) | |
| tree | 388e769c108edc0f05d8f3bb79b9a6ec797935e9 | |
| parent | 22eec2b12a2f8a079018070efa28757401de308e (diff) | |
<Miqdad> Push Sementara
| -rw-r--r-- | src/lib/transaction/components/Transactions.jsx | 615 |
1 files changed, 196 insertions, 419 deletions
diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx index fab9eb5c..0d7e3f2c 100644 --- a/src/lib/transaction/components/Transactions.jsx +++ b/src/lib/transaction/components/Transactions.jsx @@ -1,11 +1,10 @@ import { useRouter } from 'next/router'; -import { useEffect, useState, useRef } from 'react'; +import { useEffect, useState, useRef } from 'react'; import { toast } from 'react-hot-toast'; import { EllipsisVerticalIcon, MagnifyingGlassIcon, ChevronDownIcon, - ChevronUpIcon, } from '@heroicons/react/24/outline'; import useAuth from '@/core/hooks/useAuth'; import { @@ -38,13 +37,11 @@ import { Navigation } from 'swiper'; import 'swiper/css'; import 'swiper/css/navigation'; import { Calendar } from 'lucide-react'; -import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; import { DateRangePicker } from 'react-date-range'; -import { addDays } from 'date-fns'; -import 'react-date-range/dist/styles.css'; // main style file -import 'react-date-range/dist/theme/default.css'; // theme css file -import { Popover } from '@headlessui/react'; +import 'react-date-range/dist/styles.css'; +import 'react-date-range/dist/theme/default.css'; +import { fetchPaymentSummary } from '../api/regenerate'; + const Transactions = ({ context = '' }) => { const auth = useAuth(); const router = useRouter(); @@ -59,14 +56,8 @@ const Transactions = ({ context = '' }) => { startDate = null, endDate = new Date(), } = router.query; - const { - productCart, - setRefreshCart, - setProductCart, - refreshCart, - isLoading, - setIsloading, - } = useProductCartContext(); + const { setRefreshCart } = useProductCartContext(); + const [inputQuery, setInputQuery] = useState(q); const [toOthers, setToOthers] = useState(null); const [toCancel, setToCancel] = useState(null); @@ -75,17 +66,16 @@ const Transactions = ({ context = '' }) => { const [siteFilter, setSiteFilter] = useState(site); const [pageNew, setPageNew] = useState(page); const [limitNew, setLimitNew] = useState(limit); - // const [status, setStatus] = useState('idle'); const [statusNew, setStatusNew] = useState(status); const [sortNew, setSortNew] = useState(sort); const [contextNew, setcontextNew] = useState(router.query.context || context); - const [dateRange, setDateRange] = useState([null, null]); - // const [startDate, endDate] = dateRange; const [isOpenCalender, setIsOpenCalender] = useState(false); - const [cachedAllData, setCachedAllData] = useState(null); // Simpan data "All" - const [currentData, setCurrentData] = useState([]); // Data yang ditampilkan + const [cachedAllData, setCachedAllData] = useState(null); + const [currentData, setCurrentData] = useState([]); const calendarRef = useRef(null); - const [isDateSelected, setIsDateSelected] = useState(false); + + // loading id utk tombol lanjutkan transaksi + const [contLoadingId, setContLoadingId] = useState(null); const parseDate = (date) => { if (!date || date === 'null') return null; @@ -96,7 +86,7 @@ const Transactions = ({ context = '' }) => { const [state, setState] = useState([ { - startDate: startDate != null || 'null' ? parseDate(startDate) : null, // Gunakan `parseDate` + startDate: startDate != null || 'null' ? parseDate(startDate) : null, endDate: startDate == null ? endDate : parseDate(endDate), key: 'selection', }, @@ -116,6 +106,7 @@ const Transactions = ({ context = '' }) => { site: siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null), }; + const statuses = [ { id: 'all', label: 'Semua' }, { id: 'quotation', label: 'Pending Quotation' }, @@ -142,16 +133,16 @@ const Transactions = ({ context = '' }) => { { id: 'asc', label: 'dari yang terkecil' }, { id: 'desc', label: 'dari yang terbesar' }, ]; + const { transactions } = useTransactions({ query }); + const fetchSite = async () => { const site = await getSite(); setListSites(site.sites); }; const submitCancelTransaction = async () => { - const isCancelled = await cancelTransactionApi({ - transaction: toCancel, - }); + const isCancelled = await cancelTransactionApi({ transaction: toCancel }); if (isCancelled) { toast.success('Berhasil batalkan transaksi'); transactions.refetch(); @@ -172,10 +163,7 @@ const Transactions = ({ context = '' }) => { const queryParams = {}; if (inputQuery) queryParams.q = inputQuery; if (siteFilter) queryParams.site = siteFilter; - router.push({ - pathname: router.pathname, - query: queryParams, - }); + router.push({ pathname: router.pathname, query: queryParams }); }; const handleSiteFilterChange = (e) => { @@ -183,10 +171,7 @@ const Transactions = ({ context = '' }) => { const queryParams = {}; if (inputQuery) queryParams.q = inputQuery; if (e.target.value) queryParams.site = e.target.value; - router.push({ - pathname: router.pathname, - query: queryParams, - }); + router.push({ pathname: router.pathname, query: queryParams }); }; const exportToExcel = (data, siteFilter) => { @@ -211,9 +196,7 @@ const Transactions = ({ context = '' }) => { Total: currencyFormat(saleOrder.amountTotal), Status: contextLabelMap[saleOrder.status] || saleOrder.status, }; - if (siteFilter) { - row['Site'] = siteFilter; - } + if (siteFilter) row['Site'] = siteFilter; rowsToExport.push(row); }); @@ -226,13 +209,30 @@ const Transactions = ({ context = '' }) => { XLSX.writeFile(workbook, 'transactions.xlsx'); }; + const getAllData = async () => { + const query = { + name: q, + offset: (pageNew - 1) * limitNew, + limit: limitNew, + context: contextNew[statusNew] || 'all', + sort: sortNew, + startDate: state[0]?.startDate + ? state[0].startDate.toLocaleDateString('id-ID') + : null, + endDate: state[0]?.endDate + ? state[0].endDate.toLocaleDateString('id-ID') + : null, + site: + siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null), + }; + const queryString = toQuery(query); + const data = await transactionsApi({ query: queryString }); + return data; + }; + const handleExportCSV = async () => { const dataToExport = await getAllData(); - exportToCSV(dataToExport?.saleOrders, siteFilter); - }; - - const exportToCSV = (data, siteFilter) => { const fieldsToExport = [ 'No. Transaksi', 'No. PO', @@ -242,28 +242,20 @@ const Transactions = ({ context = '' }) => { 'Total', 'Status', ]; - - if (siteFilter) { - fieldsToExport.push('Site'); - } - - const rowsToExport = data.map((saleOrder) => { - const row = [ - saleOrder.name, - saleOrder.purchaseOrderName || '-', - saleOrder.dateOrder || '-', - saleOrder.address.customer?.name || '-', - saleOrder.sales, - currencyFormat(saleOrder.amountTotal), - contextLabelMap[saleOrder.status] || saleOrder.status, - ]; - - if (siteFilter) { - row.push(siteFilter); - } - - return row.join(','); - }); + const rowsToExport = + dataToExport?.saleOrders?.map((saleOrder) => { + const row = [ + saleOrder.name, + saleOrder.purchaseOrderName || '-', + saleOrder.dateOrder || '-', + saleOrder.address.customer?.name || '-', + saleOrder.sales, + currencyFormat(saleOrder.amountTotal), + contextLabelMap[saleOrder.status] || saleOrder.status, + ]; + if (siteFilter) row.push(siteFilter); + return row.join(','); + }) || []; const csvContent = 'data:text/csv;charset=utf-8,' + @@ -278,60 +270,25 @@ const Transactions = ({ context = '' }) => { document.body.removeChild(link); }; - const getAllData = async () => { - const query = { - name: q, - offset: (pageNew - 1) * limitNew, - limit: limitNew, - context: contextNew[statusNew] || 'all', - sort: sortNew, - startDate: state[0]?.startDate - ? state[0].startDate.toLocaleDateString('id-ID') - : null, - endDate: state[0]?.endDate - ? state[0].endDate.toLocaleDateString('id-ID') - : null, - site: - siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null), - }; - const queryString = toQuery(query); - const data = await transactionsApi({ query: queryString }); - return data; - }; - const handleExportExcel = async () => { const dataToExport = await getAllData(); - exportToExcel(dataToExport?.saleOrders, siteFilter); }; const handleDownload = (format) => { - handleExport(format); + if (format === 'csv') handleExportCSV(); + else if (format === 'xlsx') handleExportExcel(); setIsOpen(false); }; - const handleExport = (format) => { - if (format === 'csv') { - handleExportCSV(); - } else if (format === 'xlsx') { - handleExportExcel(); - } - }; - useEffect(() => { const handleClickOutside = (event) => { - if ( - calendarRef.current && - !calendarRef.current.contains(event.target) - ) { + if (calendarRef.current && !calendarRef.current.contains(event.target)) { setIsOpenCalender(false); } }; - - document.addEventListener("mousedown", handleClickOutside); - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const startItem = 1 + (pageNew - 1) * limitNew; @@ -346,9 +303,6 @@ const Transactions = ({ context = '' }) => { const handleBuyBack = async (products) => { try { - // setStatus('loading'); - console.log("Products to add:", products); - const results = await Promise.all( products.map((product) => upsertUserCart({ @@ -359,55 +313,44 @@ const Transactions = ({ context = '' }) => { selected: true, source: 'add_to_cart', qtyAppend: true, - }).catch(error => { - return { error, product }; - }) + }).catch((error) => ({ error, product })) ) ); - const failedOperations = results.filter(result => result && result.error); - // console.log(results); - + const failedOperations = results.filter((r) => r && r.error); if (failedOperations.length > 0) { - console.error('Some products failed to add to cart:', failedOperations); - toast.error(`${failedOperations.length} produk gagal ditambahkan ke keranjang`); - - // You might want to proceed with the successful ones or handle differently + toast.error( + `${failedOperations.length} produk gagal ditambahkan ke keranjang` + ); if (failedOperations.length < products.length) { - toast.success(`${products.length - failedOperations.length} produk berhasil ditambahkan ke keranjang`); + toast.success( + `${ + products.length - failedOperations.length + } produk berhasil ditambahkan` + ); setRefreshCart(true); router.push('/shop/cart'); } return; } - - // All operations succeeded setRefreshCart(true); - toast.success('Semua produk berhasil ditambahkan ke keranjang belanja'); + toast.success('Semua produk berhasil ditambahkan ke keranjang'); router.push('/shop/cart'); - } catch (error) { - console.error('Gagal menambahkan produk ke keranjang:', error); toast.error('Terjadi kesalahan saat menambahkan produk ke keranjang'); - // setStatus('error'); } }; - const handleStatusChange = async (status) => { setStatusNew(status); setPageNew(1); if (status === 'all' && cachedAllData) { - setCurrentData(cachedAllData); - return; + setCurrentData(cachedAllData); + return; } const data = await fetchSite(status, 1); - - if (status === 'all') { - setCachedAllData(data); - } - + if (status === 'all') setCachedAllData(data); setCurrentData(data); }; @@ -415,15 +358,8 @@ const Transactions = ({ context = '' }) => { setCachedAllData([]); }, []); - const handleReset = () => { - setState([ - { - startDate: null, - endDate: new Date(), - key: 'selection', - }, - ]); + setState([{ startDate: null, endDate: new Date(), key: 'selection' }]); setIsOpenCalender(false); router.push(`${router.pathname}`); }; @@ -443,13 +379,68 @@ const Transactions = ({ context = '' }) => { 'November', 'Desember', ]; - const [day, month, year] = dateString.split('/'); return `${day} ${months[parseInt(month, 10) - 1]} ${year}`; }; + // ==== Lanjutkan Transaksi ==== + const handleContinuePayment = async (saleOrder) => { + try { + const partnerId = + auth?.partnerId || auth?.partner_id || auth?.partner?.id || auth?.id; + + setContLoadingId(saleOrder.id); + + // 1) coba pakai URL yang sudah dikirim dari list + const existingUrl = + saleOrder?.paymentSummary?.redirectUrl || + saleOrder?.paymentLinkMidtrans; + + if (existingUrl) { + window.open(existingUrl, '_blank', 'noopener,noreferrer'); + toast.success('Membuka halaman pembayaran…'); + return; + } + + // 2) fallback: generate baru via API + const res = await fetchPaymentSummary({ + partnerId, + saleOrderId: saleOrder.id, + autogen: true, + }); + + const eligible = + res?.eligible_continue ?? + res?.eligibleContinue ?? + res?.eligible ?? + false; + + if (!eligible) { + toast.error('Transaksi belum memenuhi syarat untuk dilanjutkan.'); + return; + } + + const redirectUrl = res?.redirect_url || res?.redirectUrl; + if (redirectUrl) { + window.open(redirectUrl, '_blank', 'noopener,noreferrer'); + toast.success('Membuka halaman pembayaran…'); + } else { + toast.error('Link pembayaran belum tersedia.'); + } + } catch (e) { + const msg = + e?.response?.data?.description || + e?.message || + 'Gagal melanjutkan transaksi'; + toast.error(msg); + } finally { + setContLoadingId(null); + } + }; + return ( <> + {/* ===== MOBILE ===== */} <MobileView> <div className=' flex flex-col gap-y-4'> <div className='grid grid-cols-[40%_40%_15%] justify-between items-center gap-2 w-full '> @@ -491,7 +482,6 @@ const Transactions = ({ context = '' }) => { </button> {isOpenCalender && ( <div className='absolute right-1 mt-2 bg-white p-4 rounded shadow-lg z-50'> - {/* Tombol silang di sudut kanan atas */} <button onClick={() => setIsOpenCalender(false)} className='absolute top-2 right-2 text-gray-600 hover:text-black text-xl font-bold' @@ -508,37 +498,13 @@ const Transactions = ({ context = '' }) => { className='w-full' /> <style>{` - /* Atur container agar menjadi column */ - .rdrCalendarWrapper { - display: flex; - flex-direction: column; - } - .rdrDateRangePickerWrapper { - display: flex; - flex-direction: column; - } - - /* Pindahkan rdrStaticRanges ke atas */ - .rdrDefinedRangesWrapper { - order: -1; - width: fit-content; - } - .rdrStaticRanges { - flex-direction: row; - margin-right: 2px; - } - - /* Sembunyikan bagian input manual */ - .rdrInputRanges { - display: none !important; - } - - .rdrStaticRangeLabel { - padding: 10px 10px; - } - .rdrMonth { - width: -moz-available; - } + .rdrCalendarWrapper{display:flex;flex-direction:column;} + .rdrDateRangePickerWrapper{display:flex;flex-direction:column;} + .rdrDefinedRangesWrapper{order:-1;width:fit-content;} + .rdrStaticRanges{flex-direction:row;margin-right:2px;} + .rdrInputRanges{display:none !important;} + .rdrStaticRangeLabel{padding:10px 10px;} + .rdrMonth{width:-moz-available;} `}</style> <div className='flex flex-row justify-end gap-3 mt-2'> <button @@ -551,67 +517,6 @@ const Transactions = ({ context = '' }) => { </div> )} </div> - {/* <div className='border border-gray-300 rounded-lg px-1 py-1 bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500 text-xs'> - <DatePicker - closeOnScroll={(e) => e.target === document} - selectsRange={true} - startDate={startDate} - endDate={endDate} - dateFormat='dd/MM' - className='w-full' - maxDate={new Date()} - placeholderText='Semua Tanggal' - onChange={(update) => { - setDateRange(update); - }} - withPortal - isClearable={true} - /> - </div> */} - </div> - <div className='flex flex-row justify-between items-center gap-2'> - <form className='flex' onSubmit={handleSubmit}> - <button - className='btn-light border-r-0 rounded-r-none bg-transparent px-3' - type='submit' - > - <MagnifyingGlassIcon className='w-6' /> - </button> - <input - type='text' - className='form-input border-l-0 rounded-l-none text-xs' - placeholder='Cari Transaksi...' - value={inputQuery} - onChange={(e) => setInputQuery(e.target.value)} - /> - </form> - <div className='flex flex-row gap-2 items-center justify-center text-nowrap'> - <p className='text-xs'> - Menampilkan {startItem}- - {endItem - ? endItem - : transactions?.data?.saleOrderTotal - ? transactions?.data?.saleOrderTotal - : limitNew * pageNew}{' '} - dari{' '} - {transactions?.data?.saleOrderTotal - ? transactions?.data?.saleOrderTotal - : limitNew * pageNew} - </p> - <select - id='limitSelect' - value={limitNew} - onChange={(e) => { - setLimitNew(Number(e.target.value)); - setPageNew(1); - }} - className='border p-2 text-xs' - > - <option value={10}>10</option> - <option value={15}>15</option> - <option value={20}>20</option> - </select> - </div> </div> {transactions.isLoading && ( @@ -683,9 +588,9 @@ const Transactions = ({ context = '' }) => { <div className='flex flex-row gap-1 justify-start items-center'> {saleOrder.products .slice(1, 4) - .map((product, index) => ( + .map((product, idx) => ( <Image - key={index} // Tambahkan key untuk setiap elemen dalam map() + key={idx} src={product?.parent?.image} alt={product?.name} className='object-contain object-center border border-gray_r-6 h-8 w-8 rounded-md' @@ -719,6 +624,7 @@ const Transactions = ({ context = '' }) => { </div> </div> <div className='col-span-2 h-[1px] w-full bg-gray-300'></div> + <div className='flex flex-col gap-3 text-sm'> <div className='flex flex-col text-black'> <p className='font-extralight'>Total Harga</p> @@ -727,7 +633,6 @@ const Transactions = ({ context = '' }) => { </p> </div> - {/* Tombol aksi: vertikal & full width, responsif */} <div className='flex flex-col gap-2 w-full'> <button type='button' @@ -741,53 +646,24 @@ const Transactions = ({ context = '' }) => { Beli Lagi </button> - <button - type='button' - onClick={(e) => { - e.preventDefault(); - e.stopPropagation(); - }} - className='w-full py-2 text-center rounded-md border border-red-300 text-red-500 bg-white' - > - Lanjutkan Transaksi - </button> + {saleOrder?.eligibleContinue && ( + <button + type='button' + disabled={contLoadingId === saleOrder.id} + onClick={(e) => { + e.preventDefault(); + e.stopPropagation(); + handleContinuePayment(saleOrder); + }} + className='w-full py-2 text-center rounded-md border border-red-300 text-red-500 bg-white disabled:opacity-60' + > + {contLoadingId === saleOrder.id + ? 'Memproses…' + : 'Lanjutkan Transaksi'} + </button> + )} </div> </div> - - {/* <div className='grid grid-cols-2 mt-3'> - <div> - <span className='text-caption-2 text-gray_r-11'> - No. Purchase Order - </span> - <p className='mt-1 font-medium text-gray_r-12'> - {saleOrder.purchaseOrderName || '-'} - </p> - </div> - <div className='text-right'> - <span className='text-caption-2 text-gray_r-11'> - Total Invoice - </span> - <p className='mt-1 font-medium text-gray_r-12'> - {saleOrder.invoiceCount} Invoice - </p> - </div> - </div> */} - {/* <div className='grid grid-cols-2 mt-3'> - <div> - <span className='text-caption-2 text-gray_r-11'>Sales</span> - <p className='mt-1 font-medium text-gray_r-12'> - {saleOrder.sales} - </p> - </div> - <div className='text-right'> - <span className='text-caption-2 text-gray_r-11'> - Total Harga - </span> - <p className='mt-1 font-medium text-gray_r-12'> - {currencyFormat(saleOrder.amountTotal)} - </p> - </div> - </div> */} </Link> </div> ))} @@ -795,7 +671,6 @@ const Transactions = ({ context = '' }) => { <Pagination pageCount={pageCount} currentPage={parseInt(pageNew)} - // url={router.pathname + pageQuery} url={`${router.pathname}?${toQuery(_.omit(query, ['page']))}`} className='mt-2 mb-2' /> @@ -868,6 +743,7 @@ const Transactions = ({ context = '' }) => { </div> </MobileView> + {/* ===== DESKTOP ===== */} <DesktopView> <div className='container mx-auto flex py-10'> <div className='w-3/12 pr-4'> @@ -920,29 +796,7 @@ const Transactions = ({ context = '' }) => { )} </div> </div> - <div className=''> - <div - class='flex items-center p-4 mb-4 text-sm border border-yellow-500 text-yellow-800 rounded-lg bg-yellow-50' - role='alert' - > - <svg - class='flex-shrink-0 inline w-5 h-5 mr-2' - aria-hidden='true' - fill='currentColor' - viewBox='0 0 20 20' - > - <path d='M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z' /> - </svg> - <span class='sr-only'>Info</span> - <div className='text-justify flex flex-col gap-1'> - <p className='font-bold text-black'>Info Transaksi</p> - <span className='text-black'> - Gunakan filter status untuk mempermudah pencarian transaksi - anda di Daftar Transaksi - </span> - </div> - </div> - </div> + <div className='flex flex-col gap-y-2 border rounded-lg mb-2 w-full'> <div className='p-2'> <div className='flex items-center space-x-3'> @@ -950,9 +804,7 @@ const Transactions = ({ context = '' }) => { Status </span> <div className='relative w-full overflow-hidden'> - {/* Container flex: tombol prev - swiper - tombol next */} <div className='flex items-center space-x-2'> - {/* Prev */} <button className='custom-prev w-8 h-8 flex-shrink-0 flex items-center justify-center bg-white border rounded-full shadow z-1'> <svg className='w-4 h-4 text-gray-500' @@ -969,7 +821,6 @@ const Transactions = ({ context = '' }) => { </svg> </button> - {/* Swiper container scrollable */} <div className='w-full overflow-hidden'> <Swiper spaceBetween={10} @@ -999,7 +850,6 @@ const Transactions = ({ context = '' }) => { </Swiper> </div> - {/* Next */} <button className='custom-next w-8 h-8 flex-shrink-0 flex items-center justify-center bg-white border rounded-full shadow z-10'> <svg className='w-4 h-4 text-gray-500' @@ -1019,6 +869,7 @@ const Transactions = ({ context = '' }) => { </div> </div> </div> + <div className='flex flex-row items-center justify-between mb-2 p-2'> <div className='flex flex-col gap-2 pb-2'> {listSites?.length > 0 ? ( @@ -1054,6 +905,7 @@ const Transactions = ({ context = '' }) => { </button> </form> </div> + <div className='flex flex-row gap-4 items-center justify-center'> <p> Menampilkan {startItem}- @@ -1083,6 +935,7 @@ const Transactions = ({ context = '' }) => { Semua </option> </select> + <div ref={calendarRef} className='relative inline-block'> <button type='button' @@ -1099,7 +952,6 @@ const Transactions = ({ context = '' }) => { </button> {isOpenCalender && ( <div className='absolute right-10 mt-2 bg-white p-4 rounded shadow-lg z-50'> - {/* Tombol silang di sudut kanan atas */} <button onClick={() => setIsOpenCalender(false)} className='absolute top-2 right-2 text-gray-600 hover:text-black text-xl font-bold' @@ -1116,38 +968,14 @@ const Transactions = ({ context = '' }) => { className='w-full' /> <style>{` - /* Atur container agar menjadi column */ - .rdrCalendarWrapper { - display: flex; - flex-direction: column; - } - .rdrDateRangePickerWrapper { - display: flex; - flex-direction: column; - } - - /* Pindahkan rdrStaticRanges ke atas */ - .rdrDefinedRangesWrapper { - order: -1; - width: fit-content; - } - .rdrStaticRanges { - flex-direction: row; - margin-right: 2px; - } - - /* Sembunyikan bagian input manual */ - .rdrInputRanges { - display: none !important; - } - - .rdrStaticRangeLabel { - padding: 10px 10px; - } - .rdrMonth { - width: -moz-available; - } - `}</style> + .rdrCalendarWrapper{display:flex;flex-direction:column;} + .rdrDateRangePickerWrapper{display:flex;flex-direction:column;} + .rdrDefinedRangesWrapper{order:-1;width:fit-content;} + .rdrStaticRanges{flex-direction:row;margin-right:2px;} + .rdrInputRanges{display:none !important;} + .rdrStaticRangeLabel{padding:10px 10px;} + .rdrMonth{width:-moz-available;} + `}</style> <div className='flex flex-row justify-end gap-3 mt-2'> <button className='px-4 py-1 bg-red-500 text-white rounded' @@ -1162,6 +990,7 @@ const Transactions = ({ context = '' }) => { </div> </div> </div> + <div className='flex justify-center items-center'> {!transactions.isLoading && transactions?.data?.saleOrders?.length == 0 && ( @@ -1199,11 +1028,9 @@ const Transactions = ({ context = '' }) => { <p className='text-red-500'>{saleOrder.name}</p> <p className='text-black'> Salesperson:{' '} - { - <span className='font-semibold'> - {saleOrder.sales} - </span> - } + <span className='font-semibold'> + {saleOrder.sales} + </span> </p> </div> <div className='text-black'> @@ -1215,7 +1042,9 @@ const Transactions = ({ context = '' }) => { </span> </div> </div> + <hr className='mt-3 mb-3 border border-gray-100' /> + <div className='flex flex-row gap-2 justify-between items-center '> <div className='flex justify-start w-3/4 flex-col gap-2'> <div className='flex gap-2'> @@ -1250,9 +1079,9 @@ const Transactions = ({ context = '' }) => { <div className='flex flex-row gap-1 justify-start items-center'> {saleOrder.products .slice(1, 4) - .map((product, index) => ( + .map((product, idx) => ( <Image - key={index} // Tambahkan key untuk setiap elemen dalam map() + key={idx} src={product?.parent?.image} alt={product?.name} className='object-contain object-center border border-gray_r-6 h-16 w-16 rounded-md' @@ -1288,7 +1117,9 @@ const Transactions = ({ context = '' }) => { </p> </div> </div> + <div className='w-[1px] h-24 bg-gray-300'></div> + <div className='w-1/4 flex flex-col gap-2 items-end justify-center'> <div className='flex flex-col text-black w-full'> <p>Total Harga</p> @@ -1309,16 +1140,22 @@ const Transactions = ({ context = '' }) => { Beli Lagi </button> - <button - type='button' - onClick={(e) => { - e.preventDefault(); - e.stopPropagation(); - }} - className='w-full py-2 btn-light text-nowrap border border-red-500 text-red-500 rounded-md' - > - Lanjutkan Transaksi - </button> + {saleOrder?.eligibleContinue && ( + <button + type='button' + disabled={contLoadingId === saleOrder.id} + onClick={(e) => { + e.preventDefault(); + e.stopPropagation(); + handleContinuePayment(saleOrder); + }} + className='w-full py-2 btn-light text-nowrap border border-red-500 text-red-500 rounded-md disabled:opacity-60' + > + {contLoadingId === saleOrder.id + ? 'Memproses…' + : 'Lanjutkan Transaksi'} + </button> + )} </div> </div> </Link> @@ -1327,70 +1164,10 @@ const Transactions = ({ context = '' }) => { </div> )} </div> - {/* <table className='table-data'> - <thead> - <tr> - <th>No. Transaksi</th> - <th>No. PO</th> - <th>Tanggal</th> - <th>Created By</th> - {auth?.feature?.soApproval && <th>Site</th>} - <th className='!text-left'>Salesperson</th> - <th className='!text-left'>Total</th> - <th>Status</th> - </tr> - </thead> - <tbody> - {transactions.isLoading && ( - <tr> - <td colSpan={7}> - <div className='flex justify-center my-2'> - <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> - </div> - </td> - </tr> - )} - {!transactions.isLoading && - (!transactions?.data?.saleOrders || - transactions?.data?.saleOrders?.length == 0) && ( - <tr> - <td colSpan={7}>Tidak ada transaksi</td> - </tr> - )} - {transactions.data?.saleOrders?.map((saleOrder) => ( - <tr key={saleOrder.id}> - <td> - <Link - className='whitespace-nowrap' - href={`${router.pathname}/${saleOrder.id}`} - > - {saleOrder.name} - </Link> - </td> - <td>{saleOrder.purchaseOrderName || '-'}</td> - <td>{saleOrder.dateOrder || '-'}</td> - <td>{saleOrder.address.customer?.name || '-'}</td> - {auth?.feature?.soApproval && ( - <td>{saleOrder.sitePartner || '-'}</td> - )} - <td className='!text-left'>{saleOrder.sales}</td> - <td className='!text-left'> - {currencyFormat(saleOrder.amountTotal)} - </td> - <td> - <div className='flex justify-center'> - <TransactionStatusBadge status={saleOrder.status} /> - </div> - </td> - </tr> - ))} - </tbody> - </table> */} <Pagination pageCount={pageCount} currentPage={parseInt(pageNew)} - // url={router.pathname + (pageQuery ? `?${pageQuery}` : '')} url={`${router.pathname}?${toQuery(_.omit(query, ['page']))}`} className='mt-2 mb-2' /> |
