diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2024-11-13 16:46:14 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2024-11-13 16:46:14 +0700 |
| commit | 9622bff4d4902fcef81214236cc7ff035163e5e7 (patch) | |
| tree | 666a57d246533aa2b9f547ef306d1293adc5efad /src/lib/tempo/components | |
| parent | c873a401f0ea13e1881278e7977d4013d3a87394 (diff) | |
<iman> pengajuan tempo
Diffstat (limited to 'src/lib/tempo/components')
| -rw-r--r-- | src/lib/tempo/components/Tempo.jsx | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/src/lib/tempo/components/Tempo.jsx b/src/lib/tempo/components/Tempo.jsx new file mode 100644 index 00000000..9b68251c --- /dev/null +++ b/src/lib/tempo/components/Tempo.jsx @@ -0,0 +1,277 @@ +import { + CheckIcon, + ClockIcon, + EllipsisVerticalIcon, + MagnifyingGlassIcon, +} from '@heroicons/react/24/outline'; +import { toQuery } from 'lodash-contrib'; +import _ from 'lodash'; +import { useRouter } from 'next/router'; +import { useState } from 'react'; +import useInvoices from '../hooks/useInvoices'; +import Spinner from '@/core/components/elements/Spinner/Spinner'; +import Alert from '@/core/components/elements/Alert/Alert'; +import Pagination from '@/core/components/elements/Pagination/Pagination'; +import Link from '@/core/components/elements/Link/Link'; +import currencyFormat from '@/core/utils/currencyFormat'; +import BottomPopup from '@/core/components/elements/Popup/BottomPopup'; +import { downloadInvoice, downloadTaxInvoice } from '../utils/invoices'; +import MobileView from '@/core/components/views/MobileView'; +import DesktopView from '@/core/components/views/DesktopView'; +import Menu from '@/lib/auth/components/Menu'; + +const Tempo = () => { + const router = useRouter(); + const { q = '', page = 1 } = router.query; + + const limit = 15; + + const query = { + name: q, + offset: (page - 1) * limit, + limit, + }; + const { invoices } = useInvoices({ query }); + + const [inputQuery, setInputQuery] = useState(q); + const [toOthers, setToOthers] = useState(null); + + const pageCount = Math.ceil(invoices?.data?.invoiceTotal / limit); + let pageQuery = _.omit(query, ['limit', 'offset']); + pageQuery = _.pickBy(pageQuery, _.identity); + pageQuery = toQuery(pageQuery); + + const handleSubmit = (e) => { + e.preventDefault(); + router.push(`/my/invoices?q=${inputQuery}`); + }; + + return ( + <> + <MobileView> + <div className='p-4 flex flex-col gap-y-4'> + <form className='flex gap-x-3' onSubmit={handleSubmit}> + <input + type='text' + className='form-input' + placeholder='Cari Invoice...' + value={inputQuery} + onChange={(e) => setInputQuery(e.target.value)} + /> + <button className='btn-light bg-transparent px-3' type='submit'> + <MagnifyingGlassIcon className='w-6' /> + </button> + </form> + + {invoices.isLoading && ( + <div className='flex justify-center my-4'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> + </div> + )} + + {!invoices.isLoading && invoices.data?.invoices?.length === 0 && ( + <Alert type='info' className='text-center'> + Tidak ada invoice + </Alert> + )} + + {invoices.data?.invoices?.map((invoice, index) => ( + <div + className='p-4 shadow border border-gray_r-3 rounded-md' + key={index} + > + <div className='grid grid-cols-2'> + <Link href={`${router.pathname}/${invoice.id}`}> + <span className='text-caption-2 text-gray_r-11'> + No. Invoice + </span> + <h2 className='text-danger-500 mt-1'>{invoice.name}</h2> + </Link> + <div className='flex gap-x-1 justify-end'> + {invoice.amountResidual > 0 ? ( + <div className='badge-solid-red h-fit ml-auto'> + Belum Lunas + </div> + ) : ( + <div className='badge-solid-green h-fit ml-auto'>Lunas</div> + )} + <EllipsisVerticalIcon + className='w-5 h-5' + onClick={() => setToOthers(invoice)} + /> + </div> + </div> + <Link href={`${router.pathname}/${invoice.id}`}> + <div className='grid grid-cols-2 text-caption-2 text-gray_r-11 mt-2 font-normal'> + <p>{invoice.invoiceDate}</p> + <p className='text-right'>{invoice.paymentTerm}</p> + </div> + <hr className='my-3' /> + <div className='grid grid-cols-2'> + <div> + <span className='text-caption-2 text-gray_r-11'> + No. Purchase Order + </span> + <p className='mt-1 font-medium text-gray_r-12'> + {invoice.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'> + {currencyFormat(invoice.amountTotal)} + </p> + </div> + </div> + </Link> + {invoice.efaktur ? ( + <div className='badge-green h-fit mt-3 ml-auto flex items-center gap-x-0.5'> + <CheckIcon className='w-4 stroke-2' /> + Faktur Pajak + </div> + ) : ( + <div className='badge-red h-fit mt-3 ml-auto flex items-center gap-x-0.5'> + <ClockIcon className='w-4 stroke-2' /> + Faktur Pajak + </div> + )} + </div> + ))} + + <Pagination + pageCount={pageCount} + currentPage={parseInt(page)} + url={`/my/invoices${pageQuery}`} + className='mt-2 mb-2' + /> + + <BottomPopup + title='Lainnya' + active={toOthers} + close={() => setToOthers(null)} + > + <div className='flex flex-col gap-y-4 mt-2'> + <button + className='text-left disabled:opacity-60' + onClick={() => { + downloadInvoice(toOthers); + setToOthers(null); + }} + > + Download Invoice + </button> + <button + className='text-left disabled:opacity-60' + disabled={!toOthers?.efaktur} + onClick={() => { + downloadTaxInvoice(toOthers); + setToOthers(null); + }} + > + Download Faktur Pajak + </button> + </div> + </BottomPopup> + </div> + </MobileView> + + <DesktopView> + <div className='container mx-auto flex py-10'> + <div className='w-3/12 pr-4'> + <Menu /> + </div> + <div className='w-9/12 p-4 bg-white border border-gray_r-6 rounded'> + <div className='flex mb-6 items-center justify-between'> + <h1 className='text-title-sm font-semibold'> + Invoice & Faktur Pajak{' '} + {invoices?.data?.invoices + ? `(${invoices?.data?.invoices.length})` + : ''} + </h1> + <form className='flex gap-x-2' onSubmit={handleSubmit}> + <input + type='text' + className='form-input' + placeholder='Cari Invoice...' + value={inputQuery} + onChange={(e) => setInputQuery(e.target.value)} + /> + <button className='btn-light bg-transparent px-3' type='submit'> + <MagnifyingGlassIcon className='w-6' /> + </button> + </form> + </div> + + <table className='table-data'> + <thead> + <tr> + <th>No. Invoice</th> + <th>No. PO</th> + <th>Tanggal</th> + <th className='!text-left'>Salesperson</th> + <th>Status</th> + <th className='!text-left'>Total</th> + </tr> + </thead> + <tbody> + {invoices.isLoading && ( + <tr> + <td colSpan={6}> + <div className='flex justify-center my-2'> + <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' /> + </div> + </td> + </tr> + )} + {!invoices.isLoading && + (!invoices?.data?.invoices || + invoices?.data?.invoices?.length == 0) && ( + <tr> + <td colSpan={6}>Tidak ada invoice</td> + </tr> + )} + {invoices.data?.invoices?.map((invoice) => ( + <tr key={invoice.id}> + <td> + <Link href={`${router.pathname}/${invoice.id}`}> + {invoice.name} + </Link> + </td> + <td>{invoice.purchaseOrderName || '-'}</td> + <td>{invoice.invoiceDate}</td> + <td className='!text-left'>{invoice.sales}</td> + <td> + {invoice.amountResidual > 0 ? ( + <div className='badge-solid-red h-fit mx-auto'> + Belum Lunas + </div> + ) : ( + <div className='badge-solid-green h-fit mx-auto'> + Lunas + </div> + )} + </td> + <td className='!text-left'> + {currencyFormat(invoice.amountTotal)} + </td> + </tr> + ))} + </tbody> + </table> + + <Pagination + pageCount={pageCount} + currentPage={parseInt(page)} + url={`/my/invoices${pageQuery}`} + className='mt-2 mb-2' + /> + </div> + </div> + </DesktopView> + </> + ); +}; + +export default Tempo; |
